#pragma once #include #include template class CircularQueue { enum { Capacity = Size + 1 }; public: CircularQueue() { } bool try_push(const T& value) { usize current_tail = m_tail.load(MemoryOrder::Relaxed); const usize new_tail = (current_tail + 1) % Capacity; if (new_tail == m_head.load(MemoryOrder::Acquire)) { // Queue is full return false; } m_data[current_tail] = value; if (!m_tail.compare_exchange_strong(current_tail, new_tail, MemoryOrder::Release, MemoryOrder::Relaxed)) { // Someone else updated the tail return false; } return true; } bool try_pop(T& value) { usize current_head = m_head.load(MemoryOrder::Relaxed); if (current_head == m_tail.load(MemoryOrder::Acquire)) { // Queue is empty return false; } value = m_data[current_head]; const usize new_head = (current_head + 1) % Capacity; if (!m_head.compare_exchange_strong(current_head, new_head, MemoryOrder::Release, MemoryOrder::Relaxed)) { // Someone else updated the head return false; } return true; } private: T m_data[Capacity]; Atomic m_head = 0; Atomic m_tail = 0; };