42 explicit Array(int64_t c) :
65 void push(int64_t i, O&& o) noexcept {
69 S[i & M].store(std::forward<O>(o), std::memory_order_relaxed);
72 T
pop(int64_t i) noexcept {
75 return S[i & M].load(std::memory_order_relaxed);
78 Array* resize(int64_t b, int64_t t) {
79 Array* ptr =
new Array {2*C};
80 for(int64_t i=t; i!=b; ++i) {
111 bool empty()
const noexcept;
116 size_t size()
const noexcept;
134 template <
typename O>
143 std::optional<T>
pop();
151 std::optional<T>
steal();
155 template <
typename T>
157 assert(c && (!(c & (c-1))));
158 _top.store(0, std::memory_order_relaxed);
159 _bottom.store(0, std::memory_order_relaxed);
160 _array.store(
new Array{c}, std::memory_order_relaxed);
161 _garbage.reserve(32);
165 template <
typename T>
167 for(
auto a : _garbage) {
170 delete _array.load();
174 template <
typename T>
176 int64_t b = _bottom.load(std::memory_order_relaxed);
177 int64_t t = _top.load(std::memory_order_relaxed);
182 template <
typename T>
184 int64_t b = _bottom.load(std::memory_order_relaxed);
185 int64_t t = _top.load(std::memory_order_relaxed);
186 return static_cast<size_t>(b >= t ? b - t : 0);
190 template <
typename T>
191 template <
typename O>
193 int64_t b = _bottom.load(std::memory_order_relaxed);
194 int64_t t = _top.load(std::memory_order_acquire);
195 Array* a = _array.load(std::memory_order_relaxed);
198 if(a->capacity() - 1 < (b - t)) {
199 Array* tmp = a->resize(b, t);
200 _garbage.push_back(a);
202 _array.store(a, std::memory_order_relaxed);
205 a->push(b, std::forward<O>(o));
206 std::atomic_thread_fence(std::memory_order_release);
207 _bottom.store(b + 1, std::memory_order_relaxed);
211 template <
typename T>
213 int64_t b = _bottom.load(std::memory_order_relaxed) - 1;
214 Array* a = _array.load(std::memory_order_relaxed);
215 _bottom.store(b, std::memory_order_relaxed);
216 std::atomic_thread_fence(std::memory_order_seq_cst);
217 int64_t t = _top.load(std::memory_order_relaxed);
219 std::optional<T> item;
225 if(!_top.compare_exchange_strong(t, t+1,
226 std::memory_order_seq_cst,
227 std::memory_order_relaxed)) {
230 _bottom.store(b + 1, std::memory_order_relaxed);
234 _bottom.store(b + 1, std::memory_order_relaxed);
241 template <
typename T>
243 int64_t t = _top.load(std::memory_order_acquire);
244 std::atomic_thread_fence(std::memory_order_seq_cst);
245 int64_t b = _bottom.load(std::memory_order_acquire);
247 std::optional<T> item;
250 Array* a = _array.load(std::memory_order_consume);
252 if(!_top.compare_exchange_strong(t, t+1,
253 std::memory_order_seq_cst,
254 std::memory_order_relaxed)) {
263 template <
typename T>
265 return _array.load(std::memory_order_relaxed)->capacity();
bool empty() const noexcept
queries if the queue is empty at the time of this call
Definition: wsq.hpp:175
~WorkStealingQueue()
destructs the queue
Definition: wsq.hpp:166
void push(O &&item)
inserts an item to the queue
Definition: wsq.hpp:192
Definition: taskflow.hpp:5
size_t size() const noexcept
queries the number of items at the time of this call
Definition: wsq.hpp:183
int64_t capacity() const noexcept
queries the capacity of the queue
Definition: wsq.hpp:264
std::optional< T > pop()
pops out an item from the queue
Definition: wsq.hpp:212
Lock-free unbounded single-producer multiple-consumer queue.
Definition: wsq.hpp:27
std::optional< T > steal()
steals an item from the queue
Definition: wsq.hpp:242
WorkStealingQueue(int64_t capacity=1024)
constructs the queue with a given capacity
Definition: wsq.hpp:156