Здравствуйте, Caracrist, Вы писали:
Нашел маленький oops
,
template<typename T>
class interlocked_circle_buffer
{
protected:
enum cell_status_enum
{
cell_Free = 0,
cell_Written,
cell_Full,
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(-1),
m_reading(-1),
m_read(0),
m_written(0),
m_filled(0),
m_filling(0)
{}
~interlocked_circle_buffer(){delete [] m_buffer;}
bool push(const T& value)
{
if (InterlockedIncrement(&m_filling) > m_size)
{
InterlockedDecrement(&m_filling);
return false;
}
long write = InterlockedIncrement(&m_writing) % m_size;
m_buffer[write].data = value;
m_buffer[write].status = cell_Written;
finalize_write();
return true;
}
bool pop(T * target)
{
if (InterlockedDecrement(&m_filled) < 0)
{
InterlockedIncrement(&m_filled);
return false;
}
long read = InterlockedIncrement(&m_reading) % m_size;
*target = m_buffer[read].data;
m_buffer[read].status = cell_Read;
finalize_read();
return true;
}
private:
void finalize_read()
{
while (true)
{
long read = InterlockedExchange(&m_read, -1);
if (read != -1)
//if (long read = InterlockedExchange(&m_read, -1) != -1) // oops
{
if (InterlockedCompareExchange(&m_buffer[read].status, cell_Free, cell_Read) == cell_Read)
{
m_read = (read + 1) % m_size;
InterlockedDecrement(&m_filling);
continue;
}
else
{
m_read = read;
if (InterlockedCompareExchange(&m_buffer[read].status, cell_Read, cell_Read) == cell_Read)
continue;
}
}
break;
}
if (m_reading > MAXLONG / 2)
InterlockedOperation(&m_reading, x % m_size);
}
void finalize_write()
{
while (true)
{
long write = InterlockedExchange(&m_written, -1);
if (write != -1)
//if (long write = InterlockedExchange(&m_written, -1) != -1) // oops
{
if (InterlockedCompareExchange(&m_buffer[write].status, cell_Full, cell_Written) == cell_Written)
{
m_written = (write + 1) % m_size;
InterlockedIncrement(&m_filled);
continue;
}
else
{
m_written = write;
if (InterlockedCompareExchange(&m_buffer[write].status, cell_Written, cell_Written) == cell_Written)
continue;
}
}
break;
}
if (m_writing > MAXLONG / 2)
InterlockedOperation(&m_writing, x % m_size);
}
protected: // member fields
cell_struct * m_buffer;
long m_size;
volatile long m_writing, m_reading
, m_written, m_read
, m_filling, m_filled;
};