63 static constexpr bool default_to_weak =
71 cells(
new cell[size]),
74 assert(size >= 2 && utils::is_power_of_two(size));
75 for (std::size_t
i = 0;
i < size; ++
i)
76 cells[
i].sequence.store(
i, std::memory_order_relaxed);
77 enqueue_pos.store(0, std::memory_order_relaxed);
78 dequeue_pos.store(0, std::memory_order_relaxed);
99 template <
class...
Args>
121 template <
class...
Args>
143 template <
class...
Args>
197 std::size_t
pos = enqueue_pos.load(std::memory_order_relaxed);
199 c = &cells[
pos & index_mask];
201 std::size_t
seq =
c->sequence.load(std::memory_order_acquire);
203 if (enqueue_pos.compare_exchange_weak(
pos,
pos + 1, std::memory_order_relaxed))
210 pos = enqueue_pos.load(std::memory_order_relaxed);
212 auto pos2 = enqueue_pos.load(std::memory_order_relaxed);
213 if (pos2 == pos && dequeue_pos.load(std::memory_order_relaxed) + index_mask + 1 == pos)
219 assign_value(c->value, std::forward<Args>(args)...);
221 c->sequence.store(pos + 1, std::memory_order_release);
226 bool do_try_pop(T& result) {
228 std::size_t pos = dequeue_pos.load(std::memory_order_relaxed);
230 c = &cells[pos & index_mask];
232 std::size_t seq = c->sequence.load(std::memory_order_acquire);
233 auto new_pos = pos + 1;
234 if (seq == new_pos) {
235 if (dequeue_pos.compare_exchange_weak(pos, new_pos, std::memory_order_relaxed))
241 pos = dequeue_pos.load(std::memory_order_relaxed);
243 auto pos2 = dequeue_pos.load(std::memory_order_relaxed);
244 if (pos2 == pos && enqueue_pos.load(std::memory_order_relaxed) == pos)
250 result = std::move(c->value);
252 c->sequence.store(pos + index_mask + 1, std::memory_order_release);
256 void assign_value(T& v,
const T& source) { v = source; }
257 void assign_value(T& v, T&& source) { v = std::move(source); }
258 template <
class... Args>
259 void assign_value(T& v, Args&&... args) { v = T{std::forward<Args>(args)...}; }
263 std::atomic<std::size_t> sequence;
267 std::unique_ptr<cell[]> cells;
268 const std::size_t index_mask;
269 alignas(64) std::atomic<size_t> enqueue_pos;
270 alignas(64) std::atomic<size_t> dequeue_pos;