#include #include #include template class RingBuffer { public: explicit RingBuffer(size_t capacity) : m_buffer(capacity), m_capacity(capacity) { } void push(const T& item) { std::lock_guard lock(m_mutex); m_buffer[m_head] = item; if (m_full) { m_tail = (m_tail + 1) % m_capacity; } m_head = (m_head + 1) % m_capacity; m_full = m_head == m_tail; } void push(T&& item) { std::lock_guard lock(m_mutex); m_buffer[m_head] = std::move(item); if (m_full) { m_tail = (m_tail + 1) % m_capacity; } m_head = (m_head + 1) % m_capacity; m_full = m_head == m_tail; } std::optional pop() { std::lock_guard lock(m_mutex); if (empty_locked()) { return std::nullopt; } T value = std::move(m_buffer[m_tail]); m_full = false; m_tail = (m_tail + 1) % m_capacity; return value; } std::optional peek() const { std::lock_guard lock(m_mutex); if (empty_locked()) { return std::nullopt; } return m_buffer[m_tail]; } std::vector drain() { std::lock_guard lock(m_mutex); std::vector out; size_t count = size_locked(); out.reserve(count); if (count == 0) { return out; } size_t idx = m_tail; for (size_t i = 0; i < count; ++i) { out.push_back(std::move(m_buffer[idx])); idx = (idx + 1) % m_capacity; } m_head = 0; m_tail = 0; m_full = false; return out; } std::vector peek_drain() { std::lock_guard lock(m_mutex); std::vector out; size_t count = size_locked(); out.reserve(count); if (count == 0) { return out; } size_t idx = m_tail; for (size_t i = 0; i < count; ++i) { out.push_back(m_buffer[idx]); idx = (idx + 1) % m_capacity; } return out; } void clear() { std::lock_guard lock(m_mutex); m_head = m_tail; m_full = false; } bool empty() const { std::lock_guard lock(m_mutex); return empty_locked(); } bool full() const { std::lock_guard lock(m_mutex); return m_full; } size_t size() const { std::lock_guard lock(m_mutex); return size_locked(); } size_t capacity() const { return m_capacity; } private: bool empty_locked() const { return (!m_full && (m_head == m_tail)); } size_t size_locked() const { if (m_full) return m_capacity; if (m_head >= m_tail) return m_head - m_tail; return m_capacity + m_head - m_tail; } private: std::vector m_buffer; const size_t m_capacity; size_t m_head = 0; size_t m_tail = 0; bool m_full = false; // mutable allows const functions to modify/lock the mutex mutable std::mutex m_mutex; };