37 explicit Array(int64_t c) :
52 void push(int64_t i, O&& o) noexcept {
53 S[i & M].store(std::forward<O>(o), std::memory_order_relaxed);
56 T
pop(int64_t i) noexcept {
57 return S[i & M].load(std::memory_order_relaxed);
60 Array* resize(int64_t b, int64_t t) {
61 Array* ptr =
new Array {2*C};
62 for(int64_t i=t; i!=b; ++i) {
92 bool empty()
const noexcept;
97 size_t size()
const noexcept;
135 template <
typename T>
137 assert(c && (!(c & (c-1))));
138 _top.store(0, std::memory_order_relaxed);
139 _bottom.store(0, std::memory_order_relaxed);
140 _array.store(
new Array{c}, std::memory_order_relaxed);
141 _garbage.reserve(32);
145 template <
typename T>
147 for(
auto a : _garbage) {
150 delete _array.load();
154 template <
typename T>
156 int64_t b = _bottom.load(std::memory_order_relaxed);
157 int64_t t = _top.load(std::memory_order_relaxed);
162 template <
typename T>
164 int64_t b = _bottom.load(std::memory_order_relaxed);
165 int64_t t = _top.load(std::memory_order_relaxed);
166 return static_cast<size_t>(b >= t ? b - t : 0);
170 template <
typename T>
172 int64_t b = _bottom.load(std::memory_order_relaxed);
173 int64_t t = _top.load(std::memory_order_acquire);
174 Array* a = _array.load(std::memory_order_relaxed);
177 if(a->capacity() - 1 < (b - t)) {
178 Array* tmp = a->resize(b, t);
179 _garbage.push_back(a);
181 _array.store(a, std::memory_order_relaxed);
186 _bottom.store(b + 1, std::memory_order_relaxed);
190 template <
typename T>
192 int64_t b = _bottom.load(std::memory_order_relaxed) - 1;
193 Array* a = _array.load(std::memory_order_relaxed);
194 _bottom.store(b, std::memory_order_relaxed);
196 int64_t t = _top.load(std::memory_order_relaxed);
204 if(!_top.compare_exchange_strong(t, t+1,
205 std::memory_order_seq_cst,
206 std::memory_order_relaxed)) {
209 _bottom.store(b + 1, std::memory_order_relaxed);
213 _bottom.store(b + 1, std::memory_order_relaxed);
220 template <
typename T>
222 int64_t t = _top.load(std::memory_order_acquire);
224 int64_t b = _bottom.load(std::memory_order_acquire);
229 Array* a = _array.load(std::memory_order_consume);
231 if(!_top.compare_exchange_strong(t, t+1,
232 std::memory_order_seq_cst,
233 std::memory_order_relaxed)) {
242 template <
typename T>
244 return _array.load(std::memory_order_relaxed)->capacity();
TaskQueue(int64_t capacity=1024)
constructs the queue with a given capacity
Definition: tsq.hpp:136
size_t size() const noexcept
queries the number of items at the time of this call
Definition: tsq.hpp:163
Lock-free unbounded single-producer multiple-consumer queue.
Definition: tsq.hpp:27
bool empty() const noexcept
queries if the queue is empty at the time of this call
Definition: tsq.hpp:155
T pop()
pops out an item from the queue
Definition: tsq.hpp:191
void push(T item)
inserts an item to the queue
Definition: tsq.hpp:171
int64_t capacity() const noexcept
queries the capacity of the queue
Definition: tsq.hpp:243
T steal()
steals an item from the queue
Definition: tsq.hpp:221
T atomic_thread_fence(T... args)
~TaskQueue()
destructs the queue
Definition: tsq.hpp:146