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
+100 -60
View File
@@ -6,8 +6,10 @@
#include <sstream>
#include <memory>
#include <opts.h>
#include <asynchronousContinuation.h>
#include <deviceManager/deviceManager.h>
#include <senseApis/senseApiManager.h>
#include <marionette/marionette.h>
namespace smo {
namespace device {
@@ -21,29 +23,101 @@ std::vector<std::shared_ptr<DeviceAttachmentSpec>>
std::vector<std::shared_ptr<Device>>
DeviceManager::devices;
// Async continuation structure
struct DeviceAttachmentContinuation {
std::shared_ptr<DeviceAttachmentSpec> spec;
std::function<void(
bool success, std::shared_ptr<Device> device,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)
> callback;
DeviceAttachmentContinuation(
class DeviceManager::NewDeviceAttachmentSpecInd
: public TargetedAsynchronousContinuation<newDeviceAttachmentSpecIndCbFn>
{
public:
NewDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> s,
std::function<void(
bool success, std::shared_ptr<Device> device,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)
> cb)
: spec(s), callback(cb)
const std::shared_ptr<ComponentThread> &caller,
newDeviceAttachmentSpecIndCbFn cb)
: TargetedAsynchronousContinuation<newDeviceAttachmentSpecIndCbFn>(
caller, cb),
spec(s)
{}
void callOriginalCallback(
void callOriginalCb(
bool success,
std::shared_ptr<Device> device,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)
{
callback(success, device, deviceSpec);
if (originalCbFn)
{
caller->getIoService().post(
std::bind(
originalCbFn, success, device, deviceSpec));
}
}
public:
std::shared_ptr<DeviceAttachmentSpec> spec;
public:
void newDeviceAttachmentSpecInd1_posted(
[[maybe_unused]] std::shared_ptr<NewDeviceAttachmentSpecInd> context
)
{
sense_api::SenseApiManager::getInstance().attachSenseDeviceReq(
spec,
std::bind(
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2,
context.get(), context,
std::placeholders::_1, std::placeholders::_2));
}
void newDeviceAttachmentSpecInd2(
[[maybe_unused]] std::shared_ptr<NewDeviceAttachmentSpecInd> context,
bool success,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec
)
{
if (!success)
{
std::cerr << __func__ << ": Attach failed for device spec "
<< deviceSpec->stringify() << std::endl;
callOriginalCb(false, nullptr, deviceSpec);
return;
}
try {
/** EXPLANATION:
* Remember that deviceAttachmentSpecs don't refer to devices, but
* 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;
for (const auto& existingDevice : devices)
{
if (existingDevice->deviceIdentifier != spec->deviceIdentifier)
{ continue; }
device = existingDevice;
break;
}
// If device doesn't exist, create a new one and add it
if (!device)
{
device = std::make_shared<Device>(spec->deviceIdentifier);
devices.push_back(device);
}
// Add DeviceAttachmentSpec to device's list
device->deviceAttachmentSpecs.push_back(spec);
// Add DeviceAttachmentSpec to DeviceManager's list
deviceAttachmentSpecs.push_back(spec);
// Callback with success
callOriginalCb(true, device, spec);
} catch (const std::exception& e) {
// Attach failed, callback with error
callOriginalCb(false, nullptr, spec);
}
}
};
@@ -62,63 +136,29 @@ const std::string DeviceManager::stringifyDeviceSpecs(void)
return oss.str();
}
#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)
newDeviceAttachmentSpecIndCbFn callback)
{
// Create async continuation
auto continuation = std::make_shared<DeviceAttachmentContinuation>(
spec, callback);
// Check if a DeviceAttachmentSpec already matches
for (const auto& existingSpec : deviceAttachmentSpecs)
{
if (!(*existingSpec == *spec)) { continue; }
// Already exists, callback with error
continuation->callOriginalCallback(false, nullptr, nullptr);
callback(false, nullptr, spec);
return;
}
// Try to attach the sense device
try {
sense_api::SenseApiManager::getInstance().attachSenseDevice(spec);
// Create async continuation
const auto& caller = ComponentThread::getSelf();
auto continuation = std::make_shared<NewDeviceAttachmentSpecInd>(
spec, caller, callback);
// Look for existing Device with same identifier
std::shared_ptr<Device> device = nullptr;
for (const auto& existingDevice : devices)
{
if (existingDevice->deviceIdentifier != spec->deviceIdentifier)
{ continue; }
device = existingDevice;
break;
}
// If device doesn't exist, create a new one and add it
if (!device)
{
device = std::make_shared<Device>(spec->deviceIdentifier);
devices.push_back(device);
}
// Add DeviceAttachmentSpec to device's list
device->deviceAttachmentSpecs.push_back(spec);
// Add DeviceAttachmentSpec to DeviceManager's list
deviceAttachmentSpecs.push_back(spec);
// Callback with success
continuation->callOriginalCallback(true, device, spec);
} catch (const std::exception& e) {
// Attach failed, callback with error
continuation->callOriginalCallback(false, nullptr, nullptr);
}
mrntt::mrntt.thread->getIoService().post(
std::bind(
&NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd1_posted,
continuation.get(), continuation));
}
#endif
} // namespace device
} // namespace smo
@@ -38,10 +38,10 @@ public:
typedef std::function<void(
bool success, std::shared_ptr<Device> device,
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)>
deviceAttachmentSpecIndCbFn;
newDeviceAttachmentSpecIndCbFn;
void newDeviceAttachmentSpecInd(
std::shared_ptr<DeviceAttachmentSpec> spec,
deviceAttachmentSpecIndCbFn callback);
newDeviceAttachmentSpecIndCbFn callback);
private:
DeviceManager() = default;
@@ -58,6 +58,9 @@ public:
static std::vector<std::shared_ptr<DeviceAttachmentSpec>>
deviceAttachmentSpecs;
static std::vector<std::shared_ptr<Device>> devices;
private:
class NewDeviceAttachmentSpecInd;
};
} // namespace device