14template <
typename T,
size_t Capacity>
16 static_assert((Capacity & (Capacity - 1)) == 0,
"Capacity must be power of 2");
17 static_assert(std::is_trivially_copyable_v<T>,
"T must be trivially copyable");
32 const auto current_write =
m_write_index.load(std::memory_order_relaxed);
33 const auto next_write =
increment(current_write);
35 if (next_write ==
m_read_index.load(std::memory_order_acquire)) {
52 const auto current_read =
m_read_index.load(std::memory_order_relaxed);
54 if (current_read ==
m_write_index.load(std::memory_order_acquire)) {
69 [[nodiscard]]
bool empty() const noexcept
77 [[nodiscard]]
size_t size() const noexcept
79 const auto write =
m_write_index.load(std::memory_order_acquire);
80 const auto read =
m_read_index.load(std::memory_order_acquire);
81 return (write >= read) ? (write - read) : (Capacity - read + write);
93 static constexpr size_t increment(
size_t index)
noexcept
95 return (index + 1) & (Capacity - 1);
std::array< T, Capacity > m_buffer
bool empty() const noexcept
Check if buffer is empty.
static constexpr size_t increment(size_t index) noexcept
std::atomic< size_t > m_read_index
bool try_push(const T &item) noexcept
Attempt to write an element (wait-free)
std::optional< T > try_pop() noexcept
Attempt to read an element.
static constexpr size_t capacity() noexcept
Get buffer capacity.
std::atomic< size_t > m_write_index
size_t size() const noexcept
Get approximate size (may be stale)
Lock-free SPSC (Single Producer Single Consumer) ring buffer.