diff --git a/include/lockfree_spsc_bounded/impl.hpp b/include/lockfree_spsc_bounded/impl.hpp index 4ee2c92..aa72edc 100644 --- a/include/lockfree_spsc_bounded/impl.hpp +++ b/include/lockfree_spsc_bounded/impl.hpp @@ -9,16 +9,17 @@ namespace tsfqueue::impl template void lockfree_spsc_bounded::wait_and_push(T value) { - size_t next_tail = (tail_cache + 1) % capacity; - + size_t cur_tail = tail.load(std::memory_order_acquire); + size_t next_tail = (cur_tail + 1) % capacity; + // size_t curr_head = head.load(std::memory_order_acquire); while (next_tail == head_cache) { head_cache = head.load(std::memory_order_acquire); // busy wait } - arr[tail_cache] = std::move(value); - tail_cache = next_tail; - tail.store(tail_cache, std::memory_order_release); + arr[cur_tail] = std::move(value); + // tail_cache = next_tail; + tail.store(next_tail, std::memory_order_release); } template @@ -30,46 +31,48 @@ namespace tsfqueue::impl template bool lockfree_spsc_bounded::try_pop(T &value) { - if (tail_cache == head_cache) + // cur_tail = tail.load(std::memory_order_acquire); + size_t cur_head = head.load(std::memory_order_acquire); + if (tail_cache == cur_head) { tail_cache = tail.load(std::memory_order_acquire); - if (tail_cache == head_cache) - { + if (tail_cache == cur_head) return false; - } } - value = std::move(arr[head_cache]); - head_cache = (head_cache + 1) % capacity; - head.store(head_cache, std::memory_order_release); + value = std::move(arr[cur_head]); + // head_cache = (cur_head + 1) % capacity; + head.store((cur_head + 1) % capacity, std::memory_order_release); return true; } template void lockfree_spsc_bounded::wait_and_pop(T &value) { - while (head_cache == tail_cache) + size_t cur_head = head.load(std::memory_order_acquire); + while (tail_cache == cur_head) { tail_cache = tail.load(std::memory_order_acquire); // busy wait } - value = std::move(arr[head_cache]); - head_cache = (head_cache + 1) % capacity; - head.store(head_cache, std::memory_order_release); + value = std::move(arr[cur_head]); + // head_cache = (cur_head + 1) % capacity; + head.store((cur_head + 1) % capacity, std::memory_order_release); } template bool lockfree_spsc_bounded::peek(T &value) { - if (head_cache == tail_cache) + size_t cur_head = head.load(std::memory_order_acquire); + if (cur_head == tail_cache) { tail_cache = tail.load(std::memory_order_acquire); - if(head_cache == tail_cache) + if (cur_head == tail_cache) { return false; } } - value = arr[head_cache]; + value = arr[cur_head]; return true; } @@ -77,36 +80,38 @@ namespace tsfqueue::impl template bool lockfree_spsc_bounded::emplace_back(Args &&...args) { - if ((tail_cache + 1) % capacity == head_cache) + size_t cur_tail = tail.load(std::memory_order_acquire); + size_t next_tail = (cur_tail + 1) % capacity; + if (next_tail == head_cache) { head_cache = head.load(std::memory_order_acquire); - if ((tail_cache + 1) % capacity == head_cache) + if (next_tail == head_cache) { return false; } } - - arr[tail_cache] = T(std::forward(args)...); - tail_cache = (tail_cache + 1) % capacity; - tail.store(tail_cache, std::memory_order_release); + arr[cur_tail] = T(std::forward(args)...); + // tail_cache = next_tail; + tail.store(next_tail, std::memory_order_release); return true; } - + template bool lockfree_spsc_bounded::empty() const { - return head.load(std::memory_order_relaxed) == + return head.load(std::memory_order_relaxed) == tail.load(std::memory_order_relaxed); - // since queue is very frequently modified + // since queue is very frequently modified } - + template size_t lockfree_spsc_bounded::size() const { - return (tail.load(std::memory_order_relaxed) - - head.load(std::memory_order_relaxed) + - capacity) % capacity; - // again, since size is very frequently changing. + return (tail.load(std::memory_order_relaxed) - + head.load(std::memory_order_relaxed) + + capacity) % + capacity; + // again, since size is very frequently changing. } } // namespace tsfqueue::impl