SenseApis: Make attachDeviceReq async in drivers and SenseApiMgr
Slowly retrogressively making these sequences async
This commit is contained in:
@@ -53,10 +53,12 @@ static std::vector<std::shared_ptr<livoxProto1::Device>> g_attachedDevices;
|
||||
// Callback function declarations
|
||||
extern "C" int livoxGen1_initializeInd(void);
|
||||
extern "C" int livoxGen1_finalizeInd(void);
|
||||
extern "C" int livoxGen1_attachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc);
|
||||
extern "C" int livoxGen1_detachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc);
|
||||
extern "C" void livoxGen1_attachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
|
||||
smo::sense_api::sal_mlo_attachDeviceReqCbFn cb);
|
||||
extern "C" void livoxGen1_detachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
|
||||
smo::sense_api::sal_mlo_detachDeviceReqCbFn cb);
|
||||
|
||||
// Sense API descriptor
|
||||
static const SenseApiDesc livoxGen1ApiDesc = {
|
||||
@@ -151,8 +153,9 @@ extern "C" int livoxGen1_finalizeInd(void)
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
extern "C" int livoxGen1_attachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc
|
||||
extern "C" void livoxGen1_attachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
|
||||
smo::sense_api::sal_mlo_attachDeviceReqCbFn cb
|
||||
)
|
||||
{
|
||||
if (!livoxProto1.livoxProto1_getOrCreateDeviceReq)
|
||||
@@ -162,6 +165,17 @@ extern "C" int livoxGen1_attachDeviceReq(
|
||||
"not available");
|
||||
}
|
||||
|
||||
/** FIXME:
|
||||
* We should acquire a spinlock here to ensure that the device isn't added
|
||||
* in the interim while the async op executes.
|
||||
*/
|
||||
|
||||
for (const auto& dev : g_attachedDevices)
|
||||
{
|
||||
if (dev->discoveredDevice.deviceIdentifier == desc->deviceIdentifier)
|
||||
{ return; }
|
||||
}
|
||||
|
||||
// Parse integer parameters from provider params with defaults
|
||||
/* The Livox Avia will generally respond to a handshake request within
|
||||
* 50ms. So we set the handshake timeout to 300ms to be safe.
|
||||
@@ -233,59 +247,47 @@ extern "C" int livoxGen1_attachDeviceReq(
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic<bool> callbackCalled{false};
|
||||
std::shared_ptr<livoxProto1::Device> device = nullptr;
|
||||
std::shared_ptr<ComponentThread> self = smoHooksPtr->
|
||||
ComponentThread_getSelf();
|
||||
|
||||
(*livoxProto1.livoxProto1_getOrCreateDeviceReq)(
|
||||
desc->deviceSelector, // deviceIdentifier (broadcast code)
|
||||
smoThreadingModelDesc.componentThread,
|
||||
handshakeTimeoutMs, retryDelayMs,
|
||||
smoIp, smoSubnetNbits,
|
||||
dataPort, cmdPort, imuPort,
|
||||
[&callbackCalled, &device, self](
|
||||
[desc, cb](
|
||||
bool success, std::shared_ptr<livoxProto1::Device> dev) -> void
|
||||
{
|
||||
callbackCalled.store(true);
|
||||
device = ((success) ? dev : nullptr);
|
||||
// Ensure that the bridging loop below will get awakened.
|
||||
self->getIoService().post([]{});
|
||||
if (!dev)
|
||||
{
|
||||
std::cerr << __func__ << ": Failed to create Livox device: "
|
||||
<< desc->deviceSelector << std::endl;
|
||||
cb(false);
|
||||
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);
|
||||
}
|
||||
);
|
||||
|
||||
/** EXPLANATION:
|
||||
* Bridge the async call by dequeueing until callbackCalled is true.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
self->getIoService().run_one();
|
||||
if (callbackCalled.load() || self->getIoService().stopped())
|
||||
{ break; }
|
||||
}
|
||||
|
||||
if (!device)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Failed to create Livox device: "
|
||||
+ desc->deviceSelector);
|
||||
}
|
||||
|
||||
g_attachedDevices.push_back(device);
|
||||
if (1 || OptionParser::getOptions().verbose)
|
||||
{
|
||||
std::cout << __func__ << ": Successfully attached Livox device: "
|
||||
<< desc->deviceSelector << " (ID: " << desc->deviceIdentifier
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
extern "C" int livoxGen1_detachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc
|
||||
extern "C" void livoxGen1_detachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
|
||||
smo::sense_api::sal_mlo_detachDeviceReqCbFn cb
|
||||
)
|
||||
{
|
||||
/** FIXME:
|
||||
* We should acquire a spinlock here to ensure that iterator doesn't become
|
||||
* invalid in the interim while the async op executes. In the meantime,
|
||||
* we'll repeat the search in the callback.
|
||||
*/
|
||||
|
||||
// Find and remove the device from our collection
|
||||
auto it = std::find_if(g_attachedDevices.begin(), g_attachedDevices.end(),
|
||||
[&desc](const std::shared_ptr<livoxProto1::Device>& dev) {
|
||||
@@ -304,44 +306,52 @@ extern "C" int livoxGen1_detachDeviceReq(
|
||||
|
||||
if (it == g_attachedDevices.end())
|
||||
{
|
||||
std::cerr << __func__ << ": Device not found for detachment: "
|
||||
<< desc->deviceIdentifier << "\n";
|
||||
return -1; // Device not found
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) +
|
||||
": Device not found for detachment: " + desc->deviceIdentifier);
|
||||
}
|
||||
|
||||
std::atomic<bool> callbackCalled{false};
|
||||
bool retVal = false;
|
||||
std::shared_ptr<ComponentThread> self = smoHooksPtr->
|
||||
ComponentThread_getSelf();
|
||||
|
||||
(*livoxProto1.livoxProto1_destroyDeviceReq)(
|
||||
*it,
|
||||
[&callbackCalled, &retVal, self](bool success)
|
||||
[cb, desc](bool success)
|
||||
{
|
||||
callbackCalled.store(true);
|
||||
retVal = success;
|
||||
self->getIoService().post([]{});
|
||||
if (!success)
|
||||
{
|
||||
std::cerr << __func__ << ": Failed to destroy Livox device: "
|
||||
<< desc->deviceIdentifier << "\n";
|
||||
cb(false);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
g_attachedDevices.erase(eraseIt);
|
||||
std::cout << __func__ << ": Successfully detached Livox device: "
|
||||
<< desc->deviceIdentifier << "\n";
|
||||
|
||||
cb(success);
|
||||
}
|
||||
);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
self->getIoService().run_one();
|
||||
if (callbackCalled.load() || self->getIoService().stopped())
|
||||
{ break; }
|
||||
}
|
||||
|
||||
if (!retVal)
|
||||
{
|
||||
std::cerr << __func__ << ": Failed to destroy Livox device: "
|
||||
<< desc->deviceIdentifier << std::endl;
|
||||
}
|
||||
|
||||
g_attachedDevices.erase(it);
|
||||
std::cout << __func__ << ": Successfully detached Livox device: "
|
||||
<< desc->deviceIdentifier << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Exported function
|
||||
|
||||
@@ -273,8 +273,9 @@ static int xcbWindow_finalizeInd(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xcbWindow_attachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc
|
||||
static void xcbWindow_attachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& desc,
|
||||
smo::sense_api::sal_mlo_attachDeviceReqCbFn cb
|
||||
)
|
||||
{
|
||||
g_attachedWindows.emplace_back(
|
||||
@@ -283,11 +284,13 @@ static int xcbWindow_attachDeviceReq(
|
||||
std::cout << __func__ << ": Attached X11 window:\n "
|
||||
<< g_attachedWindows.back()->stringify()
|
||||
<< "\n";
|
||||
return 0;
|
||||
|
||||
cb(true);
|
||||
}
|
||||
|
||||
static int xcbWindow_detachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec
|
||||
static void xcbWindow_detachDeviceReq(
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
|
||||
smo::sense_api::sal_mlo_detachDeviceReqCbFn cb
|
||||
)
|
||||
{
|
||||
auto it = std::find_if(g_attachedWindows.begin(), g_attachedWindows.end(),
|
||||
@@ -298,15 +301,18 @@ static int xcbWindow_detachDeviceReq(
|
||||
|
||||
if (it == g_attachedWindows.end())
|
||||
{
|
||||
std::cerr << __func__ << ": Device not found for detachment:\n"
|
||||
<< spec->stringify() << "\n";
|
||||
return -1;
|
||||
std::cerr << __func__ << ": Device not found for detachment:\n"
|
||||
<< spec->stringify() << "\n";
|
||||
|
||||
cb(false);
|
||||
return;
|
||||
}
|
||||
|
||||
g_attachedWindows.erase(it);
|
||||
std::cout << __func__ << ": Detached X11 window device:\n"
|
||||
<< spec->stringify() << "\n";
|
||||
return 0;
|
||||
|
||||
cb(true);
|
||||
}
|
||||
|
||||
// SenseApi descriptor
|
||||
|
||||
Reference in New Issue
Block a user