OClCollMeshEngn,PcloudStimProd: port to sscl::co coros

We've now ported the OpenClCollMeshEngn and PcloudStimProd::produceFrameReq
portions of the Livox pipeline to coros.
This commit is contained in:
2026-05-30 19:32:19 -04:00
parent 1cf1be4194
commit 35eb466a60
7 changed files with 398 additions and 373 deletions
+122 -154
View File
@@ -11,6 +11,8 @@
#include <user/spMcRingBuffer.h>
#include <componentThread.h>
#include <spinscale/asynchronousLoop.h>
#include <spinscale/co/invokers.h>
#include <adapters/smo/assembleFrameAReq.h>
#include <user/stimulusFrame.h>
#include <user/frameAssemblyDesc.h>
#include <livoxProto1/device.h>
@@ -428,219 +430,205 @@ PcloudStimulusProducer::getOrCreateAttachedStimulusBuffer(
void PcloudStimulusProducer::stimFrameProductionTimesliceInd()
{
produceFrameReq({nullptr, nullptr});
holdProduceFrameCReq();
}
class PcloudStimulusProducer::ProduceFrameReq
: public sscl::cps::PostedAsynchronousContinuation<produceFrameReqCbFn>
struct AllowNextStimulusFrameGuard
{
private:
PcloudStimulusProducer& pcloudProducer;
sscl::AsynchronousLoop frameAssemblyResult;
StimulusFrame& stimulusFrame;
PcloudStimulusProducer& producer;
explicit AllowNextStimulusFrameGuard(PcloudStimulusProducer& _producer)
: producer(_producer)
{}
~AllowNextStimulusFrameGuard()
{ producer.allowNextStimulusFrame(); }
};
void PcloudStimulusProducer::holdProduceFrameCReq()
{
/** EXPLANATION:
* We shouldn't acquire stimulusProducerCanceler.s.lock here because
* this function is called from
* StimulusProducer::stimFrameProductionTimesliceInd(), which is already
* holding the lock.
*/
activeProduceFrameInvoker.emplace(produceFrameCReq(
produceFrameExceptionPtr,
[this]() { activeProduceFrameInvoker.reset(); }));
}
sscl::co::NonViralNonPostingInvoker PcloudStimulusProducer::produceFrameCReq(
[[maybe_unused]] std::exception_ptr& exceptionPtr,
[[maybe_unused]] std::function<void()> completion)
{
AllowNextStimulusFrameGuard allowNextGuard(*this);
StimulusFrame& stimulusFrame = tempStimulusFrame;
sscl::AsynchronousLoop frameAssemblyResult(0);
std::optional<std::reference_wrapper<StimulusFrame>> intensityStimFrame;
std::optional<std::reference_wrapper<StimulusFrame>> lightAmbienceStimFrame;
std::optional<std::reference_wrapper<StimulusFrame>> darkAmbienceStimFrame;
public:
ProduceFrameReq(
PcloudStimulusProducer& producer,
const std::shared_ptr<sscl::ComponentThread>& caller,
sscl::cps::Callback<produceFrameReqCbFn> cb)
: sscl::cps::PostedAsynchronousContinuation<produceFrameReqCbFn>(caller, cb),
pcloudProducer(producer),
frameAssemblyResult(0),
stimulusFrame(producer.tempStimulusFrame)
{}
auto& resumeIoContext = device->componentThread->getIoContext();
public:
void callOriginalCallback()
// produceFrameReq1_doAssemble_posted
/** EXPLANATION:
* stimFrameProductionTimesliceInd() is entered with
* stimulusProducerCanceler.s.lock held; do not re-acquire here.
*
* This function is called from
* StimulusProducer::stimFrameProductionTimesliceInd(), whose caller is
* already holding the lock.
*/
if (stimulusProducerCanceler.isCancellationRequestedUnlocked())
{ co_return; }
cpsBoundary::AssembleFrameResult assembleResult = co_await
cpsBoundary::getAssembleFrameReqAReqAwaiter(
resumeIoContext, ioUringAssemblyEngine);
// produceFrameReq2_assembleDone
std::optional<AmbienceProductionDesc> lightAmbienceProductionDescDesc;
std::optional<AmbienceProductionDesc> darkAmbienceProductionDescDesc;
{
pcloudProducer.allowNextStimulusFrame();
callOriginalCb();
}
sscl::SpinLock::Guard guard(stimulusProducerCanceler.s.lock);
if (stimulusProducerCanceler.isCancellationRequestedUnlocked())
{ co_return; }
public:
void produceFrameReq1_doAssemble_posted(
std::shared_ptr<ProduceFrameReq> context)
{
sscl::SpinLock::Guard guard(
pcloudProducer.stimulusProducerCanceler.s.lock);
if (pcloudProducer.stimulusProducerCanceler
.isCancellationRequestedUnlocked())
if (!assembleResult.success)
{
callOriginalCallback();
return;
}
pcloudProducer.ioUringAssemblyEngine.assembleFrameReq(
{context, std::bind(
&ProduceFrameReq::produceFrameReq2_assembleDone,
context.get(), context,
std::placeholders::_1, std::placeholders::_2)});
}
void produceFrameReq2_assembleDone(
std::shared_ptr<ProduceFrameReq> context,
bool success, sscl::AsynchronousLoop loop)
{
sscl::SpinLock::Guard guard(
pcloudProducer.stimulusProducerCanceler.s.lock);
if (pcloudProducer.stimulusProducerCanceler
.isCancellationRequestedUnlocked())
{
callOriginalCallback();
return;
}
if (!success)
{
callOriginalCallback();
if (pcloudProducer.attachedStimulusBuffers.size() > 0) {
if (attachedStimulusBuffers.size() > 0) {
std::cerr << __func__ << ": Failed to assemble frame.\n";
}
return;
co_return;
}
context->frameAssemblyResult = loop;
frameAssemblyResult = assembleResult.loop;
// Check if intensity buffer is attached and acquire frame if so
if (auto intensityBuff = pcloudProducer.intensityStimulusBuffer.load(
if (auto intensityBuff = intensityStimulusBuffer.load(
std::memory_order_acquire))
{
size_t intensityRingbuffIndex = intensityBuff
->ringBuffer.getIndexToProduceInto();
StimulusFrame& intensityStimFrame = intensityBuff
StimulusFrame& intensityStimFrameRef = intensityBuff
->ringBuffer.getDataAtSlot(
intensityRingbuffIndex);
intensityStimFrame.lock.writeAcquire();
context->intensityStimFrame = std::make_optional(
std::ref(intensityStimFrame));
intensityStimFrameRef.lock.writeAcquire();
intensityStimFrame = std::make_optional(
std::ref(intensityStimFrameRef));
}
else {
context->intensityStimFrame = std::nullopt;
intensityStimFrame = std::nullopt;
}
// Check if light ambience buffer is attached and acquire frame if so
std::optional<AmbienceProductionDesc> lightAmbienceProductionDescDesc;
if (auto lightAmbienceBuff =
pcloudProducer.lightAmbienceStimulusBuffer.load(
lightAmbienceStimulusBuffer.load(
std::memory_order_acquire))
{
size_t lightAmbienceRingbuffIndex = lightAmbienceBuff
->ringBuffer.getIndexToProduceInto();
StimulusFrame& lightAmbienceStimFrame = lightAmbienceBuff
StimulusFrame& lightAmbienceStimFrameRef = lightAmbienceBuff
->ringBuffer.getDataAtSlot(lightAmbienceRingbuffIndex);
lightAmbienceStimFrame.lock.writeAcquire();
context->lightAmbienceStimFrame = std::make_optional(
std::ref(lightAmbienceStimFrame));
lightAmbienceStimFrameRef.lock.writeAcquire();
lightAmbienceStimFrame = std::make_optional(
std::ref(lightAmbienceStimFrameRef));
lightAmbienceProductionDescDesc = AmbienceProductionDesc{
std::ref(lightAmbienceStimFrame),
std::ref(lightAmbienceStimFrameRef),
lightAmbienceBuff->passbandCountGtComparator};
}
else {
context->lightAmbienceStimFrame = std::nullopt;
lightAmbienceStimFrame = std::nullopt;
}
// Check if dark ambience buffer is attached and acquire frame if so
std::optional<AmbienceProductionDesc> darkAmbienceProductionDescDesc;
if (auto darkAmbienceBuff =
pcloudProducer.darkAmbienceStimulusBuffer.load(
darkAmbienceStimulusBuffer.load(
std::memory_order_acquire))
{
size_t darkAmbienceRingbuffIndex = darkAmbienceBuff
->ringBuffer.getIndexToProduceInto();
StimulusFrame& darkAmbienceStimFrame = darkAmbienceBuff
StimulusFrame& darkAmbienceStimFrameRef = darkAmbienceBuff
->ringBuffer.getDataAtSlot(darkAmbienceRingbuffIndex);
darkAmbienceStimFrame.lock.writeAcquire();
context->darkAmbienceStimFrame = std::make_optional(
std::ref(darkAmbienceStimFrame));
darkAmbienceStimFrameRef.lock.writeAcquire();
darkAmbienceStimFrame = std::make_optional(
std::ref(darkAmbienceStimFrameRef));
darkAmbienceProductionDescDesc = AmbienceProductionDesc{
std::ref(darkAmbienceStimFrame),
std::ref(darkAmbienceStimFrameRef),
darkAmbienceBuff->passbandCountLtComparator};
}
else {
context->darkAmbienceStimFrame = std::nullopt;
darkAmbienceStimFrame = std::nullopt;
}
pcloudProducer.openClCollatingAndMeshingEngine.compactCollateAndMeshFrameReq(
loop, stimulusFrame,
context->intensityStimFrame,
std::move(lightAmbienceProductionDescDesc),
std::move(darkAmbienceProductionDescDesc),
{context, std::bind(
&ProduceFrameReq::produceFrameReq3_compactCollateDone,
context.get(), context,
std::placeholders::_1, std::placeholders::_2)});
}
void produceFrameReq3_compactCollateDone(
[[maybe_unused]] std::shared_ptr<ProduceFrameReq> context,
bool success, StimulusFrame& /*stimulusFrame*/)
{
bool compactCollateSuccess = co_await
openClCollatingAndMeshingEngine.compactCollateAndMeshFrameCReq(
frameAssemblyResult, stimulusFrame,
intensityStimFrame,
std::move(lightAmbienceProductionDescDesc),
std::move(darkAmbienceProductionDescDesc));
// produceFrameReq3_compactCollateDone
#if SMO_DEBUG_PCLOUD_AMBIENCE_INTRIN
uint32_t logLightPassbandCount = 0;
uint32_t logDarkPassbandCount = 0;
bool logLightAmbience = false;
bool logDarkAmbience = false;
if (success)
if (compactCollateSuccess)
{
if (context->lightAmbienceStimFrame.has_value())
if (lightAmbienceStimFrame.has_value())
{
logLightPassbandCount = *reinterpret_cast<const uint32_t*>(
context->lightAmbienceStimFrame->get().slotDesc.vaddr);
lightAmbienceStimFrame->get().slotDesc.vaddr);
logLightAmbience = true;
}
if (context->darkAmbienceStimFrame.has_value())
if (darkAmbienceStimFrame.has_value())
{
logDarkPassbandCount = *reinterpret_cast<const uint32_t*>(
context->darkAmbienceStimFrame->get().slotDesc.vaddr);
darkAmbienceStimFrame->get().slotDesc.vaddr);
logDarkAmbience = true;
}
}
#endif
// Release intensity frame if it was used
if (context->intensityStimFrame.has_value()) {
context->intensityStimFrame->get().lock.writeRelease();
}
// Release ambience frames if they were used
if (context->lightAmbienceStimFrame.has_value()) {
context->lightAmbienceStimFrame->get().lock.writeRelease();
}
if (context->darkAmbienceStimFrame.has_value()) {
context->darkAmbienceStimFrame->get().lock.writeRelease();
}
// Release intensity frame if it was used
if (intensityStimFrame.has_value()) {
intensityStimFrame->get().lock.writeRelease();
}
// Release ambience frames if they were used
if (lightAmbienceStimFrame.has_value()) {
lightAmbienceStimFrame->get().lock.writeRelease();
}
if (darkAmbienceStimFrame.has_value()) {
darkAmbienceStimFrame->get().lock.writeRelease();
}
sscl::SpinLock::Guard guard(
pcloudProducer.stimulusProducerCanceler.s.lock);
if (pcloudProducer.stimulusProducerCanceler
.isCancellationRequestedUnlocked())
{
callOriginalCallback();
return;
}
{
sscl::SpinLock::Guard guard(stimulusProducerCanceler.s.lock);
if (stimulusProducerCanceler.isCancellationRequestedUnlocked())
{ co_return; }
if (!success) {
std::cerr << __func__ << ": Failed to compact and collate frame" << std::endl;
if (!compactCollateSuccess) {
std::cerr << "produceFrameReq3_compactCollateDone"
<< ": Failed to compact and collate frame" << std::endl;
} else
{
guard.unlockPrematurely();
if (pcloudProducer.pcloudFrameDumper.isEnabled())
if (pcloudFrameDumper.isEnabled())
{
try
{
pcloudProducer.pcloudFrameDumper.dumpProducedFrame(
*pcloudProducer.device,
pcloudProducer.collationBuffer,
context->frameAssemblyResult);
pcloudFrameDumper.dumpProducedFrame(
*device, collationBuffer,
frameAssemblyResult);
}
catch (const std::exception& e)
{
@@ -653,7 +641,7 @@ public:
if (logLightAmbience)
{
auto lightBuff =
pcloudProducer.lightAmbienceStimulusBuffer.load(
lightAmbienceStimulusBuffer.load(
std::memory_order_acquire);
if (lightBuff)
{
@@ -687,7 +675,7 @@ public:
if (logDarkAmbience)
{
auto darkBuff =
pcloudProducer.darkAmbienceStimulusBuffer.load(
darkAmbienceStimulusBuffer.load(
std::memory_order_acquire);
if (darkBuff)
{
@@ -728,12 +716,12 @@ public:
std::chrono::duration_cast<std::chrono::milliseconds>(
logNow.time_since_epoch()) % 1000;
auto assemblyDuration =
pcloudProducer.ioUringAssemblyEngine.getAssemblyDuration();
ioUringAssemblyEngine.getAssemblyDuration();
auto compactDuration =
pcloudProducer.openClCollatingAndMeshingEngine
openClCollatingAndMeshingEngine
.getCompactKernelDuration();
auto collateDuration =
pcloudProducer.openClCollatingAndMeshingEngine
openClCollatingAndMeshingEngine
.getCollateKernelDuration();
std::cout << std::put_time(std::localtime(&logTime), "%T")
<< '.' << std::setfill('0') << std::setw(3)
@@ -745,29 +733,9 @@ public:
<< "ms" << std::endl;
#endif
}
callOriginalCallback();
}
};
void PcloudStimulusProducer::produceFrameReq(
sscl::cps::Callback<produceFrameReqCbFn> callback)
{
/** EXPLANATION:
* We shouldn't acquire stimulusProducerCanceler.s.lock here because
* this function is called from
* StimulusProducer::stimFrameProductionTimesliceInd(), which is already
* holding the lock.
*/
auto caller = smoHooksPtr->ComponentThread_getSelf();
auto request = std::make_shared<ProduceFrameReq>(
*this, caller, std::move(callback));
// Post the doAssemble method to the component thread
boost::asio::post(device->componentThread->getIoContext(),
STC(std::bind(
&ProduceFrameReq::produceFrameReq1_doAssemble_posted,
request.get(), request)));
co_return;
}
} // namespace stim_buff