template<typename T>
class interlocked_circle_buffer
{
protected:
enum cell_status_enum
{
cell_Free = 0,
cell_Filling,
cell_Full,
cell_Reading,
cell_Read
};
struct cell_struct {
volatile long status;
T data;
cell_struct(): status(cell_Free){}
};
public:
interlocked_circle_buffer(size_t size) :
m_size(size),
m_buffer(new cell_struct[size]),
m_writing(0),
m_reading(0),
m_read(0)
{}
~interlocked_circle_buffer(){delete [] m_buffer;}
bool push(const T& value)
{
long write;
bool searching = true;
while (searching)
{
write = m_writing;
long cellStatus = InterlockedCompareExchange(&m_buffer[write].status, cell_Filling, cell_Free);
switch (cellStatus)
{
case cell_Free:
searching = false;
case cell_Filling:
InterlockedCompareExchange(&m_writing, (write+1) % m_size, write);
break;
default:
return false;
}
}
m_buffer[write].data = value;
m_buffer[write].status = cell_Full;
return true;
}
bool pop(T * target)
{
long read;
bool searching = true;
while (searching)
{
read = m_reading;
long cellStatus = InterlockedCompareExchange(&m_buffer[read].status, cell_Reading, cell_Full);
switch (cellStatus)
{
case cell_Full:
searching = false;
case cell_Reading:
case cell_Read:
InterlockedCompareExchange(&m_reading, (read+1) % m_size, read);
break;
default:
return false;
}
}
*target = m_buffer[read].data;
m_buffer[read].status = cell_Read;
if (InterlockedCompareExchange(&m_read, (read+1) % m_size, read) == read)
{
while (InterlockedCompareExchange(&m_buffer[read].status, cell_Free, cell_Read) == cell_Read)
{
if (InterlockedCompareExchange(&m_read, (read+1) % m_size, read) != read)
break;
read = (read+1) % m_size;
}
}
return true;
}
protected: // member fields
cell_struct * m_buffer;
size_t m_size;
volatile long m_writing, m_reading, m_read;
};