/*
 * ringbuffer.h: A ring buffer
 *
 * See the main source file 'vdr.c' for copyright information and
 * how to reach the author.
 *
 * $Id: ringbuff.h,v 1.1 2005/02/12 19:18:17 dom Exp $
 */

#ifndef __RINGBUFF_H
#define __RINGBUFF_H

#include <vdr/thread.h>
#include <vdr/tools.h>

class cRingBuff {
private:
  cMutex mutex;
  cCondVar readyForPut, readyForGet;
  cMutex putMutex, getMutex;
  int putTimeout;
  int getTimeout;
  int size;
  time_t lastOverflowReport;
  int overflowCount;
  int overflowBytes;
protected:
  int maxFill;//XXX
  int lastPercent;
  bool statistics;//XXX
  void WaitForPut(void);
  void WaitForGet(void);
  void EnablePut(void);
  void EnableGet(void);
  virtual void Clear(void) = 0;
  virtual int Available(void) = 0;
  int Free(void) { return size - Available() - 1; }
  void Lock(void) { mutex.Lock(); }
  void Unlock(void) { mutex.Unlock(); }
  int Size(void) { return size; }
public:
  cRingBuff(int Size, bool Statistics = false);
  virtual ~cRingBuff();
  void SetTimeouts(int PutTimeout, int GetTimeout);
  void ReportOverflow(int Bytes);
  };

class cRingBuffLinear : public cRingBuff {
private:
  int margin, head, tail;
  int lastGet;
  uchar *buffer;
  pthread_t getThreadTid;
public:
  cRingBuffLinear(int Size, int Margin = 0, bool Statistics = false);
    ///< Creates a linear ring buffer.
    ///< The buffer will be able to hold at most Size bytes of data, and will
    ///< be guaranteed to return at least Margin bytes in one consecutive block.
  virtual ~cRingBuffLinear();
  virtual int Available(void);
  virtual void Clear(void);
    ///< Immediately clears the ring buffer.
  int Put(const uchar *Data, int Count);
    ///< Puts at most Count bytes of Data into the ring buffer.
    ///< \return Returns the number of bytes actually stored.
  uchar *Get(int &Count);
    ///< Gets data from the ring buffer.
    ///< The data will remain in the buffer until a call to Del() deletes it.
    ///< \return Returns a pointer to the data, and stores the number of bytes
    ///< actually retrieved in Count. If the returned pointer is NULL, Count has no meaning.
  void Del(int Count);
    ///< Deletes at most Count bytes from the ring buffer.
    ///< Count must be less or equal to the number that was returned by a previous
    ///< call to Get().
  };


#endif // __RINGBUFF_H
