From 9e64c510ccb9d33bb6b86bc92780f13e3b5d23c7 Mon Sep 17 00:00:00 2001 From: Hayodea Hekol Date: Thu, 20 Nov 2025 03:06:35 -0400 Subject: [PATCH] SpMcRingBuff: Add getNextIndexForProducer/abortProduction These two methods form the core of the SpMcRingbuffer's wrap-around behaviour. --- include/user/spMcRingBuffer.h | 41 ++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/include/user/spMcRingBuffer.h b/include/user/spMcRingBuffer.h index b368af6..2a3258a 100644 --- a/include/user/spMcRingBuffer.h +++ b/include/user/spMcRingBuffer.h @@ -40,7 +40,8 @@ public: : nBuffers(frameAssemblyDesc_ ? frameAssemblyDesc_->slots.size() : 0), frameAssemblyDesc(frameAssemblyDesc_), - slots(nBuffers) // Default-construct all frames + slots(nBuffers), // Default-construct all frames + producerNextUsableIndex(0) { if (!frameAssemblyDesc) { @@ -100,6 +101,42 @@ public: return slots[slotIndex].lock; } + /** + * @brief Get the next index to produce into, atomically incrementing it + * + * Uses sequence lock to perform an emulated fetch_add with modulo nBuffers + * applied, ensuring the returned index is always < nBuffers. + * + * @return The index to produce into (always < nBuffers) + */ + size_t getIndexToProduceInto() + { + producerNextUsableIndexLock.writeAcquire(); + size_t currentIndex = producerNextUsableIndex; + size_t nextIndex = (currentIndex + 1) % nBuffers; + producerNextUsableIndex = nextIndex; + producerNextUsableIndexLock.writeRelease(); + return currentIndex; + } + + /** + * @brief Abort production by setting the producer index to a specific value + * + * @param index The index to set (must be < nBuffers) + * @throws std::out_of_range if index >= nBuffers + */ + void abortProduction(size_t index) + { + if (index >= nBuffers) + { + throw std::out_of_range(std::string(__func__) + + ": SpMcRingBuffer: index must be < nBuffers"); + } + producerNextUsableIndexLock.writeAcquire(); + producerNextUsableIndex = index; + producerNextUsableIndexLock.writeRelease(); + } + public: // Layout/invariants size_t nBuffers; @@ -109,6 +146,8 @@ private: std::shared_ptr frameAssemblyDesc; // Frames vector: each frame contains a sequence lock and SlotDesc std::vector slots; + SequenceLock producerNextUsableIndexLock; + size_t producerNextUsableIndex; }; } // namespace stim_buff