From 5f663f3de44eeb6a4fde5867b42b99795cb8618f Mon Sep 17 00:00:00 2001 From: Ritesh Raj Singh Date: Fri, 3 Apr 2026 22:59:40 +0530 Subject: [PATCH 1/2] updated head and tail cache --- include/lockfree_spsc_bounded/impl.hpp | 88 ++++++++++++++------------ 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/include/lockfree_spsc_bounded/impl.hpp b/include/lockfree_spsc_bounded/impl.hpp index 4ee2c92..03b2dd1 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 tail_load = tail.load(std::memory_order_relaxed); + size_t next_tail = (tail_load + 1) % capacity; while (next_tail == head_cache) { head_cache = head.load(std::memory_order_acquire); // busy wait } - arr[tail_cache] = std::move(value); + arr[tail_load] = std::move(value); tail_cache = next_tail; - tail.store(tail_cache, std::memory_order_release); + tail.store(next_tail, std::memory_order_release); } template @@ -27,86 +28,91 @@ namespace tsfqueue::impl return emplace_back(std::move(value)); } + template + template + bool lockfree_spsc_bounded::emplace_back(Args &&...args) + { + size_t tail_load = tail.load(std::memory_order_relaxed); + if ((tail_load + 1) % capacity == head_cache) + { + head_cache = head.load(std::memory_order_acquire); + if ((tail_load + 1) % capacity == head_cache) + { + return false; + } + } + + arr[tail_load] = T(std::forward(args)...); + tail_load = (tail_load + 1) % capacity; + tail.store(tail_load, std::memory_order_release); + return true; + } + template bool lockfree_spsc_bounded::try_pop(T &value) { - if (tail_cache == head_cache) + size_t head_load = head.load(std::memory_order_relaxed); + if (tail_cache == head_load) { tail_cache = tail.load(std::memory_order_acquire); - if (tail_cache == head_cache) + if (tail_cache == head_load) { 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[head_load]); + head_load = (head_load + 1) % capacity; + head.store(head_load, std::memory_order_release); return true; } template void lockfree_spsc_bounded::wait_and_pop(T &value) { - while (head_cache == tail_cache) + size_t head_load = head.load(std::memory_order_relaxed); + while (head_load == tail_cache) { 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[head_load]); + head_load = (head_load + 1) % capacity; + head.store(head_load, std::memory_order_release); } template bool lockfree_spsc_bounded::peek(T &value) { - if (head_cache == tail_cache) + size_t head_load = head.load(std::memory_order_relaxed); + if (head_load == tail_cache) { tail_cache = tail.load(std::memory_order_acquire); - if(head_cache == tail_cache) + if (head_load == tail_cache) { return false; } } - value = arr[head_cache]; + value = arr[head_load]; return true; } - template - template - bool lockfree_spsc_bounded::emplace_back(Args &&...args) - { - if ((tail_cache + 1) % capacity == head_cache) - { - head_cache = head.load(std::memory_order_acquire); - if ((tail_cache + 1) % capacity == 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); - 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 From c8dbbe10ff910de2c4548f176ffcc0ca57fb2ac5 Mon Sep 17 00:00:00 2001 From: Ritesh Raj Singh Date: Fri, 3 Apr 2026 23:36:04 +0530 Subject: [PATCH 2/2] updated spsc bounded --- include/lockfree_spsc_bounded/impl.hpp | 83 +++++++++++++------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/include/lockfree_spsc_bounded/impl.hpp b/include/lockfree_spsc_bounded/impl.hpp index 03b2dd1..aa72edc 100644 --- a/include/lockfree_spsc_bounded/impl.hpp +++ b/include/lockfree_spsc_bounded/impl.hpp @@ -9,16 +9,16 @@ namespace tsfqueue::impl template void lockfree_spsc_bounded::wait_and_push(T value) { - size_t tail_load = tail.load(std::memory_order_relaxed); - size_t next_tail = (tail_load + 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_load] = std::move(value); - tail_cache = next_tail; + arr[cur_tail] = std::move(value); + // tail_cache = next_tail; tail.store(next_tail, std::memory_order_release); } @@ -28,72 +28,71 @@ namespace tsfqueue::impl return emplace_back(std::move(value)); } - template - template - bool lockfree_spsc_bounded::emplace_back(Args &&...args) - { - size_t tail_load = tail.load(std::memory_order_relaxed); - if ((tail_load + 1) % capacity == head_cache) - { - head_cache = head.load(std::memory_order_acquire); - if ((tail_load + 1) % capacity == head_cache) - { - return false; - } - } - - arr[tail_load] = T(std::forward(args)...); - tail_load = (tail_load + 1) % capacity; - tail.store(tail_load, std::memory_order_release); - return true; - } - template bool lockfree_spsc_bounded::try_pop(T &value) { - size_t head_load = head.load(std::memory_order_relaxed); - if (tail_cache == head_load) + // 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_load) - { + if (tail_cache == cur_head) return false; - } } - value = std::move(arr[head_load]); - head_load = (head_load + 1) % capacity; - head.store(head_load, 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) { - size_t head_load = head.load(std::memory_order_relaxed); - while (head_load == 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_load]); - head_load = (head_load + 1) % capacity; - head.store(head_load, 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) { - size_t head_load = head.load(std::memory_order_relaxed); - if (head_load == 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_load == tail_cache) + if (cur_head == tail_cache) { return false; } } - value = arr[head_load]; + value = arr[cur_head]; + return true; + } + + template + template + bool lockfree_spsc_bounded::emplace_back(Args &&...args) + { + 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 (next_tail == head_cache) + { + return false; + } + } + arr[cur_tail] = T(std::forward(args)...); + // tail_cache = next_tail; + tail.store(next_tail, std::memory_order_release); return true; }