#pragma once #include #include template class RingBuffer { public: using UnitType = T; constexpr explicit RingBuffer(UnitType* buffer, size_t buffer_size) : _buffer_size(buffer_size), _buffer(buffer) { assert(buffer_size); assert(buffer); } constexpr void Push(UnitType item) { _buffer[_head] = item; _head = (_head + 1) % _buffer_size; } constexpr void Push(const UnitType *items, size_t nitems) { if (items) for (; nitems; items++, nitems--) Push(*items); } constexpr UnitType Pop() { const auto item = _buffer[_tail]; _tail = (_tail + 1) % _buffer_size; return item; } constexpr void Pop(UnitType* buf, size_t nitems) { if (buf) for (; nitems; nitems--, buf++) *buf = Pop(); } constexpr size_t Free() { return Size() - Occupied(); } constexpr size_t Occupied() { return _head - _tail + (_head >= _tail) ? 0 : _buffer_size; } constexpr bool IsEmpty() { return _head == _tail; } constexpr bool IsFull() { return _tail + 1 == _head; } constexpr size_t Size() { return _buffer_size - 1; } private: size_t _buffer_size{}; UnitType *_buffer{}; size_t _head{}, _tail{}; };