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