19 return _state.fetch_add(kReader, std::memory_order_acq_rel) / kWriter == 0;
24 return _state.load(std::memory_order_relaxed) ==
s &&
25 _state.compare_exchange_strong(
s,
s + kWriter, std::memory_order_acq_rel, std::memory_order_relaxed);
29 std::lock_guard lock{_lock};
30 if (_readers_pass != 0) {
34 YACLIB_ASSERT(_state.load(std::memory_order_relaxed) / kWriter != 0);
35 _readers.PushBack(
curr);
42 std::lock_guard lock{_lock};
43 auto s = _state.fetch_add(kWriter, std::memory_order_acq_rel);
44 if (
s / kWriter == 0) {
45 std::uint32_t
r =
s % kWriter;
46 _writers_first = &
curr;
47 return r != 0 && _readers_wait.fetch_add(
r, std::memory_order_acq_rel) != -
r;
50 _writers_tail = &
curr;
52 _writers_prio +=
static_cast<std::uint32_t
>(_readers.Empty());
58 auto s = _state.load(std::memory_order_relaxed);
60 if (
s / kWriter != 0) {
63 }
while (!_state.compare_exchange_weak(
s,
s + kReader, std::memory_order_acq_rel, std::memory_order_relaxed));
72 if (
auto s = _state.fetch_sub(kReader, std::memory_order_acq_rel);
s >= kWriter) {
74 if (_readers_wait.fetch_sub(1, std::memory_order_acq_rel) == 1) {
82 if (
auto s = kWriter; !_state.compare_exchange_strong(
s, 0, std::memory_order_acq_rel, std::memory_order_relaxed)) {
89 static constexpr auto kReader = std::uint64_t{1};
90 static constexpr auto kWriter = kReader << std::uint64_t{32};
94 auto&
core =
static_cast<BaseCore&
>(*node);
105 if (_writers_head.
next ==
nullptr) {
106 _writers_tail = &_writers_head;
113 void PassReaders(std::uint64_t
s)
noexcept {
115 std::uint32_t
r =
s % kWriter;
117 _readers_pass +=
r - _readers_size;
120 void RunReaders(std::uint64_t
s)
noexcept {
121 if (std::uint32_t
w =
s / kWriter;
w != 1) {
122 _readers_wait.store(_readers_size, std::memory_order_relaxed);
125 if (_writers_head.
next ==
nullptr) {
126 _writers_tail = &_writers_head;
128 _writers_first =
node;
129 if constexpr (
FIFO) {
130 _writers_prio =
w - 2;
135 auto readers = std::move(_readers);
146 auto s = _state.fetch_sub(kWriter, std::memory_order_acq_rel);
147 if constexpr (
FIFO) {
148 if (_writers_prio != 0) {
153 if (!_readers.Empty()) {
154 return RunReaders(
s);
156 if constexpr (!
FIFO) {
157 if (
s / kWriter != 1) {
166 std::conditional_t<ReadersFIFO, List, Stack> _readers;
168 Node* _writers_first =
nullptr;
170 Node* _writers_tail = &_writers_head;
171 std::uint32_t _writers_prio = 0;
173 std::uint32_t _readers_size = 0;
174 std::uint32_t _readers_pass = 0;
175 Spinlock<std::uint32_t> _lock;