(cc'ing Tim, the author, as well)

As an after thought, maybe I should directly be using / subclassing ringbuffer_base?  While that won't allow me to move the read head forward without actually reading, it would allow me to check how much space was available before the first push.

cheers,
Rich


On Fri, May 10, 2013 at 1:16 PM, Rich E <reakinator@gmail.com> wrote:
I'm using boost::lockfree::spsc_queue in an audio graph to allow audio input samples written from one thread to be read from another. This currently looks like:


#include <boost/lockfree/spsc_queue.hpp>

class RingBuffer {
public:
RingBuffer() : mLockFreeQueue( 0 ) {}

RingBuffer( size_t size ) : mLockFreeQueue( size + 1 ), mSize( size ) {}
~RingBuffer() {}

//! pushes to buffer, overwriting oldest samples
void write( const float *samples, size_t count ) {
if( count > mSize ) {
count = mSize;
}
size_t numPushed = mLockFreeQueue.push( samples, count );
if( count > numPushed ) {
size_t numLeft = count - numPushed;
// ???: is there a more efficient way to overwrite?
float old;
for( int i = 0; i < numLeft; i++ ) {
mLockFreeQueue.pop( old );
}
numPushed = mLockFreeQueue.push( &samples[numPushed], numLeft );
assert( numPushed == numLeft );
}
}

size_t read( float *samples, size_t count ) {
if( count > mSize ) {
count = mSize;
}
return mLockFreeQueue.pop( samples, count );
}

private:
boost::lockfree::spsc_queue<float> mLockFreeQueue;
size_t mSize;
};


If there is not enough space in the write call, I sequentially pop off elements until there is enough.  Is there a better way to do this?  It seems like there should be a mechanism for just moving the read head forward (atomically) without reading anything, but then I am not sure I completely understand the implications of that on the lockfree model.  I'm also not 100% sure this is adhering to the lockfree model, so please inform me if/how it isn't if you know.

Thank you for your time,
Rich