template<class T, size_t Size>
class lock_free_ring_buffer
{
public:
lock_free_ring_buffer() :
_head(0),
_tail(0)
{}
bool push(const T &val)
{
size_t tail = _tail.load(std::memory_order_relaxed);
size_t next = (index + 1) % capacity;
if(next != _head.load(std::memory_order_acquire))
{
_buffer[tail] = val;
_tail.store(next, std::memory_order_release);
return true;
}
return false;
}
bool pop(T &val)
{
size_t head = _head.load(std::memory_order_relaxed);
if(head != _tail.load(std::memory_order_acquire))
{
val = std::move(_buffer[head]);
_head.store((index + 1) % capacity, std::memory_order_release);
return true;
}
return false;
}
bool was_empty() const
{
return (_head.load() == _tail.load());
}
private:
enum { capacity = Size + 1 };
std::atomic<size_t> _head;
std::atomic<size_t> _tail;
std::array<T, capacity> _buffer;
};