diff --git a/smocore/deviceManager/deviceManager.cpp b/smocore/deviceManager/deviceManager.cpp index 5d5c4e2..b8d0f42 100644 --- a/smocore/deviceManager/deviceManager.cpp +++ b/smocore/deviceManager/deviceManager.cpp @@ -6,8 +6,10 @@ #include #include #include +#include #include #include +#include namespace smo { namespace device { @@ -21,29 +23,101 @@ std::vector> std::vector> DeviceManager::devices; -// Async continuation structure -struct DeviceAttachmentContinuation { - std::shared_ptr spec; - std::function device, - std::shared_ptr deviceSpec) - > callback; - - DeviceAttachmentContinuation( +class DeviceManager::NewDeviceAttachmentSpecInd +: public TargetedAsynchronousContinuation +{ +public: + NewDeviceAttachmentSpecInd( std::shared_ptr s, - std::function device, - std::shared_ptr deviceSpec) - > cb) - : spec(s), callback(cb) + const std::shared_ptr &caller, + newDeviceAttachmentSpecIndCbFn cb) + : TargetedAsynchronousContinuation( + caller, cb), + spec(s) {} - void callOriginalCallback( + void callOriginalCb( bool success, std::shared_ptr device, std::shared_ptr deviceSpec) { - callback(success, device, deviceSpec); + if (originalCbFn) + { + caller->getIoService().post( + std::bind( + originalCbFn, success, device, deviceSpec)); + } + } + +public: + std::shared_ptr spec; + +public: + void newDeviceAttachmentSpecInd1_posted( + [[maybe_unused]] std::shared_ptr 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 context, + bool success, + std::shared_ptr 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 = 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(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 spec, - std::function device, - std::shared_ptr deviceSpec) - > callback) + newDeviceAttachmentSpecIndCbFn callback) { - // Create async continuation - auto continuation = std::make_shared( - 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( + spec, caller, callback); - // Look for existing Device with same identifier - std::shared_ptr 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(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 diff --git a/smocore/include/deviceManager/deviceManager.h b/smocore/include/deviceManager/deviceManager.h index ac0a550..d63740f 100644 --- a/smocore/include/deviceManager/deviceManager.h +++ b/smocore/include/deviceManager/deviceManager.h @@ -38,10 +38,10 @@ public: typedef std::function device, std::shared_ptr deviceSpec)> - deviceAttachmentSpecIndCbFn; + newDeviceAttachmentSpecIndCbFn; void newDeviceAttachmentSpecInd( std::shared_ptr spec, - deviceAttachmentSpecIndCbFn callback); + newDeviceAttachmentSpecIndCbFn callback); private: DeviceManager() = default; @@ -58,6 +58,9 @@ public: static std::vector> deviceAttachmentSpecs; static std::vector> devices; + +private: + class NewDeviceAttachmentSpecInd; }; } // namespace device