Async: Drop-in SyncCancelerForAsyncWork without execUncancelableSegment*

We're doing this to prep for the coro port
This commit is contained in:
2026-05-30 10:52:15 -04:00
parent c7dee57072
commit f100764bd8
9 changed files with 72 additions and 91 deletions
@@ -91,10 +91,7 @@ void StimulusProducer::destroyAttachedStimulusBuffer(
void StimulusProducer::stop() void StimulusProducer::stop()
{ {
{ (void)stimulusProducerCanceler.requestStop();
sscl::SpinLock::Guard lock(shouldContinueLock);
shouldContinue = false;
}
// Cancel timer immediately // Cancel timer immediately
timer.cancel(); timer.cancel();
@@ -105,7 +102,7 @@ void StimulusProducer::stop()
void StimulusProducer::scheduleNextTimeout(int delayMs) void StimulusProducer::scheduleNextTimeout(int delayMs)
{ {
if (!shouldContinue) if (stimulusProducerCanceler.isCancellationRequestedUnlocked())
{ return; } { return; }
// Schedule the next timeout using the provided delay // Schedule the next timeout using the provided delay
@@ -131,8 +128,8 @@ void StimulusProducer::onTimeout(const boost::system::error_code& error)
return; return;
} }
sscl::SpinLock::Guard lock(shouldContinueLock); sscl::SpinLock::Guard guard(stimulusProducerCanceler.s.lock);
if (!shouldContinue) if (stimulusProducerCanceler.isCancellationRequestedUnlocked())
{ return; } { return; }
/** EXPLANATION: /** EXPLANATION:
+4 -5
View File
@@ -14,6 +14,7 @@
#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 <spinscale/spinLock.h> #include <spinscale/spinLock.h>
#include <spinscale/syncCancelerForAsyncWork.h>
#include "deviceAttachmentSpec.h" #include "deviceAttachmentSpec.h"
namespace smo { namespace smo {
@@ -41,8 +42,7 @@ public:
boost::asio::io_service& ioService_) boost::asio::io_service& ioService_)
: deviceAttachmentSpec(deviceAttachmentSpec), : deviceAttachmentSpec(deviceAttachmentSpec),
ioService(ioService_), ioService(ioService_),
shouldContinue(false), timer(ioService), timer(ioService), nDeferrals(0)
nDeferrals(0)
{} {}
virtual ~StimulusProducer() = default; virtual ~StimulusProducer() = default;
@@ -59,7 +59,7 @@ public:
std::cout << __func__ << ": Starting stimulus producer for device " std::cout << __func__ << ": Starting stimulus producer for device "
<< deviceAttachmentSpec->deviceSelector << std::endl; << deviceAttachmentSpec->deviceSelector << std::endl;
shouldContinue = true; stimulusProducerCanceler.startAcceptingWork();
nDeferrals = 0; nDeferrals = 0;
scheduleNextTimeout(); scheduleNextTimeout();
} }
@@ -109,8 +109,7 @@ public:
private: private:
boost::asio::io_service& ioService; boost::asio::io_service& ioService;
protected: protected:
sscl::SpinLock shouldContinueLock; sscl::SyncCancelerForAsyncWork stimulusProducerCanceler;
bool shouldContinue;
private: private:
boost::asio::deadline_timer timer; boost::asio::deadline_timer timer;
size_t nDeferrals; size_t nDeferrals;
+8 -9
View File
@@ -18,8 +18,7 @@ constexpr unsigned int reattachInFlightStaleThresholdMultiplier = 4;
DeviceReattacher::DeviceReattacher( DeviceReattacher::DeviceReattacher(
DeviceManager& parent, std::shared_ptr<sscl::ComponentThread> ioThread) DeviceManager& parent, std::shared_ptr<sscl::ComponentThread> ioThread)
: parent(parent), ioThread(ioThread), shouldContinue(false), : parent(parent), ioThread(ioThread), timer(ioThread->getIoService())
timer(ioThread->getIoService())
{ {
} }
@@ -41,16 +40,16 @@ mrntt::MrnttNonViralPostingInvoker DeviceReattacher::reattachKnownListCReq(
void DeviceReattacher::start() void DeviceReattacher::start()
{ {
shouldContinue = true; deviceReattacherCanceler.startAcceptingWork();
scheduleNextTimeout(); scheduleNextTimeout();
} }
void DeviceReattacher::stop() void DeviceReattacher::stop()
{ {
{ {
sscl::SpinLock::Guard lock(shouldContinueLock); sscl::SpinLock::Guard guard(deviceReattacherCanceler.s.lock);
shouldContinue = false;
reattachOpInFlight = false; reattachOpInFlight = false;
deviceReattacherCanceler.s.rsrc.shouldContinue = false;
/** EXPLANATION: /** EXPLANATION:
* Do not call reattachCReqInvoker.reset() here. Forcibly destroying * Do not call reattachCReqInvoker.reset() here. Forcibly destroying
* the invoker would tear down an in-flight reattach coroutine frame * the invoker would tear down an in-flight reattach coroutine frame
@@ -65,7 +64,7 @@ void DeviceReattacher::stop()
void DeviceReattacher::scheduleNextTimeout() void DeviceReattacher::scheduleNextTimeout()
{ {
if (!shouldContinue) { if (deviceReattacherCanceler.isCancellationRequestedUnlocked()) {
return; return;
} }
@@ -88,7 +87,7 @@ void DeviceReattacher::holdReattachCReq()
reattachLifetimeExceptionPtr, reattachLifetimeExceptionPtr,
[this]() [this]()
{ {
sscl::SpinLock::Guard lock(shouldContinueLock); sscl::SpinLock::Guard guard(deviceReattacherCanceler.s.lock);
reattachOpInFlight = false; reattachOpInFlight = false;
})); }));
} }
@@ -107,8 +106,8 @@ void DeviceReattacher::onTimeout(const boost::system::error_code& error)
return; return;
} }
sscl::SpinLock::Guard lock(shouldContinueLock); sscl::SpinLock::Guard guard(deviceReattacherCanceler.s.lock);
if (!shouldContinue) { if (deviceReattacherCanceler.isCancellationRequestedUnlocked()) {
return; return;
} }
@@ -11,7 +11,7 @@
#include <boost/asio/deadline_timer.hpp> #include <boost/asio/deadline_timer.hpp>
#include <marionette/marionetteThread.h> #include <marionette/marionetteThread.h>
#include <spinscale/multiOperationResultSet.h> #include <spinscale/multiOperationResultSet.h>
#include <spinscale/spinLock.h> #include <spinscale/syncCancelerForAsyncWork.h>
namespace smo { namespace smo {
@@ -44,8 +44,7 @@ private:
DeviceManager &parent; DeviceManager &parent;
std::shared_ptr<sscl::ComponentThread> ioThread; std::shared_ptr<sscl::ComponentThread> ioThread;
sscl::SpinLock shouldContinueLock; sscl::SyncCancelerForAsyncWork deviceReattacherCanceler;
bool shouldContinue;
boost::asio::deadline_timer timer; boost::asio::deadline_timer timer;
std::exception_ptr reattachLifetimeExceptionPtr; std::exception_ptr reattachLifetimeExceptionPtr;
std::optional<mrntt::MrnttNonViralPostingInvoker> reattachCReqInvoker; std::optional<mrntt::MrnttNonViralPostingInvoker> reattachCReqInvoker;
@@ -59,7 +59,6 @@ IoUringAssemblyEngine::IoUringAssemblyEngine(
frameAssemblyDesc(nullptr), ring{}, frameAssemblyDesc(nullptr), ring{},
eventfdFd(-1), eventfdDesc(nullptr), eventfd_value(0), eventfdFd(-1), eventfdDesc(nullptr), eventfd_value(0),
stallTimer(parent_.device->componentThread->getIoService()), stallTimer(parent_.device->componentThread->getIoService()),
shouldAcceptRequests(false),
nDgramsPerStagingBufferFrame(nDgramsPerStagingBufferFrame_), nDgramsPerStagingBufferFrame(nDgramsPerStagingBufferFrame_),
assembledSlotsTracker(nDgramsPerStagingBufferFrame_), assembledSlotsTracker(nDgramsPerStagingBufferFrame_),
randomDevice(), randomGenerator(randomDevice()) randomDevice(), randomGenerator(randomDevice())
@@ -68,14 +67,11 @@ randomDevice(), randomGenerator(randomDevice())
bool IoUringAssemblyEngine::setup() bool IoUringAssemblyEngine::setup()
{ {
// Defensive check to prevent double-calling // Defensive check to prevent double-calling
{ if (!ioUringAssemblyEngnCanceler.isCancellationRequested())
sscl::SpinLock::Guard lock(shouldAcceptRequestsLock);
if (shouldAcceptRequests)
{ {
throw std::runtime_error(std::string(__func__) + ": setup() called " throw std::runtime_error(std::string(__func__) + ": setup() called "
"while already set up"); "while already set up");
} }
}
// Get FrameAssemblyDesc from staging buffer // Get FrameAssemblyDesc from staging buffer
frameAssemblyDesc = static_cast<std::shared_ptr<FrameAssemblyDesc>>( frameAssemblyDesc = static_cast<std::shared_ptr<FrameAssemblyDesc>>(
@@ -156,7 +152,7 @@ bool IoUringAssemblyEngine::setup()
if (ret < 0) if (ret < 0)
{ goto cleanup_eventfd; } { goto cleanup_eventfd; }
shouldAcceptRequests = true; ioUringAssemblyEngnCanceler.startAcceptingWork();
return true; return true;
cleanup_eventfd: cleanup_eventfd:
@@ -229,7 +225,7 @@ void IoUringAssemblyEngine::resetAndAssembleFrame(
+ ": onCqeReady callback is invalid"); + ": onCqeReady callback is invalid");
} }
if (!shouldAcceptRequests) if (ioUringAssemblyEngnCanceler.isCancellationRequestedUnlocked())
{ {
throw std::runtime_error(std::string(__func__) throw std::runtime_error(std::string(__func__)
+ ": engine is not accepting requests"); + ": engine is not accepting requests");
@@ -321,11 +317,7 @@ void IoUringAssemblyEngine::resetAndAssembleFrame(
bool IoUringAssemblyEngine::stop() bool IoUringAssemblyEngine::stop()
{ {
// Acquire and release lock tightly around setting the flag return ioUringAssemblyEngnCanceler.requestStop();
sscl::SpinLock::Guard lock(shouldAcceptRequestsLock);
bool wasAcceptingRequests = shouldAcceptRequests;
shouldAcceptRequests = false;
return wasAcceptingRequests;
} }
void IoUringAssemblyEngine::assemblyCycleComplete() void IoUringAssemblyEngine::assemblyCycleComplete()
@@ -444,9 +436,9 @@ public:
void assembleFrameReq1_posted( void assembleFrameReq1_posted(
std::shared_ptr<AssembleFrameReq> context) std::shared_ptr<AssembleFrameReq> context)
{ {
sscl::SpinLock::Guard lock(engine.shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(engine.ioUringAssemblyEngnCanceler.s.lock);
if (!engine.shouldAcceptRequests) if (engine.ioUringAssemblyEngnCanceler.isCancellationRequestedUnlocked())
{ {
context->callOriginalCallback(false, sscl::AsynchronousLoop(0)); context->callOriginalCallback(false, sscl::AsynchronousLoop(0));
return; return;
@@ -498,9 +490,11 @@ public:
* indeed seen a SEGFAULT even in the current code with locking, so * indeed seen a SEGFAULT even in the current code with locking, so
* I'm going to hold the lock here for now. * I'm going to hold the lock here for now.
*/ */
sscl::SpinLock::Guard lock(context->engine.shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(
context->engine.ioUringAssemblyEngnCanceler.s.lock);
if (!context->engine.shouldAcceptRequests) if (context->engine.ioUringAssemblyEngnCanceler
.isCancellationRequestedUnlocked())
{ {
context->engine.assemblyCycleComplete(); context->engine.assemblyCycleComplete();
context->loop.setRemainingIterationsToFailure(); context->loop.setRemainingIterationsToFailure();
@@ -518,7 +512,8 @@ public:
void *user_data, int cqe_result) void *user_data, int cqe_result)
{ {
// NB: The lock was acquired by onEventFdRead before calling this func // NB: The lock was acquired by onEventFdRead before calling this func
if (!context->engine.shouldAcceptRequests) if (context->engine.ioUringAssemblyEngnCanceler
.isCancellationRequestedUnlocked())
{ {
context->engine.assemblyCycleComplete(); context->engine.assemblyCycleComplete();
context->loop.setRemainingIterationsToFailure(); context->loop.setRemainingIterationsToFailure();
@@ -549,7 +544,7 @@ public:
{ {
/** EXPLANATION: /** EXPLANATION:
* All branch paths that invoke this unifyig oracle function are * All branch paths that invoke this unifyig oracle function are
* expected to already hold the shouldAcceptRequestsLock before calling * expected to already hold ioUringAssemblyEngnCanceler.s.lock before calling
* it. * it.
*/ */
// Ensure we only execute once using atomic exchange // Ensure we only execute once using atomic exchange
@@ -638,8 +633,8 @@ void IoUringAssemblyEngine::assembleFrameReq(
sscl::cps::Callback<assembleFrameReqCbFn> cb) sscl::cps::Callback<assembleFrameReqCbFn> cb)
{ {
{ {
sscl::SpinLock::Guard lock(shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(ioUringAssemblyEngnCanceler.s.lock);
if (!shouldAcceptRequests) if (ioUringAssemblyEngnCanceler.isCancellationRequestedUnlocked())
{ {
cb.callbackFn(false, sscl::AsynchronousLoop(0)); cb.callbackFn(false, sscl::AsynchronousLoop(0));
return; return;
@@ -670,7 +665,7 @@ void IoUringAssemblyEngine::onEventfdRead(
* IoUringAssemblyEngine's per-assembly state isn't destroyed while this * IoUringAssemblyEngine's per-assembly state isn't destroyed while this
* handler is running. * handler is running.
*/ */
sscl::SpinLock::Guard lock(shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(ioUringAssemblyEngnCanceler.s.lock);
/** EXPLANATION: /** EXPLANATION:
* You'd think we should put check for shouldAcceptRequests here and * You'd think we should put check for shouldAcceptRequests here and
* `return` here if !shouldAcceptRequests, but we shouldn't because * `return` here if !shouldAcceptRequests, but we shouldn't because
@@ -722,7 +717,7 @@ void IoUringAssemblyEngine::onEventfdRead(
* But we do put a `return` here because we know that at this point, the * But we do put a `return` here because we know that at this point, the
* caller's callback has already been invoked. * caller's callback has already been invoked.
*/ */
if (!shouldAcceptRequests if (ioUringAssemblyEngnCanceler.isCancellationRequestedUnlocked()
|| eventfdDesc == nullptr || !eventfdDesc->is_open()) || eventfdDesc == nullptr || !eventfdDesc->is_open())
{ {
return; return;
@@ -19,7 +19,7 @@
#include <spinscale/cps/asynchronousContinuation.h> #include <spinscale/cps/asynchronousContinuation.h>
#include <spinscale/asynchronousLoop.h> #include <spinscale/asynchronousLoop.h>
#include <spinscale/cps/callback.h> #include <spinscale/cps/callback.h>
#include <spinscale/spinLock.h> #include <spinscale/syncCancelerForAsyncWork.h>
#include <user/frameAssemblyDesc.h> #include <user/frameAssemblyDesc.h>
#include <user/stagingBuffer.h> #include <user/stagingBuffer.h>
@@ -80,12 +80,7 @@ private:
boost::asio::deadline_timer stallTimer; boost::asio::deadline_timer stallTimer;
// Callback for CQE ntfns (called with user_data+result from each CQE) // Callback for CQE ntfns (called with user_data+result from each CQE)
resetAndAssembleFrameCbFn onCqeReadyCallback; resetAndAssembleFrameCbFn onCqeReadyCallback;
/** EXPLANATION: sscl::SyncCancelerForAsyncWork ioUringAssemblyEngnCanceler;
* Flag to indicate whether engine should accept new requests.
* Set by setup(), cleared by stop().
*/
sscl::SpinLock shouldAcceptRequestsLock;
bool shouldAcceptRequests;
size_t nDgramsPerStagingBufferFrame; size_t nDgramsPerStagingBufferFrame;
@@ -39,7 +39,6 @@ clAverageIntensityBufferClBuffer(nullptr),
clAssemblyBuffer(nullptr), clAssemblyBuffer(nullptr),
clCollationBuffer(nullptr), clCollationBuffer(nullptr),
clAverageIntensityBuffer(nullptr), clAverageIntensityBuffer(nullptr),
shouldAcceptRequests(false),
compactIsRunning(false), compactIsRunning(false),
collateIsRunning(false), collateIsRunning(false),
currentCompactKernelEvent(nullptr), currentCollateKernelEvent(nullptr), currentCompactKernelEvent(nullptr), currentCollateKernelEvent(nullptr),
@@ -64,14 +63,11 @@ OpenClCollatingAndMeshingEngine::~OpenClCollatingAndMeshingEngine()
bool OpenClCollatingAndMeshingEngine::setup() bool OpenClCollatingAndMeshingEngine::setup()
{ {
// Defensive check to prevent double-calling // Defensive check to prevent double-calling
{ if (!openClCollMeshEngnCanceler.isCancellationRequested())
sscl::SpinLock::Guard lock(shouldAcceptRequestsLock);
if (shouldAcceptRequests)
{ {
throw std::runtime_error(std::string(__func__) + ": setup() called " throw std::runtime_error(std::string(__func__) + ": setup() called "
"while already set up"); "while already set up");
} }
}
if (!smoHooksPtr || !smoHooksPtr->ComputeManager_getDevice) if (!smoHooksPtr || !smoHooksPtr->ComputeManager_getDevice)
{ {
@@ -202,13 +198,13 @@ bool OpenClCollatingAndMeshingEngine::setup()
clFlush(computeDevice->commandQueue); clFlush(computeDevice->commandQueue);
clFinish(computeDevice->commandQueue); clFinish(computeDevice->commandQueue);
shouldAcceptRequests = true; openClCollMeshEngnCanceler.startAcceptingWork();
return true; return true;
} }
void OpenClCollatingAndMeshingEngine::finalize() void OpenClCollatingAndMeshingEngine::finalize()
{ {
// Call stop() to set shouldAcceptRequests to false and get previous state // Call stop() to clear shouldContinue and get previous state
bool wasAcceptingRequests = stop(); bool wasAcceptingRequests = stop();
(void)wasAcceptingRequests; (void)wasAcceptingRequests;
@@ -771,11 +767,7 @@ bool OpenClCollatingAndMeshingEngine::setupCollateDgramsArgs(
bool OpenClCollatingAndMeshingEngine::stop() bool OpenClCollatingAndMeshingEngine::stop()
{ {
// Acquire and release lock tightly around setting the flag return openClCollMeshEngnCanceler.requestStop();
sscl::SpinLock::Guard lock(shouldAcceptRequestsLock);
bool wasAcceptingRequests = shouldAcceptRequests;
shouldAcceptRequests = false;
return wasAcceptingRequests;
} }
void OpenClCollatingAndMeshingEngine::compactKernelComplete(bool isFinalizing) void OpenClCollatingAndMeshingEngine::compactKernelComplete(bool isFinalizing)
@@ -1051,8 +1043,8 @@ public:
void compactCollateAndMeshFrameReq1_doCompact_posted( void compactCollateAndMeshFrameReq1_doCompact_posted(
std::shared_ptr<CompactCollateAndMeshFrameReq> context) std::shared_ptr<CompactCollateAndMeshFrameReq> context)
{ {
sscl::SpinLock::Guard lock(engine.shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(engine.openClCollMeshEngnCanceler.s.lock);
if (!engine.shouldAcceptRequests) if (engine.openClCollMeshEngnCanceler.isCancellationRequestedUnlocked())
{ {
callOriginalCallback(false); callOriginalCallback(false);
return; return;
@@ -1082,8 +1074,8 @@ public:
std::shared_ptr<CompactCollateAndMeshFrameReq> context, std::shared_ptr<CompactCollateAndMeshFrameReq> context,
cl_int compactStatus) cl_int compactStatus)
{ {
sscl::SpinLock::Guard lock(engine.shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(engine.openClCollMeshEngnCanceler.s.lock);
if (!engine.shouldAcceptRequests) if (engine.openClCollMeshEngnCanceler.isCancellationRequestedUnlocked())
{ {
/** EXPLANATION: /** EXPLANATION:
* We intentionally don't call compactKernelComplete() here because * We intentionally don't call compactKernelComplete() here because
@@ -1116,15 +1108,15 @@ public:
} }
#endif #endif
lock.unlockPrematurely(); guard.unlockPrematurely();
context->compactCollateAndMeshFrameReq3_doCollate_posted(context); context->compactCollateAndMeshFrameReq3_doCollate_posted(context);
} }
void compactCollateAndMeshFrameReq3_doCollate_posted( void compactCollateAndMeshFrameReq3_doCollate_posted(
std::shared_ptr<CompactCollateAndMeshFrameReq> context) std::shared_ptr<CompactCollateAndMeshFrameReq> context)
{ {
sscl::SpinLock::Guard lock(engine.shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(engine.openClCollMeshEngnCanceler.s.lock);
if (!engine.shouldAcceptRequests) if (engine.openClCollMeshEngnCanceler.isCancellationRequestedUnlocked())
{ {
callOriginalCallback(false); callOriginalCallback(false);
return; return;
@@ -1155,8 +1147,8 @@ public:
[[maybe_unused]] std::shared_ptr<CompactCollateAndMeshFrameReq> context, [[maybe_unused]] std::shared_ptr<CompactCollateAndMeshFrameReq> context,
cl_int collateStatus) cl_int collateStatus)
{ {
sscl::SpinLock::Guard lock(engine.shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(engine.openClCollMeshEngnCanceler.s.lock);
if (!engine.shouldAcceptRequests) if (engine.openClCollMeshEngnCanceler.isCancellationRequestedUnlocked())
{ {
/* We intentionally don't call collateKernelComplete() here for the /* We intentionally don't call collateKernelComplete() here for the
* same reason as above. * same reason as above.
@@ -1256,8 +1248,8 @@ void OpenClCollatingAndMeshingEngine::compactCollateAndMeshFrameReq(
sscl::cps::Callback<compactCollateAndMeshFrameReqCbFn> callback) sscl::cps::Callback<compactCollateAndMeshFrameReqCbFn> callback)
{ {
{ {
sscl::SpinLock::Guard lock(shouldAcceptRequestsLock); sscl::SpinLock::Guard guard(openClCollMeshEngnCanceler.s.lock);
if (!shouldAcceptRequests) if (openClCollMeshEngnCanceler.isCancellationRequestedUnlocked())
{ {
callback.callbackFn(false, stimulusFrame); callback.callbackFn(false, stimulusFrame);
return; return;
@@ -15,7 +15,7 @@
#include <CL/cl.h> #include <CL/cl.h>
#include <spinscale/asynchronousLoop.h> #include <spinscale/asynchronousLoop.h>
#include <spinscale/cps/callback.h> #include <spinscale/cps/callback.h>
#include <spinscale/spinLock.h> #include <spinscale/syncCancelerForAsyncWork.h>
#include <user/stimulusFrame.h> #include <user/stimulusFrame.h>
#include <user/stagingBuffer.h> #include <user/stagingBuffer.h>
#include <user/frameAssemblyDesc.h> #include <user/frameAssemblyDesc.h>
@@ -150,8 +150,7 @@ private:
cl_mem clAverageIntensityBuffer; cl_mem clAverageIntensityBuffer;
// State tracking // State tracking
sscl::SpinLock shouldAcceptRequestsLock; sscl::SyncCancelerForAsyncWork openClCollMeshEngnCanceler;
bool shouldAcceptRequests;
bool compactIsRunning; bool compactIsRunning;
bool collateIsRunning; bool collateIsRunning;
cl_event currentCompactKernelEvent; cl_event currentCompactKernelEvent;
@@ -464,8 +464,10 @@ public:
void produceFrameReq1_doAssemble_posted( void produceFrameReq1_doAssemble_posted(
std::shared_ptr<ProduceFrameReq> context) std::shared_ptr<ProduceFrameReq> context)
{ {
sscl::SpinLock::Guard lock(pcloudProducer.shouldContinueLock); sscl::SpinLock::Guard guard(
if (!pcloudProducer.shouldContinue) pcloudProducer.stimulusProducerCanceler.s.lock);
if (pcloudProducer.stimulusProducerCanceler
.isCancellationRequestedUnlocked())
{ {
callOriginalCallback(); callOriginalCallback();
return; return;
@@ -482,8 +484,10 @@ public:
std::shared_ptr<ProduceFrameReq> context, std::shared_ptr<ProduceFrameReq> context,
bool success, sscl::AsynchronousLoop loop) bool success, sscl::AsynchronousLoop loop)
{ {
sscl::SpinLock::Guard lock(pcloudProducer.shouldContinueLock); sscl::SpinLock::Guard guard(
if (!pcloudProducer.shouldContinue) pcloudProducer.stimulusProducerCanceler.s.lock);
if (pcloudProducer.stimulusProducerCanceler
.isCancellationRequestedUnlocked())
{ {
callOriginalCallback(); callOriginalCallback();
return; return;
@@ -615,8 +619,10 @@ public:
context->darkAmbienceStimFrame->get().lock.writeRelease(); context->darkAmbienceStimFrame->get().lock.writeRelease();
} }
sscl::SpinLock::Guard lock(pcloudProducer.shouldContinueLock); sscl::SpinLock::Guard guard(
if (!pcloudProducer.shouldContinue) pcloudProducer.stimulusProducerCanceler.s.lock);
if (pcloudProducer.stimulusProducerCanceler
.isCancellationRequestedUnlocked())
{ {
callOriginalCallback(); callOriginalCallback();
return; return;
@@ -626,7 +632,7 @@ public:
std::cerr << __func__ << ": Failed to compact and collate frame" << std::endl; std::cerr << __func__ << ": Failed to compact and collate frame" << std::endl;
} else } else
{ {
lock.unlockPrematurely(); guard.unlockPrematurely();
if (pcloudProducer.pcloudFrameDumper.isEnabled()) if (pcloudProducer.pcloudFrameDumper.isEnabled())
{ {
try try
@@ -748,7 +754,7 @@ void PcloudStimulusProducer::produceFrameReq(
sscl::cps::Callback<produceFrameReqCbFn> callback) sscl::cps::Callback<produceFrameReqCbFn> callback)
{ {
/** EXPLANATION: /** EXPLANATION:
* We shouldn't acquire the StimulusProducer::shouldContinueLock here because * We shouldn't acquire stimulusProducerCanceler.s.lock here because
* this function is called from * this function is called from
* StimulusProducer::stimFrameProductionTimesliceInd(), which is already * StimulusProducer::stimFrameProductionTimesliceInd(), which is already
* holding the lock. * holding the lock.