Async: add sh_ptr<ContinuationChainLink> to Callback<>

This change enables us to finally implement the tracing of
continuations backward from the point of acquisition for deadlock
debugging.
This commit is contained in:
2025-09-27 18:30:09 -04:00
parent 2212aec080
commit 782bcd4567
26 changed files with 384 additions and 269 deletions
+120 -65
View File
@@ -9,8 +9,10 @@
#include <opts.h>
#include <user/senseApiDesc.h>
#include <user/deviceAttachmentSpec.h>
#include <callback.h>
#include <livoxProto1/livoxProto1.h>
#include <livoxProto1/device.h>
#include <asynchronousContinuation.h>
namespace smo {
@@ -50,6 +52,105 @@ static LivoxProto1DllState livoxProto1;
// Attached Livox devices
static std::vector<std::shared_ptr<livoxProto1::Device>> g_attachedDevices;
// Continuation classes for async operations
class AttachDeviceReq
: public smo::NonPostedAsynchronousContinuation<sal_mlo_attachDeviceReqCbFn>
{
public:
AttachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
smo::Callback<sal_mlo_attachDeviceReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation<sal_mlo_attachDeviceReqCbFn>(
std::move(cb)),
spec(spec)
{}
public:
const std::shared_ptr<smo::device::DeviceAttachmentSpec> spec;
public:
void attachDeviceReq1(
std::shared_ptr<AttachDeviceReq> context,
bool success, std::shared_ptr<livoxProto1::Device> dev)
{
if (!dev)
{
std::cerr << __func__ << ": Failed to create Livox device: "
<< context->spec->deviceSelector << std::endl;
context->callOriginalCb(false, context->spec);
return;
}
g_attachedDevices.push_back(dev);
if (1 || OptionParser::getOptions().verbose)
{
std::cout << __func__ << ": Successfully attached Livox "
"device: " << context->spec->deviceSelector << " (ID: "
<< context->spec->deviceIdentifier << ")\n";
}
context->callOriginalCb(success, context->spec);
}
};
class DetachDeviceReq
: public smo::NonPostedAsynchronousContinuation<sal_mlo_detachDeviceReqCbFn>
{
public:
DetachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
smo::Callback<sal_mlo_detachDeviceReqCbFn> cb)
: smo::NonPostedAsynchronousContinuation<sal_mlo_detachDeviceReqCbFn>(
std::move(cb)),
spec(spec)
{}
public:
const std::shared_ptr<smo::device::DeviceAttachmentSpec> spec;
public:
void detachDeviceReq1(
std::shared_ptr<DetachDeviceReq> context,
bool success)
{
if (!success)
{
std::cerr << __func__ << ": Failed to destroy Livox device: "
<< context->spec->deviceIdentifier << "\n";
context->callOriginalCb(false, context->spec);
return;
}
// Find the device in g_attachedDevices and remove it.
auto eraseIt = std::find_if(
g_attachedDevices.begin(), g_attachedDevices.end(),
[context](const std::shared_ptr<livoxProto1::Device>& dev)
{
const std::string& devId = dev->discoveredDevice.deviceIdentifier;
std::string devIdPrefix = devId.substr(
0, std::min<size_t>(14, devId.size()));
return devIdPrefix == context->spec->deviceSelector.substr(
0, std::min<size_t>(14, context->spec->deviceSelector.size()));
}
);
if (eraseIt == g_attachedDevices.end())
{
std::cerr << __func__ << ": Race condition: device not found "
"in g_attachedDevices for detachment: "
<< context->spec->deviceIdentifier << "\n";
context->callOriginalCb(false, context->spec);
return;
}
g_attachedDevices.erase(eraseIt);
std::cout << __func__ << ": Successfully detached Livox device: "
<< context->spec->deviceIdentifier << "\n";
context->callOriginalCb(success, context->spec);
}
};
// Callback function declarations
extern "C" sal_mlo_initializeIndFn livoxGen1_initializeInd;
extern "C" sal_mlo_finalizeIndFn livoxGen1_finalizeInd;
@@ -152,7 +253,7 @@ extern "C" int livoxGen1_finalizeInd(void)
extern "C" void livoxGen1_attachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
const std::shared_ptr<smo::ComponentThread>& componentThread,
smo::sense_api::sal_mlo_attachDeviceReqCbFn cb
Callback<smo::sense_api::sal_mlo_attachDeviceReqCbFn> cb
)
{
if (!livoxProto1.livoxProto1_getOrCreateDeviceReq)
@@ -170,7 +271,10 @@ extern "C" void livoxGen1_attachDeviceReq(
for (const auto& dev : g_attachedDevices)
{
if (dev->discoveredDevice.deviceIdentifier == desc->deviceIdentifier)
{ return; }
{
cb.callbackFn(true, desc);
return;
}
}
// Parse integer parameters from provider params with defaults
@@ -245,39 +349,23 @@ extern "C" void livoxGen1_attachDeviceReq(
}
}
auto request = std::make_shared<AttachDeviceReq>(desc, cb);
(*livoxProto1.livoxProto1_getOrCreateDeviceReq)(
desc->deviceSelector, // deviceIdentifier (broadcast code)
componentThread,
handshakeTimeoutMs, retryDelayMs,
smoIp, smoSubnetNbits,
dataPort, cmdPort, imuPort,
[desc, cb](
bool success, std::shared_ptr<livoxProto1::Device> dev) -> void
{
if (!dev)
{
std::cerr << __func__ << ": Failed to create Livox device: "
<< desc->deviceSelector << std::endl;
cb(false, desc);
return;
}
g_attachedDevices.push_back(dev);
if (1 || OptionParser::getOptions().verbose)
{
std::cout << __func__ << ": Successfully attached Livox "
"device: " << desc->deviceSelector << " (ID: "
<< desc->deviceIdentifier << ")\n";
}
cb(success, desc);
}
);
{request, std::bind(
&AttachDeviceReq::attachDeviceReq1,
request.get(), request,
std::placeholders::_1, std::placeholders::_2)});
}
extern "C" void livoxGen1_detachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
smo::sense_api::sal_mlo_detachDeviceReqCbFn cb
Callback<smo::sense_api::sal_mlo_detachDeviceReqCbFn> cb
)
{
/** FIXME:
@@ -307,51 +395,18 @@ extern "C" void livoxGen1_detachDeviceReq(
std::cerr << std::string(__func__)
<< ": Device not found for detachment: "
<< desc->deviceIdentifier << std::endl;
cb(false, desc);
cb.callbackFn(false, desc);
return;
}
auto request = std::make_shared<DetachDeviceReq>(desc, cb);
(*livoxProto1.livoxProto1_destroyDeviceReq)(
*it,
[cb, desc](bool success)
{
if (!success)
{
std::cerr << __func__ << ": Failed to destroy Livox device: "
<< desc->deviceIdentifier << "\n";
cb(false, desc);
return;
}
// Find the device in g_attachedDevices and remove it.
auto eraseIt = std::find_if(
g_attachedDevices.begin(), g_attachedDevices.end(),
[desc](const std::shared_ptr<livoxProto1::Device>& dev)
{
const std::string& devId = dev->discoveredDevice.deviceIdentifier;
std::string devIdPrefix = devId.substr(
0, std::min<size_t>(14, devId.size()));
return devIdPrefix == desc->deviceSelector.substr(
0, std::min<size_t>(14, desc->deviceSelector.size()));
}
);
if (eraseIt == g_attachedDevices.end())
{
std::cerr << __func__ << ": Race condition: device not found "
"in g_attachedDevices for detachment: "
<< desc->deviceIdentifier << "\n";
cb(false, desc);
return;
}
g_attachedDevices.erase(eraseIt);
std::cout << __func__ << ": Successfully detached Livox device: "
<< desc->deviceIdentifier << "\n";
cb(success, desc);
}
);
{request, std::bind(
&DetachDeviceReq::detachDeviceReq1,
request.get(), request,
std::placeholders::_1)});
}
// Exported function
+6 -5
View File
@@ -8,6 +8,7 @@
#include <xcb/xcb.h>
#include <user/senseApiDesc.h>
#include <user/deviceAttachmentSpec.h>
#include <callback.h>
#include <xcbXorg/xcbXorg.h>
#include "xcbWindow.h"
@@ -276,7 +277,7 @@ static int xcbWindow_finalizeInd(void)
static void xcbWindow_attachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
const std::shared_ptr<smo::ComponentThread>& componentThread,
smo::sense_api::sal_mlo_attachDeviceReqCbFn cb
smo::Callback<smo::sense_api::sal_mlo_attachDeviceReqCbFn> cb
)
{
// Not used yet, but may be used later.
@@ -289,12 +290,12 @@ static void xcbWindow_attachDeviceReq(
<< g_attachedWindows.back()->stringify()
<< "\n";
cb(true, desc);
cb.callbackFn(true, desc);
}
static void xcbWindow_detachDeviceReq(
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
smo::sense_api::sal_mlo_detachDeviceReqCbFn cb
smo::Callback<smo::sense_api::sal_mlo_detachDeviceReqCbFn> cb
)
{
auto it = std::find_if(g_attachedWindows.begin(), g_attachedWindows.end(),
@@ -308,7 +309,7 @@ static void xcbWindow_detachDeviceReq(
std::cerr << __func__ << ": Device not found for detachment:\n"
<< spec->stringify() << "\n";
cb(false, spec);
cb.callbackFn(false, spec);
return;
}
@@ -316,7 +317,7 @@ static void xcbWindow_detachDeviceReq(
std::cout << __func__ << ": Detached X11 window device:\n"
<< spec->stringify() << "\n";
cb(true, spec);
cb.callbackFn(true, spec);
}
// SenseApi descriptor