6 #ifndef XENIUM_NIKOLAEV_BOUNDED_QUEUE_HPP
7 #define XENIUM_NIKOLAEV_BOUNDED_QUEUE_HPP
9 #include <xenium/parameter.hpp>
10 #include <xenium/policy.hpp>
11 #include <xenium/utils.hpp>
13 #include <xenium/detail/nikolaev_scq.hpp>
41 template <
class T,
class... Policies>
45 static constexpr
unsigned pop_retries =
80 bool try_pop(value_type& result);
85 [[nodiscard]] std::size_t
capacity() const noexcept {
return _capacity; }
88 using storage_t =
typename std::aligned_storage<
sizeof(T),
alignof(T)>::type;
89 const std::size_t _capacity;
90 const std::size_t _remap_shift;
91 std::unique_ptr<storage_t[]> _storage;
92 detail::nikolaev_scq _allocated_queue;
93 detail::nikolaev_scq _free_queue;
96 template <
class T,
class... Policies>
98 _capacity(utils::next_power_of_two(capacity)),
99 _remap_shift(detail::nikolaev_scq::calc_remap_shift(_capacity)),
100 _storage(new storage_t[_capacity]),
101 _allocated_queue(_capacity, _remap_shift, detail::nikolaev_scq::empty_tag{}),
102 _free_queue(_capacity, _remap_shift, detail::nikolaev_scq::full_tag{}) {
103 assert(capacity > 0);
106 template <
class T,
class... Policies>
107 nikolaev_bounded_queue<T, Policies...>::~nikolaev_bounded_queue() {
109 while (_allocated_queue.dequeue<
false, pop_retries>(eidx, _capacity, _remap_shift)) {
110 reinterpret_cast<T&
>(_storage[eidx]).~T();
114 template <
class T,
class... Policies>
118 if (!_free_queue.dequeue<
false, pop_retries>(eidx, _capacity, _remap_shift)) {
122 assert(eidx < _capacity);
123 new (&_storage[eidx]) T(std::move(value));
124 _allocated_queue.enqueue<
false,
false>(eidx, _capacity, _remap_shift);
128 template <
class T,
class... Policies>
132 if (!_allocated_queue.dequeue<
false, pop_retries>(eidx, _capacity, _remap_shift)) {
136 assert(eidx < _capacity);
137 T& data =
reinterpret_cast<T&
>(_storage[eidx]);
138 result = std::move(data);
140 _free_queue.enqueue<
false,
false>(eidx, _capacity, _remap_shift);