Split StimulusProducer=>StimulusBuffer+StimulusProducer

We're getting ready for the last mile of the StimulusBuffer API
and the proto-completion of the LivoxGen1 StimBuffApi.
This commit is contained in:
2025-11-14 20:44:37 -04:00
parent 70c0175a8b
commit 8a7dc10892
5 changed files with 96 additions and 46 deletions
+59
View File
@@ -0,0 +1,59 @@
#ifndef _STIMULUS_BUFFER_H
#define _STIMULUS_BUFFER_H
#include <config.h>
#include <vector>
#include <memory>
#include <user/spMcRingBuffer.h>
#include "stimulusFrame.h"
namespace smo {
namespace stim_buff {
// Forward declaration
class StimulusProducer;
/**
* StimulusBuffer manages a collection of stimulus frames and ring buffer.
*
* This buffer holds the actual frame storage and ring buffer for stimulus
* data. It maintains a reference to the StimulusProducer that it owns.
*/
class StimulusBuffer
{
public:
explicit StimulusBuffer(
std::shared_ptr<StimulusProducer> &producer,
int histbuffMs,
const SpMcRingBuffer::InputEngineConstraints& ringBufferConstraints)
: producer(producer),
histbuffMs(histbuffMs),
frames_(static_cast<size_t>(histbuffMs / CONFIG_STIMBUFF_FRAME_PERIOD_MS)),
ringBufferConstraints(ringBufferConstraints),
ringBuffer(
static_cast<size_t>(histbuffMs / CONFIG_STIMBUFF_FRAME_PERIOD_MS),
ringBufferConstraints)
{}
~StimulusBuffer() = default;
// Non-copyable, movable
StimulusBuffer(const StimulusBuffer&) = delete;
StimulusBuffer& operator=(const StimulusBuffer&) = delete;
StimulusBuffer(StimulusBuffer&&) = default;
StimulusBuffer& operator=(StimulusBuffer&&) = default;
public:
std::shared_ptr<StimulusProducer> producer;
std::vector<StimulusFrame> frames_;
protected:
int histbuffMs;
SpMcRingBuffer::InputEngineConstraints ringBufferConstraints;
SpMcRingBuffer ringBuffer;
};
} // namespace stim_buff
} // namespace smo
#endif // _STIMULUS_BUFFER_H
+2 -24
View File
@@ -14,8 +14,6 @@
#include <boost/asio/io_service.hpp> #include <boost/asio/io_service.hpp>
#include <boost/asio/deadline_timer.hpp> #include <boost/asio/deadline_timer.hpp>
#include <spinLock.h> #include <spinLock.h>
#include <user/spMcRingBuffer.h>
#include "stimulusFrame.h"
#include "deviceAttachmentSpec.h" #include "deviceAttachmentSpec.h"
namespace smo { namespace smo {
@@ -33,29 +31,12 @@ namespace stim_buff {
*/ */
class StimulusProducer class StimulusProducer
{ {
public:
class PcloudFormatDesc
{
public:
enum class Format
{
XYZ,
XYZI,
};
public:
Format format;
};
public: public:
explicit StimulusProducer( explicit StimulusProducer(
const std::shared_ptr<device::DeviceAttachmentSpec> const std::shared_ptr<device::DeviceAttachmentSpec>
&deviceAttachmentSpec, &deviceAttachmentSpec,
size_t nSlots,
const SpMcRingBuffer::InputEngineConstraints& ringBufferConstraints,
boost::asio::io_service& ioService_) boost::asio::io_service& ioService_)
: deviceAttachmentSpec(deviceAttachmentSpec), : deviceAttachmentSpec(deviceAttachmentSpec),
ringBuffer(nSlots, ringBufferConstraints),
ioService(ioService_), ioService(ioService_),
shouldContinue(false), timer(ioService), shouldContinue(false), timer(ioService),
nDeferrals(0) nDeferrals(0)
@@ -86,6 +67,8 @@ public:
{ frameAssemblyRateLimiter.release(); } { frameAssemblyRateLimiter.release(); }
protected: protected:
SpinLock frameAssemblyRateLimiter;
// Virtual functions for derived classes to override // Virtual functions for derived classes to override
virtual int getStopDelayMs() const virtual int getStopDelayMs() const
{ {
@@ -99,11 +82,6 @@ private:
public: public:
std::shared_ptr<device::DeviceAttachmentSpec> deviceAttachmentSpec; std::shared_ptr<device::DeviceAttachmentSpec> deviceAttachmentSpec;
std::vector<StimulusFrame> frames_;
protected:
SpinLock frameAssemblyRateLimiter;
SpMcRingBuffer ringBuffer;
private: private:
boost::asio::io_service& ioService; boost::asio::io_service& ioService;
+4 -3
View File
@@ -170,6 +170,7 @@ public:
// Parse history buffer duration from quale-iface-api-params // Parse history buffer duration from quale-iface-api-params
int histbuffMs = 30000; // Default: 30000ms (30 seconds) int histbuffMs = 30000; // Default: 30000ms (30 seconds)
(void)histbuffMs;
const std::vector<std::string> histbuffParamNames = { const std::vector<std::string> histbuffParamNames = {
"history-buffer-duration-ms", "history-buffer-duration-ms",
"hist-buff-duration-ms", "hist-buff-duration-ms",
@@ -194,10 +195,10 @@ public:
} }
// Create and add PcloudDataProducer to collection now that device is ready // Create and add PcloudDataProducer to collection now that device is ready
StimulusProducer::PcloudFormatDesc formatDesc; PcloudDataProducer::PcloudFormatDesc formatDesc;
formatDesc.format = StimulusProducer::PcloudFormatDesc::Format::XYZI; formatDesc.format = PcloudDataProducer::PcloudFormatDesc::Format::XYZI;
auto pcloudDataProducer = std::make_shared<PcloudDataProducer>( auto pcloudDataProducer = std::make_shared<PcloudDataProducer>(
context->spec, context->deviceTmp, formatDesc, histbuffMs, 30); context->spec, context->deviceTmp, formatDesc, 30);
context->stimProducer = pcloudDataProducer; context->stimProducer = pcloudDataProducer;
context->deviceTmp->nAttachedStimBuffs++; context->deviceTmp->nAttachedStimBuffs++;
+15 -18
View File
@@ -23,12 +23,9 @@ PcloudDataProducer::PcloudDataProducer(
const std::shared_ptr<device::DeviceAttachmentSpec> &deviceAttachmentSpec, const std::shared_ptr<device::DeviceAttachmentSpec> &deviceAttachmentSpec,
std::shared_ptr<livoxProto1::Device> &device, std::shared_ptr<livoxProto1::Device> &device,
const PcloudFormatDesc& formatDesc, const PcloudFormatDesc& formatDesc,
int histbuffMs,
size_t nDgramsPerStagingBufferFrame) size_t nDgramsPerStagingBufferFrame)
: StimulusProducer( : StimulusProducer(
deviceAttachmentSpec, deviceAttachmentSpec,
static_cast<size_t>(histbuffMs / CONFIG_STIMBUFF_FRAME_PERIOD_MS),
openClInputConstraints,
device->componentThread->getIoService()), device->componentThread->getIoService()),
device(device), device(device),
formatDesc(formatDesc), formatDesc(formatDesc),
@@ -112,25 +109,25 @@ class PcloudDataProducer::ProduceFrameReq
: public PostedAsynchronousContinuation<produceFrameReqCbFn> : public PostedAsynchronousContinuation<produceFrameReqCbFn>
{ {
private: private:
PcloudDataProducer& stimBuff; PcloudDataProducer& pcloudProducer;
AsynchronousLoop frameAssemblyResult; AsynchronousLoop frameAssemblyResult;
StimulusFrame& stimulusFrame; StimulusFrame& stimulusFrame;
public: public:
ProduceFrameReq( ProduceFrameReq(
PcloudDataProducer& buffer, PcloudDataProducer& producer,
const std::shared_ptr<ComponentThread>& caller, const std::shared_ptr<ComponentThread>& caller,
Callback<produceFrameReqCbFn> cb) Callback<produceFrameReqCbFn> cb)
: PostedAsynchronousContinuation<produceFrameReqCbFn>(caller, cb), : PostedAsynchronousContinuation<produceFrameReqCbFn>(caller, cb),
stimBuff(buffer), pcloudProducer(producer),
frameAssemblyResult(0), frameAssemblyResult(0),
stimulusFrame(buffer.frames_[0]) stimulusFrame(producer.tempStimulusFrame)
{} {}
public: public:
void callOriginalCallback() void callOriginalCallback()
{ {
stimBuff.allowNextStimulusFrame(); pcloudProducer.allowNextStimulusFrame();
callOriginalCb(); callOriginalCb();
} }
@@ -138,14 +135,14 @@ public:
void produceFrameReq1_doAssemble_posted( void produceFrameReq1_doAssemble_posted(
std::shared_ptr<ProduceFrameReq> context) std::shared_ptr<ProduceFrameReq> context)
{ {
SpinLock::Guard lock(stimBuff.shouldContinueLock); SpinLock::Guard lock(pcloudProducer.shouldContinueLock);
if (!stimBuff.shouldContinue) if (!pcloudProducer.shouldContinue)
{ {
callOriginalCallback(); callOriginalCallback();
return; return;
} }
stimBuff.ioUringAssemblyEngine.assembleFrameReq( pcloudProducer.ioUringAssemblyEngine.assembleFrameReq(
{context, std::bind( {context, std::bind(
&ProduceFrameReq::produceFrameReq2_assembleDone, &ProduceFrameReq::produceFrameReq2_assembleDone,
context.get(), context, context.get(), context,
@@ -156,8 +153,8 @@ public:
std::shared_ptr<ProduceFrameReq> context, std::shared_ptr<ProduceFrameReq> context,
bool success, AsynchronousLoop loop) bool success, AsynchronousLoop loop)
{ {
SpinLock::Guard lock(stimBuff.shouldContinueLock); SpinLock::Guard lock(pcloudProducer.shouldContinueLock);
if (!stimBuff.shouldContinue) if (!pcloudProducer.shouldContinue)
{ {
callOriginalCallback(); callOriginalCallback();
return; return;
@@ -172,7 +169,7 @@ public:
context->frameAssemblyResult = loop; context->frameAssemblyResult = loop;
stimBuff.openClCollatingAndMeshingEngine.compactCollateAndMeshFrameReq( pcloudProducer.openClCollatingAndMeshingEngine.compactCollateAndMeshFrameReq(
loop, stimulusFrame, loop, stimulusFrame,
{context, std::bind( {context, std::bind(
&ProduceFrameReq::produceFrameReq3_compactCollateDone, &ProduceFrameReq::produceFrameReq3_compactCollateDone,
@@ -184,8 +181,8 @@ public:
[[maybe_unused]] std::shared_ptr<ProduceFrameReq> context, [[maybe_unused]] std::shared_ptr<ProduceFrameReq> context,
bool success, StimulusFrame& /*stimulusFrame*/) bool success, StimulusFrame& /*stimulusFrame*/)
{ {
SpinLock::Guard lock(stimBuff.shouldContinueLock); SpinLock::Guard lock(pcloudProducer.shouldContinueLock);
if (!stimBuff.shouldContinue) if (!pcloudProducer.shouldContinue)
{ {
callOriginalCallback(); callOriginalCallback();
return; return;
@@ -198,8 +195,8 @@ public:
} }
// Print kernel execution durations // Print kernel execution durations
auto compactDuration = stimBuff.openClCollatingAndMeshingEngine.getCompactKernelDuration(); auto compactDuration = pcloudProducer.openClCollatingAndMeshingEngine.getCompactKernelDuration();
auto collateDuration = stimBuff.openClCollatingAndMeshingEngine.getCollateKernelDuration(); auto collateDuration = pcloudProducer.openClCollatingAndMeshingEngine.getCollateKernelDuration();
std::cout << __func__ << ": compactKernelDuration=" << compactDuration.count() std::cout << __func__ << ": compactKernelDuration=" << compactDuration.count()
<< "ms, collateKernelDuration=" << collateDuration.count() << "ms" << std::endl; << "ms, collateKernelDuration=" << collateDuration.count() << "ms" << std::endl;
+16 -1
View File
@@ -4,6 +4,7 @@
#include <functional> #include <functional>
#include <atomic> #include <atomic>
#include <user/stimulusProducer.h> #include <user/stimulusProducer.h>
#include <user/stimulusFrame.h>
#include <livoxProto1/device.h> #include <livoxProto1/device.h>
#include <asynchronousContinuation.h> #include <asynchronousContinuation.h>
#include <callback.h> #include <callback.h>
@@ -25,12 +26,25 @@ namespace stim_buff {
class PcloudDataProducer class PcloudDataProducer
: public StimulusProducer : public StimulusProducer
{ {
public:
class PcloudFormatDesc
{
public:
enum class Format
{
XYZ,
XYZI,
};
public:
Format format;
};
public: public:
explicit PcloudDataProducer( explicit PcloudDataProducer(
const std::shared_ptr<device::DeviceAttachmentSpec> &deviceAttachmentSpec, const std::shared_ptr<device::DeviceAttachmentSpec> &deviceAttachmentSpec,
std::shared_ptr<livoxProto1::Device> &device, std::shared_ptr<livoxProto1::Device> &device,
const PcloudFormatDesc& formatDesc, const PcloudFormatDesc& formatDesc,
int histbuffMs,
size_t nDgramsPerStagingBufferFrame); size_t nDgramsPerStagingBufferFrame);
~PcloudDataProducer() = default; ~PcloudDataProducer() = default;
@@ -61,6 +75,7 @@ public:
IoUringAssemblyEngine ioUringAssemblyEngine; IoUringAssemblyEngine ioUringAssemblyEngine;
StagingBuffer collationBuffer; StagingBuffer collationBuffer;
std::atomic<size_t> nAttachedStimBuffs{0}; std::atomic<size_t> nAttachedStimBuffs{0};
StimulusFrame tempStimulusFrame;
private: private:
class ProduceFrameReq; class ProduceFrameReq;