SpMcRingBuff: Add getNextIndexForProducer/abortProduction

These two methods form the core of the SpMcRingbuffer's wrap-around
behaviour.
This commit is contained in:
2025-11-20 03:06:35 -04:00
parent 9d9644cb31
commit 9e64c510cc
+40 -1
View File
@@ -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> frameAssemblyDesc;
// Frames vector: each frame contains a sequence lock and SlotDesc
std::vector<StimulusFrame> slots;
SequenceLock producerNextUsableIndexLock;
size_t producerNextUsableIndex;
};
} // namespace stim_buff