StimBuff: Use a single StagingBuffer for all StimFrames

We now allocate all the stimFrames for a StimBuffer using a
single StagingBuffer. This gives us all the benefits we're
looking for (pinning, alignment, etc).
This commit is contained in:
2025-11-19 03:08:16 -04:00
parent 3f04d1b387
commit 41b8385cb2
8 changed files with 93 additions and 57 deletions
+22 -15
View File
@@ -6,7 +6,9 @@
#include <stdexcept>
#include <string>
#include <new>
#include <memory>
#include <user/stimulusFrame.h>
#include <user/frameAssemblyDesc.h>
#include <user/sequenceLock.h>
namespace smo {
@@ -24,32 +26,35 @@ class SpMcRingBuffer
{
public:
/** EXPLANATION:
* Constructor initializes the ring buffer with the given constraints and
* number of buffers. Allocates slots vector with properly constructed
* StimulusFrame instances.
* Constructor initializes the ring buffer with FrameAssemblyDesc.
* Allocates frames vector with properly constructed StimulusFrame instances,
* each initialized with a SlotDesc from the FrameAssemblyDesc.
*/
explicit SpMcRingBuffer(
size_t nBuffers_,
const StagingBuffer::IOEngineConstraints& inputEngineConstraints,
const StagingBuffer::IOEngineConstraints& outputEngineConstraints,
size_t nSlotsPerStimFrame)
: nBuffers(nBuffers_),
// Default-construct all frames
slots(nBuffers)
const std::shared_ptr<FrameAssemblyDesc> &frameAssemblyDesc_)
:
nBuffers(frameAssemblyDesc_ ? frameAssemblyDesc_->slots.size() : 0),
frameAssemblyDesc(frameAssemblyDesc_),
slots(nBuffers) // Default-construct all frames
{
if (!frameAssemblyDesc)
{
throw std::invalid_argument(std::string(__func__)
+ ": SpMcRingBuffer: frameAssemblyDesc must not be null");
}
if (nBuffers == 0)
{
throw std::invalid_argument(std::string(__func__)
+ ": SpMcRingBuffer: nBuffers must be > 0");
+ ": SpMcRingBuffer: frameAssemblyDesc must have at least one "
"slot");
}
// Re-invoke constructors w/placement new on default-constructed frames
for (size_t i = 0; i < nBuffers; ++i)
{
slots[i].~StimulusFrame(); // Destroy default-constructed object
new (&slots[i]) StimulusFrame(
inputEngineConstraints, outputEngineConstraints,
nSlotsPerStimFrame);
new (&slots[i]) StimulusFrame(frameAssemblyDesc->slots[i]);
}
}
@@ -94,7 +99,9 @@ public:
size_t nBuffers;
private:
// Frames vector: each frame contains a sequence lock and staging buffer
// FrameAssemblyDesc describing the memory layout
std::shared_ptr<FrameAssemblyDesc> frameAssemblyDesc;
// Frames vector: each frame contains a sequence lock and SlotDesc
std::vector<StimulusFrame> slots;
};
+8 -6
View File
@@ -6,6 +6,7 @@
#include <memory>
#include <user/spMcRingBuffer.h>
#include <user/stagingBuffer.h>
#include <user/frameAssemblyDesc.h>
#include "stimulusFrame.h"
#include "deviceAttachmentSpec.h"
@@ -30,15 +31,15 @@ public:
&deviceAttachmentSpec,
int histbuffMs,
const StagingBuffer::IOEngineConstraints& inputEngineConstraints,
const StagingBuffer::IOEngineConstraints& outputEngineConstraints,
size_t nSlotsPerStimFrame)
const StagingBuffer::IOEngineConstraints& outputEngineConstraints)
: parent(parent),
deviceAttachmentSpec(deviceAttachmentSpec),
histbuffMs(histbuffMs),
ringBuffer(
static_cast<size_t>(histbuffMs / CONFIG_STIMBUFF_FRAME_PERIOD_MS),
inputEngineConstraints, outputEngineConstraints,
nSlotsPerStimFrame)
stagingBuffer(
inputEngineConstraints,
outputEngineConstraints,
static_cast<size_t>(histbuffMs / CONFIG_STIMBUFF_FRAME_PERIOD_MS)),
ringBuffer(static_cast<std::shared_ptr<FrameAssemblyDesc>>(stagingBuffer))
{}
virtual ~StimulusBuffer() = default;
@@ -53,6 +54,7 @@ public:
StimulusProducer& parent;
std::shared_ptr<device::DeviceAttachmentSpec> deviceAttachmentSpec;
int histbuffMs;
StagingBuffer stagingBuffer;
SpMcRingBuffer ringBuffer;
};
+4 -8
View File
@@ -2,7 +2,7 @@
#define _ATTACHMENT_SUPPORT_STIMULUS_FRAME_H
#include <cstdint>
#include <user/stagingBuffer.h>
#include <user/frameAssemblyDesc.h>
#include <user/sequenceLock.h>
namespace smo {
@@ -69,12 +69,8 @@ public:
*/
StimulusFrame() = default;
StimulusFrame(
const StagingBuffer::IOEngineConstraints& inputEngineConstraints,
const StagingBuffer::IOEngineConstraints& outputEngineConstraints,
size_t nSlots)
: stagingBuffer(
inputEngineConstraints, outputEngineConstraints, nSlots)
StimulusFrame(const FrameAssemblyDesc::SlotDesc& slotDesc_)
: slotDesc(slotDesc_)
{}
~StimulusFrame() = default;
@@ -88,7 +84,7 @@ public:
public:
SequenceLock lock;
SimultaneityStamp simultaneityStamp;
StagingBuffer stagingBuffer;
FrameAssemblyDesc::SlotDesc slotDesc;
};
} // namespace stim_buff