2#ifndef LIBSBX_CONTAINERS_SPSC_QUEUE_HPP_
3#define LIBSBX_CONTAINERS_SPSC_QUEUE_HPP_
7#include <libsbx/utility/fast_mod.hpp>
9#include <libsbx/memory/cache.hpp>
11namespace sbx::containers {
13template<
typename Type, std::
size_t Capacity>
26 bool push(
const Type& value) {
27 const auto head = _head.load(std::memory_order_relaxed);
28 const auto next = increment(head);
30 if (next == _tail.load(std::memory_order_acquire)) {
34 auto* slot = _slot(head);
35 std::construct_at(slot, value);
37 _head.store(next, std::memory_order_release);
43 const auto tail = _tail.load(std::memory_order_relaxed);
45 if (tail == _head.load(std::memory_order_acquire)) {
49 auto* element = _slot(tail);
50 out = std::move(*element);
51 std::destroy_at(element);
53 _tail.store(increment(tail), std::memory_order_release);
60 static constexpr auto increment(
const std::size_t i) -> std::size_t {
61 return utility::fast_mod(i + 1, Capacity);
64 auto _slot(
const std::size_t index)
noexcept -> Type* {
65 return std::launder(
reinterpret_cast<Type*
>(_buffer.data()) + index);
68 auto _slot(
const std::size_t index)
const noexcept ->
const Type* {
69 return std::launder(
reinterpret_cast<const Type*
>(_buffer.data()) + index);
72 alignas(memory::cacheline::size) std::atomic<std::size_t> _head{0};
73 alignas(memory::cacheline::size) std::atomic<std::size_t> _tail{0};
74 alignas(Type) std::array<std::byte, Capacity *
sizeof(Type)> _buffer{};
Definition: spsc_queue.hpp:14