18 template <
typename T, T nullValue = T()>
39 void set(
size_t size);
48 size_t c = this->countLB();
49 return (c >= 1000000) ? (c - 1000000) : 0;
67 void forEach(std::function<
void(T)> f)
const;
73 return _countLB.load(std::memory_order_relaxed);
79 return _countUB.load(std::memory_order_relaxed);
88 std::atomic<T>* _array;
89 char pad0[UTL_CACHE_LINE_SIZE -
sizeof(
void*)];
90 std::atomic_size_t _countLB;
91 char pad1[UTL_CACHE_LINE_SIZE -
sizeof(size_t)];
92 std::atomic_size_t _countUB;
93 char pad2[UTL_CACHE_LINE_SIZE -
sizeof(size_t)];
94 std::atomic_size_t _head;
95 char pad3[UTL_CACHE_LINE_SIZE -
sizeof(size_t)];
96 std::atomic_size_t _tail;
97 char pad4[UTL_CACHE_LINE_SIZE -
sizeof(size_t)];
103 template <
typename T, T nullValue>
107 ASSERTD(
sizeof(T) <=
sizeof(
void*));
124 #if UTL_HOST_OS == UTL_OS_MINGW 125 size_t sizeBytes = (_size *
sizeof(std::atomic<T>)) + (2 * UTL_CACHE_LINE_SIZE);
126 _array = (std::atomic<T>*)malloc(sizeBytes);
127 _array += (UTL_CACHE_LINE_SIZE /
sizeof(std::atomic<T>));
129 size_t sizeBytes = (_size *
sizeof(std::atomic<T>)) + UTL_CACHE_LINE_SIZE;
130 posix_memalign((
void**)&_array, UTL_CACHE_LINE_SIZE, sizeBytes);
132 auto lim = _array + _size;
133 for (
auto it = _array; it != lim; ++it)
135 new (it) std::atomic<T>(nullValue);
138 #include <libutl/gblnew_macros.h> 142 template <
typename T, T nullValue>
146 #if UTL_HOST_OS == UTL_OS_MINGW 147 _array -= (UTL_CACHE_LINE_SIZE /
sizeof(std::atomic<T>));
155 template <
typename T, T nullValue>
160 if (this->countUB() >= _countMax)
return false;
161 if (_countUB.fetch_add(1, std::memory_order_relaxed) >= _countMax)
163 _countUB.fetch_sub(1, std::memory_order_relaxed);
168 auto pos = _tail.fetch_add(9, std::memory_order_relaxed) & _mask;
169 auto& val = _array[pos];
170 auto cur = nullValue;
171 while (!val.compare_exchange_weak(cur, value, std::memory_order_relaxed,
172 std::memory_order_relaxed))
178 _countLB.fetch_add(1, std::memory_order_relaxed);
184 template <
typename T, T nullValue>
189 if (this->countLB() <= 1000000)
return false;
190 if (_countLB.fetch_sub(1, std::memory_order_relaxed) <= 1000000)
192 _countLB.fetch_add(1, std::memory_order_relaxed);
197 auto pos = _head.fetch_add(9, std::memory_order_relaxed) & _mask;
198 auto& val = _array[pos];
200 while (value == nullValue)
202 value = val.exchange(nullValue, std::memory_order_relaxed);
206 _countUB.fetch_sub(1, std::memory_order_relaxed);
212 template <
typename T, T nullValue>
216 auto tail = _tail.load(std::memory_order_relaxed);
217 for (
auto pos = _head.load(std::memory_order_relaxed); pos != tail; pos += 9)
219 auto idx = pos & _mask;
220 auto val = _array[idx].load(std::memory_order_relaxed);
size_t count() const
Sample a lower-bound on the number of contained items.
Thread-safe fixed-size queue.
#define ASSERTD
Do an assertion in DEBUG mode only.