40template<
typename T,
size_t Size>
42 static_assert((Size & (Size - 1)) == 0,
"Size must be a power of 2");
43 static_assert(Size > 1,
"Size must be greater than 1");
53 for (
size_t i = 0; i < Size; ++i) {
54 cells_[i].sequence.store(i, std::memory_order_relaxed);
92 const size_t pos =
tail_.load(std::memory_order_relaxed);
95 const size_t seq =
cell.
sequence.load(std::memory_order_acquire);
96 const size_t expected_seq = pos + 1;
98 if (seq != expected_seq) {
104 tail_.store(pos + 1, std::memory_order_relaxed);
114 const size_t head_pos =
head_.load(std::memory_order_acquire);
115 const size_t tail_pos =
tail_.load(std::memory_order_acquire);
116 return head_pos == tail_pos;
124 const size_t head_pos =
head_.load(std::memory_order_acquire);
125 const size_t tail_pos =
tail_.load(std::memory_order_acquire);
126 return ((head_pos + 1) &
mask_) == (tail_pos &
mask_);
134 const size_t head_pos =
head_.load(std::memory_order_acquire);
135 const size_t tail_pos =
tail_.load(std::memory_order_acquire);
136 return head_pos - tail_pos;
148 static constexpr size_t mask_ = Size - 1;
158 struct alignas(cache_line_size)
cell {
173 const size_t pos = head_.load(std::memory_order_relaxed);
174 auto&
cell = cells_[pos & mask_];
176 const size_t seq =
cell.
sequence.load(std::memory_order_acquire);
177 const size_t expected_seq = pos;
179 if (seq != expected_seq) {
184 cell.
sequence.store(pos + 1, std::memory_order_release);
185 head_.store(pos + 1, std::memory_order_relaxed);
191 alignas(cache_line_size) std::atomic<size_t> head_;
192 alignas(cache_line_size) std::atomic<size_t> tail_;
193 alignas(cache_line_size) std::array<cell, Size> cells_;
202template<
typename T,
size_t Size = 1024>
204 return std::make_unique<lockfree_spsc_queue<T, Size>>();
213template<
typename T,
size_t Size>
216 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