// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Templatized, thread-safe RingBuffer.  Acts like a FIFO, but using a
// fixed-size buffer that wraps around and optimized for operations that
// read or write many elements at a time.  Commonly used to buffer audio
// samples that need to be passed from one thread to another.
//
// Supports a flag "finished" so the writing thread can notify the reading
// thread that there's no more data.
//
// The implementation is all contained within this .h file because
// it's templatized.

#ifndef SPEECH_CLIENT_SYNTHESIS_SERVICE_RINGBUFFER_H_
#define SPEECH_CLIENT_SYNTHESIS_SERVICE_RINGBUFFER_H_

#include "threading.h"

namespace speech_synthesis {

template<typename T> class RingBuffer {
 public:
  // Construct a RingBuffer using a given Threading object (used for
  // locking - may not be NULL) of a given capacity (cannot be increased
  // later).
  explicit RingBuffer(int capacity);

  // Destructor.
  ~RingBuffer();

  //
  // Methods for either thread
  //

  int GetCapacity() { return buffer_.size(); }

  //
  // Methods for the writer thread
  //

  // Reset to the initial state: the ring buffer is empty and marked as
  // unfinished.
  void Reset();

  // Get the number of items of type T that are available to be written.
  // This will be a number between 0 and capacity, inclusive.
  int WriteAvail();

  // Write *len* elements to the end of the ring buffer.  Returns true on
  // success.  If all *len* elements cannot be written without blocking,
  // returns false and writes nothing.
  bool Write(const T* data, int len);

  // Mark the buffer as finished.  Future write operations will fail.
  // Read operations will succeed until the buffer is empty, but
  // IsFinished() will return true immediately.
  void MarkFinished();

  //
  // Methods for the reader thread
  //

  // Get the number of items of type T that are available to be read.
  // This will be a number between 0 and capacity, inclusive.
  int ReadAvail();

  // Read *len* elements from the front of the ring buffer.  Returns true on
  // success.  If all *len* elements cannot be read without blocking,
  // returns false and reads nothing.
  bool Read(T* data, int len);

  // Returns true if the buffer has been marked as finished by a call to
  // MarkFinished, whether the buffer is empty or not.
  bool IsFinished();

 private:
  scoped_ptr<Mutex> mutex_;
  std::vector<T> buffer_;
  bool finished_;
  volatile int read_pos_;
  volatile int write_pos_;

  DISALLOW_COPY_AND_ASSIGN(RingBuffer);
};

//
// Implementation notes:
//
// We use a simple mutex to protect all of the fields.
//
// A special value of -1 is used for read_pos_ to indicate that the buffer
// is empty, otherwise there would be no way to distinguish between an empty
// buffer and a full buffer when read_pos_ == write_pos_.
//

template<typename T> RingBuffer<T>::RingBuffer(int capacity)
    : mutex_(Mutex::Create()),
      buffer_(capacity),
      finished_(false),
      read_pos_(0),
      write_pos_(0) {
  Reset();
}

template<typename T> RingBuffer<T>::~RingBuffer() {
}

template<typename T> void RingBuffer<T>::Reset() {
  mutex_->Lock();
  finished_ = false;
  read_pos_ = -1;
  write_pos_ = 0;
  mutex_->Unlock();
};

template<typename T> int RingBuffer<T>::WriteAvail() {
  int avail = GetCapacity();
  mutex_->Lock();
  if (read_pos_ != -1) {
    avail = read_pos_ - write_pos_;
  }
  mutex_->Unlock();
  if (avail < 0) {
    avail += GetCapacity();
  }
  return avail;
}

template<typename T> bool RingBuffer<T>::Write(const T* data, int len) {
  mutex_->Lock();
  if (finished_) {
    mutex_->Unlock();
    return false;
  }
  int avail = GetCapacity();
  if (read_pos_ != -1) {
    avail = read_pos_ - write_pos_;
  }
  if (avail < 0) {
    avail += GetCapacity();
  }
  if (len > avail) {
    mutex_->Unlock();
    return false;
  }

  if (read_pos_ == -1) {
    read_pos_ = write_pos_;
  }
  for (int i = 0; i < len; i++) {
    buffer_[write_pos_] = data[i];
    write_pos_ = (write_pos_ + 1) % GetCapacity();
  }
  mutex_->Unlock();

  return true;
}

template<typename T> void RingBuffer<T>::MarkFinished() {
  mutex_->Lock();
  finished_ = true;
  mutex_->Unlock();
}

template<typename T> int RingBuffer<T>::ReadAvail() {
  mutex_->Lock();
  if (read_pos_ == -1) {
    mutex_->Unlock();
    return 0;
  }
  int avail = write_pos_ - read_pos_;
  mutex_->Unlock();
  if (avail <= 0) {
    avail += GetCapacity();
  }
  return avail;
}

template<typename T> bool RingBuffer<T>::Read(T* data, int len) {
  mutex_->Lock();
  int avail;
  if (read_pos_ == -1) {
    avail = 0;
  } else {
    avail = write_pos_ - read_pos_;
    if (avail <= 0) {
      avail += GetCapacity();
    }
  }
  if (len > avail) {
    mutex_->Unlock();
    return false;
  }

  for (int i = 0; i < len; i++) {
    data[i] = buffer_[read_pos_];
    read_pos_ = (read_pos_ + 1) % GetCapacity();
  }

  if (read_pos_ == write_pos_) {
    read_pos_ = -1;
  }

  mutex_->Unlock();

  return true;
}

template<typename T> bool RingBuffer<T>::IsFinished() {
  mutex_->Lock();
  bool is_finished = finished_;
  mutex_->Unlock();
  return is_finished;
}

}  // namespace speech_synthesis

#endif  // SPEECH_CLIENT_SYNTHESIS_SERVICE
