You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/flow/bufferqueue.h

149 lines
3.1 KiB

/*
* BC - Status (2002-03-08): ByteBuffer, BufferQueue
*
* None of these classes is considered part of the public API. Do NOT use it
* in your apps. These are part of the implementation of libartsflow's
* AudioSubSystem, and subject to change/disappearing due to optimization
* work.
*/
#ifndef _BUFFERQUEUE_H
#define _BUFFERQUEUE_H
#include "thread.h"
#define _DEFAULT_CHUNK_SIZE 4096
#define _MAX_CHUNKS 3
namespace Arts
{
class ByteBuffer
{
unsigned char* content;
int _size;
int _maxSize;
int rp;
public:
ByteBuffer() {
_size = rp = 0;
_maxSize = _DEFAULT_CHUNK_SIZE;
content = new unsigned char[_DEFAULT_CHUNK_SIZE];
}
ByteBuffer(const void* s, int len) {
_maxSize = _DEFAULT_CHUNK_SIZE;
content = new unsigned char[_DEFAULT_CHUNK_SIZE];
put(s, len);
}
~ByteBuffer() { delete [] content; }
void put(const void* s, int len) {
if ((_size = len) != 0)
memcpy(content, s, len);
rp = 0;
}
void* get() { return content+rp; }
void* reset() { _size = 0; rp = 0; return content; }
int push(int len) { _size -= len; rp += len; return _size; }
void set(int len) { _size = len; rp = 0; }
int size() const { return _size; }
int maxSize() const { return _maxSize; }
void setMaxSize(int size) {
delete [] content;
content = new unsigned char[size];
_maxSize = size;
}
};
///////////////////////////////////////////////////////////////////////////////
class BufferQueue
{
private:
ByteBuffer bufs[_MAX_CHUNKS];
int rp;
int wp;
Arts::Semaphore* sema_produced;
Arts::Semaphore* sema_consumed;
void semaReinit() {
delete sema_consumed;
delete sema_produced;
sema_consumed = new Arts::Semaphore(0, _MAX_CHUNKS);
sema_produced = new Arts::Semaphore(0, 0);
}
public:
BufferQueue() {
rp = wp = 0;
sema_consumed = new Arts::Semaphore(0, _MAX_CHUNKS);
sema_produced = new Arts::Semaphore(0, 0);
}
~BufferQueue() {
delete sema_consumed;
delete sema_produced;
}
void write(void* data, int len);
ByteBuffer* waitConsumed();
void produced();
ByteBuffer* waitProduced();
void consumed();
bool isEmpty() const { return sema_produced->getValue() == 0; }
int bufferedChunks() const { return sema_produced->getValue(); }
int freeChunks() const { return sema_consumed->getValue(); }
int maxChunks() const { return _MAX_CHUNKS; }
int chunkSize() const { return bufs[0].maxSize(); }
void clear() { rp = wp = 0; semaReinit(); }
void setChunkSize(int size){
for (int i=0; i < maxChunks(); i++)
bufs[i].setMaxSize(size);
}
};
///////////////////////////////////////////////////////////////////////////////
inline void BufferQueue::write(void* data, int len)
{
sema_consumed->wait();
bufs[wp].put(data, len);
++wp %= _MAX_CHUNKS;
sema_produced->post();
}
inline ByteBuffer* BufferQueue::waitConsumed()
{
sema_consumed->wait();
return &bufs[wp];
}
inline void BufferQueue::produced()
{
++wp %= _MAX_CHUNKS;
sema_produced->post();
}
inline ByteBuffer* BufferQueue::waitProduced()
{
sema_produced->wait();
return &bufs[rp];
}
inline void BufferQueue::consumed()
{
++rp %=_MAX_CHUNKS;
sema_consumed->post();
}
}
#endif