SpMcRingBuff: Add getNextIndexForProducer/abortProduction
These two methods form the core of the SpMcRingbuffer's wrap-around behaviour.
This commit is contained in:
@@ -40,7 +40,8 @@ public:
|
|||||||
:
|
:
|
||||||
nBuffers(frameAssemblyDesc_ ? frameAssemblyDesc_->slots.size() : 0),
|
nBuffers(frameAssemblyDesc_ ? frameAssemblyDesc_->slots.size() : 0),
|
||||||
frameAssemblyDesc(frameAssemblyDesc_),
|
frameAssemblyDesc(frameAssemblyDesc_),
|
||||||
slots(nBuffers) // Default-construct all frames
|
slots(nBuffers), // Default-construct all frames
|
||||||
|
producerNextUsableIndex(0)
|
||||||
{
|
{
|
||||||
if (!frameAssemblyDesc)
|
if (!frameAssemblyDesc)
|
||||||
{
|
{
|
||||||
@@ -100,6 +101,42 @@ public:
|
|||||||
return slots[slotIndex].lock;
|
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:
|
public:
|
||||||
// Layout/invariants
|
// Layout/invariants
|
||||||
size_t nBuffers;
|
size_t nBuffers;
|
||||||
@@ -109,6 +146,8 @@ private:
|
|||||||
std::shared_ptr<FrameAssemblyDesc> frameAssemblyDesc;
|
std::shared_ptr<FrameAssemblyDesc> frameAssemblyDesc;
|
||||||
// Frames vector: each frame contains a sequence lock and SlotDesc
|
// Frames vector: each frame contains a sequence lock and SlotDesc
|
||||||
std::vector<StimulusFrame> slots;
|
std::vector<StimulusFrame> slots;
|
||||||
|
SequenceLock producerNextUsableIndexLock;
|
||||||
|
size_t producerNextUsableIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace stim_buff
|
} // namespace stim_buff
|
||||||
|
|||||||
Reference in New Issue
Block a user