#pragma once #include /** * A simple ring buffer. * Template arguments are for numeric type stored, and for size. * Not thread safe. * Guaranteed to be non-blocking. Adding or removing items will never * allocate or free memory. * Objects in RingBuffer are not owned by RingBuffer - they will not be destroyed. */ template class RingBuffer { public: RingBuffer() { for (int i = 0; i < SIZE; ++i) { memory[i] = 0; } } void push(T); T pop(); bool full() const; bool empty() const; private: T memory[SIZE]; bool couldBeFull = false; // full and empty are ambiguous, both are in--out int inIndex = 0; int outIndex = 0; /** Move up 'p' (a buffer index), wrap around if we hit the end * (this is the core of the circular ring buffer). */ void advance(int &p); }; template inline void RingBuffer::push(T value) { assert(!full()); memory[inIndex] = value; advance(inIndex); couldBeFull = true; } template inline T RingBuffer::pop() { assert(!empty()); T value = memory[outIndex]; advance(outIndex); couldBeFull = false; return value; } template inline bool RingBuffer::full() const { return (inIndex == outIndex) && couldBeFull; } template inline bool RingBuffer::empty() const { return (inIndex == outIndex) && !couldBeFull; } template inline void RingBuffer::advance(int &p) { if (++p >= SIZE) p = 0; }