34template<
typename T,
size_t Size>
36 static_assert((Size & (Size - 1)) == 0,
"Size must be a power of 2");
37 static_assert(Size > 1,
"Size must be greater than 1");
47 for (
size_t i = 0; i < Size; ++i) {
48 cells_[i].sequence.store(i, std::memory_order_relaxed);
86 const size_t pos =
tail_.load(std::memory_order_relaxed);
89 const size_t seq =
cell.
sequence.load(std::memory_order_acquire);
90 const size_t expected_seq = pos + 1;
92 if (seq != expected_seq) {
98 tail_.store(pos + 1, std::memory_order_relaxed);
108 const size_t head_pos =
head_.load(std::memory_order_acquire);
109 const size_t tail_pos =
tail_.load(std::memory_order_acquire);
110 return head_pos == tail_pos;
118 const size_t head_pos =
head_.load(std::memory_order_acquire);
119 const size_t tail_pos =
tail_.load(std::memory_order_acquire);
120 return ((head_pos + 1) &
mask_) == (tail_pos &
mask_);
128 const size_t head_pos =
head_.load(std::memory_order_acquire);
129 const size_t tail_pos =
tail_.load(std::memory_order_acquire);
130 return head_pos - tail_pos;
142 static constexpr size_t mask_ = Size - 1;
152 struct alignas(cache_line_size)
cell {
167 const size_t pos = head_.load(std::memory_order_relaxed);
168 auto&
cell = cells_[pos & mask_];
170 const size_t seq =
cell.
sequence.load(std::memory_order_acquire);
171 const size_t expected_seq = pos;
173 if (seq != expected_seq) {
178 cell.
sequence.store(pos + 1, std::memory_order_release);
179 head_.store(pos + 1, std::memory_order_relaxed);
185 alignas(cache_line_size) std::atomic<size_t> head_;
186 alignas(cache_line_size) std::atomic<size_t> tail_;
187 alignas(cache_line_size) std::array<cell, Size> cells_;
196template<
typename T,
size_t Size = 1024>
198 return std::make_unique<lockfree_spsc_queue<T, Size>>();
207template<
typename T,
size_t Size>
210 static_assert(
sizeof(T) == 0,
"MPMC queue not yet implemented");
Multi-producer multi-consumer lock-free queue (for future use)
Lock-free single-producer single-consumer queue.
std::atomic< size_t > head_
bool empty() const
Check if queue is empty.
std::atomic< size_t > tail_
static constexpr size_t mask_
bool enqueue(T &&item)
Enqueue an item using move semantics (producer side)
size_t size() const
Get approximate queue size.
bool enqueue(const T &item)
Enqueue an item (producer side)
std::array< cell, Size > cells_
static constexpr size_t cache_line_size
Cache line size for padding.
lockfree_spsc_queue()
Constructor.
bool dequeue(T &item)
Dequeue an item (consumer side)
bool full() const
Check if queue is full.
constexpr size_t capacity() const
Get queue capacity.
~lockfree_spsc_queue()
Destructor.
bool enqueue_impl(U &&item)
Implementation for enqueue operations.
std::unique_ptr< lockfree_spsc_queue< T, Size > > make_lockfree_queue()
Factory function to create a lock-free queue.
Cell structure with sequence number for ABA prevention.
std::atomic< size_t > sequence