DevMgr:newDevSpecInd: fix posting and async pattern conformance

This commit is contained in:
2025-09-15 14:20:08 -04:00
parent b768739b96
commit 674d74cfb9
2 changed files with 105 additions and 62 deletions
+92 -52
View File
@@ -6,8 +6,10 @@
#include <sstream> #include <sstream>
#include <memory> #include <memory>
#include <opts.h> #include <opts.h>
#include <asynchronousContinuation.h>
#include <deviceManager/deviceManager.h> #include <deviceManager/deviceManager.h>
#include <senseApis/senseApiManager.h> #include <senseApis/senseApiManager.h>
#include <marionette/marionette.h>
namespace smo { namespace smo {
namespace device { namespace device {
@@ -21,73 +23,72 @@ std::vector<std::shared_ptr<DeviceAttachmentSpec>>
std::vector<std::shared_ptr<Device>> std::vector<std::shared_ptr<Device>>
DeviceManager::devices; DeviceManager::devices;
// Async continuation structure class DeviceManager::NewDeviceAttachmentSpecInd
struct DeviceAttachmentContinuation { : public TargetedAsynchronousContinuation<newDeviceAttachmentSpecIndCbFn>
std::shared_ptr<DeviceAttachmentSpec> spec; {
std::function<void( public:
bool success, std::shared_ptr<Device> device, NewDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)
> callback;
DeviceAttachmentContinuation(
std::shared_ptr<DeviceAttachmentSpec> s, std::shared_ptr<DeviceAttachmentSpec> s,
std::function<void( const std::shared_ptr<ComponentThread> &caller,
bool success, std::shared_ptr<Device> device, newDeviceAttachmentSpecIndCbFn cb)
std::shared_ptr<DeviceAttachmentSpec> deviceSpec) : TargetedAsynchronousContinuation<newDeviceAttachmentSpecIndCbFn>(
> cb) caller, cb),
: spec(s), callback(cb) spec(s)
{} {}
void callOriginalCallback( void callOriginalCb(
bool success, bool success,
std::shared_ptr<Device> device, std::shared_ptr<Device> device,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec) std::shared_ptr<DeviceAttachmentSpec> deviceSpec)
{ {
callback(success, device, deviceSpec); if (originalCbFn)
}
};
const std::string DeviceManager::stringifyDeviceSpecs(void)
{ {
std::ostringstream oss; caller->getIoService().post(
std::bind(
for (const auto& spec : DeviceManager::interoceptorDeviceSpecs) { originalCbFn, success, device, deviceSpec));
oss << "Interoceptor " << spec->stringify(); }
} }
for (const auto& spec : DeviceManager::extrospectorDeviceSpecs) { public:
oss << "Extrospector " << spec->stringify(); std::shared_ptr<DeviceAttachmentSpec> spec;
}
return oss.str(); public:
} void newDeviceAttachmentSpecInd1_posted(
[[maybe_unused]] std::shared_ptr<NewDeviceAttachmentSpecInd> context
#if 0 )
void DeviceManager::newDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> spec,
std::function<void(
bool success, std::shared_ptr<Device> device,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)
> callback)
{ {
// Create async continuation sense_api::SenseApiManager::getInstance().attachSenseDeviceReq(
auto continuation = std::make_shared<DeviceAttachmentContinuation>( spec,
spec, callback); std::bind(
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2,
context.get(), context,
std::placeholders::_1, std::placeholders::_2));
}
// Check if a DeviceAttachmentSpec already matches void newDeviceAttachmentSpecInd2(
for (const auto& existingSpec : deviceAttachmentSpecs) [[maybe_unused]] std::shared_ptr<NewDeviceAttachmentSpecInd> context,
bool success,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec
)
{ {
if (!(*existingSpec == *spec)) { continue; } if (!success)
// Already exists, callback with error {
continuation->callOriginalCallback(false, nullptr, nullptr); std::cerr << __func__ << ": Attach failed for device spec "
<< deviceSpec->stringify() << std::endl;
callOriginalCb(false, nullptr, deviceSpec);
return; return;
} }
// Try to attach the sense device
try { try {
sense_api::SenseApiManager::getInstance().attachSenseDevice(spec); /** EXPLANATION:
* Remember that deviceAttachmentSpecs don't refer to devices, but
// Look for existing Device with same identifier * rather to roles that a device can enact when attached to in the
* described manner. Therefore, it's possible for multiple DA specs
* to refer to the same device.
*
* That's why we need to ensure that the device doesn't already
* exist before trying to create a new device for it.
*/
std::shared_ptr<Device> device = nullptr; std::shared_ptr<Device> device = nullptr;
for (const auto& existingDevice : devices) for (const auto& existingDevice : devices)
{ {
@@ -112,13 +113,52 @@ void DeviceManager::newDeviceAttachmentSpecInd(
deviceAttachmentSpecs.push_back(spec); deviceAttachmentSpecs.push_back(spec);
// Callback with success // Callback with success
continuation->callOriginalCallback(true, device, spec); callOriginalCb(true, device, spec);
} catch (const std::exception& e) { } catch (const std::exception& e) {
// Attach failed, callback with error // Attach failed, callback with error
continuation->callOriginalCallback(false, nullptr, nullptr); callOriginalCb(false, nullptr, spec);
} }
} }
#endif };
const std::string DeviceManager::stringifyDeviceSpecs(void)
{
std::ostringstream oss;
for (const auto& spec : DeviceManager::interoceptorDeviceSpecs) {
oss << "Interoceptor " << spec->stringify();
}
for (const auto& spec : DeviceManager::extrospectorDeviceSpecs) {
oss << "Extrospector " << spec->stringify();
}
return oss.str();
}
void DeviceManager::newDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> spec,
newDeviceAttachmentSpecIndCbFn callback)
{
// Check if a DeviceAttachmentSpec already matches
for (const auto& existingSpec : deviceAttachmentSpecs)
{
if (!(*existingSpec == *spec)) { continue; }
// Already exists, callback with error
callback(false, nullptr, spec);
return;
}
// Create async continuation
const auto& caller = ComponentThread::getSelf();
auto continuation = std::make_shared<NewDeviceAttachmentSpecInd>(
spec, caller, callback);
mrntt::mrntt.thread->getIoService().post(
std::bind(
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd1_posted,
continuation.get(), continuation));
}
} // namespace device } // namespace device
} // namespace smo } // namespace smo
@@ -38,10 +38,10 @@ public:
typedef std::function<void( typedef std::function<void(
bool success, std::shared_ptr<Device> device, bool success, std::shared_ptr<Device> device,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)> std::shared_ptr<DeviceAttachmentSpec> deviceSpec)>
deviceAttachmentSpecIndCbFn; newDeviceAttachmentSpecIndCbFn;
void newDeviceAttachmentSpecInd( void newDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> spec, std::shared_ptr<DeviceAttachmentSpec> spec,
deviceAttachmentSpecIndCbFn callback); newDeviceAttachmentSpecIndCbFn callback);
private: private:
DeviceManager() = default; DeviceManager() = default;
@@ -58,6 +58,9 @@ public:
static std::vector<std::shared_ptr<DeviceAttachmentSpec>> static std::vector<std::shared_ptr<DeviceAttachmentSpec>>
deviceAttachmentSpecs; deviceAttachmentSpecs;
static std::vector<std::shared_ptr<Device>> devices; static std::vector<std::shared_ptr<Device>> devices;
private:
class NewDeviceAttachmentSpecInd;
}; };
} // namespace device } // namespace device