From ca726f10ef28765e40f85f7e04af43258db69ee6 Mon Sep 17 00:00:00 2001 From: Vadim Skipin Date: Fri, 24 Jul 2026 18:25:28 +0000 Subject: [PATCH] Move values through BoundedQueue slots enqueue moved from its by-value parameter into the slot and dequeue moved the slot value out, where both previously copied. A dequeued slot no longer retains a copy until its next lap, so a T holding a reference (a shared pointer) releases it at hand-off; enqueue's retry-on-full callers keep their argument intact either way. --- include/silk/util/bounded-queue.h | 5 +++-- src/util/tests/bounded-queue-test.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/silk/util/bounded-queue.h b/include/silk/util/bounded-queue.h index d6c91ad..13a3c0a 100644 --- a/include/silk/util/bounded-queue.h +++ b/include/silk/util/bounded-queue.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace silk { @@ -70,7 +71,7 @@ class BoundedQueue { if (enqueuePos.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) { - slot.value = value; + slot.value = std::move(value); slot.sequence.store(pos + 1, std::memory_order_release); return true; } @@ -102,7 +103,7 @@ class BoundedQueue { if (dequeuePos.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) { - *value = slot.value; + *value = std::move(slot.value); slot.sequence.store(pos + mask + 1, std::memory_order_release); return true; } diff --git a/src/util/tests/bounded-queue-test.cpp b/src/util/tests/bounded-queue-test.cpp index e2b23d6..e5ffdd5 100644 --- a/src/util/tests/bounded-queue-test.cpp +++ b/src/util/tests/bounded-queue-test.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -85,6 +86,30 @@ TEST(BoundedQueue, ReusableAfterDrain) EXPECT_TRUE(queue.empty()); } +TEST(BoundedQueue, MovesValuesThroughSlots) +{ + BoundedQueue> queue{4}; + + std::shared_ptr source = std::make_shared(42); + std::weak_ptr observer = source; + + bool b = queue.enqueue(std::move(source)); + ASSERT_TRUE(b); + + std::shared_ptr result; + b = queue.dequeue(&result); + ASSERT_TRUE(b); + ASSERT_EQ(*result, 42); + + // The slot releases its reference at hand-off - result is the sole owner. + long useCount = observer.use_count(); + ASSERT_EQ(useCount, 1); + + result.reset(); + b = observer.expired(); + ASSERT_TRUE(b); +} + TEST(BoundedQueue, ConcurrentEnqueue) { constexpr int N_THREADS = 8;