From e6b8d3e85d63190a9bf63f7b181d46a7210d6337 Mon Sep 17 00:00:00 2001 From: Hayodea Hekol Date: Sat, 27 Sep 2025 23:16:46 -0400 Subject: [PATCH] DevMgr: Move at/detachSenseDevs[FromSpecs] into DeviceMgr:: This is logically cleaner and it begins preparing our next set of restructuring changes. To wit: we're revamping the device manager to distinguish between devices and their roles. --- smocore/body/body.cpp | 6 +- smocore/deviceManager/deviceManager.cpp | 337 +++++++++++++++++- smocore/include/deviceManager/deviceManager.h | 27 ++ smocore/include/senseApis/senseApiManager.h | 25 -- smocore/senseApis/senseApiManager.cpp | 330 ----------------- 5 files changed, 366 insertions(+), 359 deletions(-) diff --git a/smocore/body/body.cpp b/smocore/body/body.cpp index f536063..0c30b71 100644 --- a/smocore/body/body.cpp +++ b/smocore/body/body.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace smo { namespace body { @@ -77,8 +78,7 @@ public: std::cout << __func__ << ": About to attachAllSenseDevicesFromSpecs" << '\n'; } - sense_api::SenseApiManager::getInstance() - .attachAllSenseDevicesFromSpecsReq( + device::DeviceManager::getInstance().attachAllSenseDevicesFromSpecsReq( {context, std::bind( &InitializeReq::initializeReq2, context.get(), context, @@ -117,7 +117,7 @@ public: } std::cout << "Mrntt: About to detach all sense devices." << "\n"; - sense_api::SenseApiManager::getInstance().detachAllSenseDevicesReq( + device::DeviceManager::getInstance().detachAllSenseDevicesReq( {context, std::bind( &FinalizeReq::finalizeReq2, context.get(), context, diff --git a/smocore/deviceManager/deviceManager.cpp b/smocore/deviceManager/deviceManager.cpp index e549c59..641fc17 100644 --- a/smocore/deviceManager/deviceManager.cpp +++ b/smocore/deviceManager/deviceManager.cpp @@ -8,9 +8,11 @@ #include #include #include +#include #include #include #include +#include namespace smo { namespace device { @@ -60,7 +62,7 @@ public: [[maybe_unused]] std::shared_ptr context ) { - sense_api::SenseApiManager::getInstance().attachSenseDeviceReq( + DeviceManager::getInstance().attachSenseDeviceReq( spec, {context, std::bind( &NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2, @@ -148,5 +150,338 @@ void DeviceManager::newDeviceAttachmentSpecInd( continuation.get(), continuation)); } +class DeviceManager::AttachSenseDeviceReq +: public PostedAsynchronousContinuation +{ +public: + AttachSenseDeviceReq( + const std::shared_ptr& spec, + const std::shared_ptr &caller, + Callback cb) + : PostedAsynchronousContinuation( + caller, cb), + spec(spec) + {} + +public: + void attachSenseDeviceReq1_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + if (caller->id != ComponentThread::MRNTT) + { + std::cerr << std::string(__func__) + << ": executed on non-mrntt thread: " + << caller->name << std::endl; + callOriginalCb(false, spec); + return; + } + + /** FIXME: + * We should acquire a spinlock here to ensure that the device isn't + * added in the interim while the async op executes. + */ + auto libOpt = sense_api::SenseApiManager::getInstance() + .getSenseApiLibByApiName(spec->api); + + if (!libOpt) + { + std::cerr << std::string(__func__) + ": No library found for API '" + << spec->api << "'" << std::endl; + callOriginalCb(false, spec); + return; + } + + auto& lib = *libOpt.value(); + if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq) + { + std::cerr << std::string(__func__) + ": attachDeviceReq() is NULL " + "for library '" << lib.libraryPath << "'" << std::endl; + callOriginalCb(false, spec); + return; + } + + /** EXPLANATION: + * We pass in either the body or world thread here, depending on whether + * the device is an introspector (idev) or extrospector (edev). + * + * Introspectors are attached to the body thread; extrospectors are + * attached to the world thread. + */ + std::shared_ptr threadForAttachment; + if (spec->sensorType == 'e') + { + threadForAttachment = mind::globalMind->world.thread; + std::cout << __func__ << ": Attaching edev " + << spec->deviceIdentifier << " to world thread" << "\n"; + } + else + { + threadForAttachment = mind::globalMind->body.thread; + std::cout << __func__ << ": Attaching non-edev " + << spec->deviceIdentifier << " to body thread" << "\n"; + } + + lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq( + spec, threadForAttachment, + {context, std::bind( + &AttachSenseDeviceReq::attachSenseDeviceReq2, + context.get(), context, + std::placeholders::_1, std::placeholders::_2)}); + } + + void attachSenseDeviceReq2( + [[maybe_unused]] std::shared_ptr context, + bool success, + std::shared_ptr deviceSpec + ) + { + callOriginalCb(success, deviceSpec); + } + + void detachSenseDeviceReq1_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + if (caller->id != ComponentThread::MRNTT) + { + std::cerr << std::string(__func__) + << ": executed on non-mrntt thread: " + << caller->name << std::endl; + callOriginalCb(false, spec); + return; + } + + /** FIXME: + * We should acquire a spinlock here to ensure that the device isn't + * removed in the interim while the async op executes. + */ + auto libOpt = sense_api::SenseApiManager::getInstance() + .getSenseApiLibByApiName(spec->api); + + if (!libOpt) + { + std::cerr << std::string(__func__) + ": No library found for API '" + << spec->api << "'" << std::endl; + callOriginalCb(false, spec); + return; + } + auto& lib = *libOpt.value(); + if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq) + { + std::cerr << std::string(__func__) + ": detachDeviceReq() is NULL " + "for library '" << lib.libraryPath << "'" << std::endl; + callOriginalCb(false, spec); + return; + } + lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq( + spec, + {context, std::bind( + &DetachSenseDeviceReq::detachSenseDeviceReq2, + context.get(), context, + std::placeholders::_1, std::placeholders::_2)}); + } + + void detachSenseDeviceReq2( + [[maybe_unused]] std::shared_ptr context, + bool success, + std::shared_ptr deviceSpec + ) + { + callOriginalCb(success, deviceSpec); + } + +public: + std::shared_ptr spec; +}; + +void DeviceManager::attachSenseDeviceReq( + const std::shared_ptr& spec, + Callback cb + ) +{ + const auto& caller = ComponentThread::getSelf(); + auto request = std::make_shared( + spec, caller, cb); + + mrntt::mrntt.thread->getIoService().post( + std::bind( + &AttachSenseDeviceReq::attachSenseDeviceReq1_posted, + request.get(), request)); +} + +void DeviceManager::detachSenseDeviceReq( + const std::shared_ptr& spec, + Callback cb + ) +{ + const auto& caller = ComponentThread::getSelf(); + auto request = std::make_shared( + spec, caller, cb); + + mrntt::mrntt.thread->getIoService().post( + std::bind( + &DetachSenseDeviceReq::detachSenseDeviceReq1_posted, + request.get(), request)); +} + +class DeviceManager::AttachAllSenseDevicesFromSpecsReq +: public PostedAsynchronousContinuation< + attachAllSenseDevicesFromSpecsReqCbFn> +{ +public: + AttachAllSenseDevicesFromSpecsReq( + const unsigned int totalNSpecs, + const std::shared_ptr& caller, + Callback cb) + : PostedAsynchronousContinuation( + caller, cb), + loop(totalNSpecs) + {} + +public: + void attachAllSenseDevicesFromSpecsReq1_posted( + [[maybe_unused]] std::shared_ptr + context + ) + { + for (const auto& spec : DeviceManager::deviceAttachmentSpecs) + { + DeviceManager::getInstance().attachSenseDeviceReq( + spec, + {context, std::bind( + &AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq2, + context.get(), context, + std::placeholders::_1, std::placeholders::_2)}); + } + } + + // Callback methods for the attachment sequence + void attachAllSenseDevicesFromSpecsReq2( + std::shared_ptr context, + bool success, std::shared_ptr spec + ) + { + if (!success) + { + std::cerr << __func__ << ": Failed to attach device: " + << spec->deviceIdentifier << "\n"; + // Fallthrough. + } + + if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo( + success)) + { + return; + } + + if (OptionParser::getOptions().verbose) + { + std::cout << __func__ << ": " << context->loop.nSucceeded.load() + << " devices attached, " + << context->loop.nFailed.load() << " devices failed\n"; + } + + context->callOriginalCb(loop); + } + +public: + AsynchronousLoop loop; +}; + +void DeviceManager::attachAllSenseDevicesFromSpecsReq( + Callback cb + ) +{ + if (DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0) + { + AsynchronousLoop tmp(0); + cb.callbackFn(tmp); + return; + } + + const auto& caller = ComponentThread::getSelf(); + auto request = std::make_shared( + DeviceManager::getInstance().deviceAttachmentSpecs.size(), + caller, std::move(cb)); + + mrntt::mrntt.thread->getIoService().post( + std::bind( + &AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq1_posted, + request.get(), request)); +} + +class DeviceManager::DetachAllSenseDevicesReq +: public AttachAllSenseDevicesFromSpecsReq +{ +public: + using AttachAllSenseDevicesFromSpecsReq::AttachAllSenseDevicesFromSpecsReq; + + void detachAllSenseDevicesReq1_posted( + [[maybe_unused]] std::shared_ptr context + ) + { + for (const auto& spec : DeviceManager::deviceAttachmentSpecs) + { + DeviceManager::getInstance().detachSenseDeviceReq( + spec, + {context, std::bind( + &DetachAllSenseDevicesReq::detachAllSenseDevicesReq2, + context.get(), context, + std::placeholders::_1, std::placeholders::_2)}); + } + } + + void detachAllSenseDevicesReq2( + std::shared_ptr context, + bool success, std::shared_ptr spec + ) + { + if (!success) + { + std::cerr << __func__ << ": Failed to detach device: " + << spec->deviceIdentifier << "\n"; + // Fallthrough. + } + + if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo( + success)) + { + return; + } + + if (OptionParser::getOptions().verbose) + { + std::cout << __func__ << ": " << context->loop.nSucceeded.load() + << " devices detached, " + << context->loop.nFailed.load() << " devices failed\n"; + } + + context->callOriginalCb(loop); + } +}; + +void DeviceManager::detachAllSenseDevicesReq( + Callback cb + ) +{ + if (DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0) + { + AsynchronousLoop tmp(0); + cb.callbackFn(tmp); + return; + } + + const auto& caller = ComponentThread::getSelf(); + auto request = std::make_shared( + DeviceManager::getInstance().deviceAttachmentSpecs.size(), + caller, std::move(cb)); + + mrntt::mrntt.thread->getIoService().post( + std::bind( + &DetachAllSenseDevicesReq::detachAllSenseDevicesReq1_posted, + request.get(), request)); +} + } // namespace device } // namespace smo diff --git a/smocore/include/deviceManager/deviceManager.h b/smocore/include/deviceManager/deviceManager.h index 1beb771..82c5094 100644 --- a/smocore/include/deviceManager/deviceManager.h +++ b/smocore/include/deviceManager/deviceManager.h @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include #include @@ -44,6 +46,27 @@ public: std::shared_ptr spec, Callback callback); + // Device attachment/detachment methods moved from SenseApiManager + typedef sense_api::sal_mlo_attachDeviceReqCbFn attachSenseDeviceReqCbFn; + typedef sense_api::sal_mlo_detachDeviceReqCbFn detachSenseDeviceReqCbFn; + + void attachSenseDeviceReq( + const std::shared_ptr& spec, + Callback cb); + void detachSenseDeviceReq( + const std::shared_ptr& spec, + Callback cb); + + typedef std::function + attachAllSenseDevicesFromSpecsReqCbFn; + typedef std::function + detachAllSenseDevicesReqCbFn; + + void attachAllSenseDevicesFromSpecsReq( + Callback cb); + void detachAllSenseDevicesReq( + Callback cb); + private: DeviceManager() = default; ~DeviceManager() = default; @@ -62,6 +85,10 @@ public: private: class NewDeviceAttachmentSpecInd; + class AttachSenseDeviceReq; + typedef AttachSenseDeviceReq DetachSenseDeviceReq; + class AttachAllSenseDevicesFromSpecsReq; + class DetachAllSenseDevicesReq; }; } // namespace device diff --git a/smocore/include/senseApis/senseApiManager.h b/smocore/include/senseApis/senseApiManager.h index a437ee9..ad4b761 100644 --- a/smocore/include/senseApis/senseApiManager.h +++ b/smocore/include/senseApis/senseApiManager.h @@ -50,26 +50,6 @@ public: void initializeAllSenseApiLibs(void); void finalizeAllSenseApiLibs(void); - typedef sal_mlo_attachDeviceReqCbFn attachSenseDeviceReqCbFn; - typedef sal_mlo_detachDeviceReqCbFn detachSenseDeviceReqCbFn; - - void attachSenseDeviceReq( - const std::shared_ptr& spec, - Callback cb); - void detachSenseDeviceReq( - const std::shared_ptr& spec, - Callback cb); - - typedef std::function - attachAllSenseDevicesFromSpecsReqCbFn; - typedef std::function - detachAllSenseDevicesReqCbFn; - - void attachAllSenseDevicesFromSpecsReq( - Callback cb); - void detachAllSenseDevicesReq( - Callback cb); - std::string stringifyLibs() const; private: @@ -81,11 +61,6 @@ private: std::vector> senseApiLibs; - class AttachSenseDeviceReq; - typedef AttachSenseDeviceReq DetachSenseDeviceReq; - class AttachAllSenseDevicesFromSpecsReq; - class DetachAllSenseDevicesReq; - public: static std::optional searchForLibInSmoSearchPaths( const std::string& libraryPath); diff --git a/smocore/senseApis/senseApiManager.cpp b/smocore/senseApis/senseApiManager.cpp index e31e887..cbe637b 100644 --- a/smocore/senseApis/senseApiManager.cpp +++ b/smocore/senseApis/senseApiManager.cpp @@ -262,336 +262,6 @@ void SenseApiManager::finalizeAllSenseApiLibs(void) } } -class SenseApiManager::AttachSenseDeviceReq -: public PostedAsynchronousContinuation -{ -public: - AttachSenseDeviceReq( - const std::shared_ptr& spec, - const std::shared_ptr &caller, - Callback cb) - : PostedAsynchronousContinuation( - caller, cb), - spec(spec) - {} - -public: - void attachSenseDeviceReq1_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - if (caller->id != ComponentThread::MRNTT) - { - std::cerr << std::string(__func__) - << ": executed on non-mrntt thread: " - << caller->name << std::endl; - callOriginalCb(false, spec); - return; - } - - /** FIXME: - * We should acquire a spinlock here to ensure that the device isn't - * added in the interim while the async op executes. - */ - auto libOpt = SenseApiManager::getInstance().getSenseApiLibByApiName( - spec->api); - - if (!libOpt) - { - std::cerr << std::string(__func__) + ": No library found for API '" - << spec->api << "'" << std::endl; - callOriginalCb(false, spec); - return; - } - - auto& lib = *libOpt.value(); - if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq) - { - std::cerr << std::string(__func__) + ": attachDeviceReq() is NULL " - "for library '" << lib.libraryPath << "'" << std::endl; - callOriginalCb(false, spec); - return; - } - - /** EXPLANATION: - * We pass in either the body or world thread here, depending on whether - * the device is an introspector (idev) or extrospector (edev). - * - * Introspectors are attached to the body thread; extrospectors are - * attached to the world thread. - */ - std::shared_ptr threadForAttachment; - if (spec->sensorType == 'e') - { - threadForAttachment = mind::globalMind->world.thread; - std::cout << __func__ << ": Attaching edev " - << spec->deviceIdentifier << " to world thread" << "\n"; - } - else - { - threadForAttachment = mind::globalMind->body.thread; - std::cout << __func__ << ": Attaching non-edev " - << spec->deviceIdentifier << " to body thread" << "\n"; - } - - lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq( - spec, threadForAttachment, - {context, std::bind( - &AttachSenseDeviceReq::attachSenseDeviceReq2, - context.get(), context, - std::placeholders::_1, std::placeholders::_2)}); - } - - void attachSenseDeviceReq2( - [[maybe_unused]] std::shared_ptr context, - bool success, - std::shared_ptr deviceSpec - ) - { - callOriginalCb(success, deviceSpec); - } - - void detachSenseDeviceReq1_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - if (caller->id != ComponentThread::MRNTT) - { - std::cerr << std::string(__func__) - << ": executed on non-mrntt thread: " - << caller->name << std::endl; - callOriginalCb(false, spec); - return; - } - - /** FIXME: - * We should acquire a spinlock here to ensure that the device isn't - * removed in the interim while the async op executes. - */ - auto libOpt = SenseApiManager::getInstance().getSenseApiLibByApiName( - spec->api); - if (!libOpt) - { - std::cerr << std::string(__func__) + ": No library found for API '" - << spec->api << "'" << std::endl; - callOriginalCb(false, spec); - return; - } - auto& lib = *libOpt.value(); - if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq) - { - std::cerr << std::string(__func__) + ": detachDeviceReq() is NULL " - "for library '" << lib.libraryPath << "'" << std::endl; - callOriginalCb(false, spec); - return; - } - lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq( - spec, - {context, std::bind( - &DetachSenseDeviceReq::detachSenseDeviceReq2, - context.get(), context, - std::placeholders::_1, std::placeholders::_2)}); - } - - void detachSenseDeviceReq2( - [[maybe_unused]] std::shared_ptr context, - bool success, - std::shared_ptr deviceSpec - ) - { - callOriginalCb(success, deviceSpec); - } - -public: - std::shared_ptr spec; -}; - -void SenseApiManager::attachSenseDeviceReq( - const std::shared_ptr& spec, - Callback cb - ) -{ - const auto& caller = ComponentThread::getSelf(); - auto request = std::make_shared( - spec, caller, cb); - - mrntt::mrntt.thread->getIoService().post( - std::bind( - &AttachSenseDeviceReq::attachSenseDeviceReq1_posted, - request.get(), request)); -} - -void SenseApiManager::detachSenseDeviceReq( - const std::shared_ptr& spec, - Callback cb - ) -{ - const auto& caller = ComponentThread::getSelf(); - auto request = std::make_shared( - spec, caller, cb); - - mrntt::mrntt.thread->getIoService().post( - std::bind( - &DetachSenseDeviceReq::detachSenseDeviceReq1_posted, - request.get(), request)); -} - -class SenseApiManager::AttachAllSenseDevicesFromSpecsReq -: public PostedAsynchronousContinuation< - attachAllSenseDevicesFromSpecsReqCbFn> -{ -public: - AttachAllSenseDevicesFromSpecsReq( - const unsigned int totalNSpecs, - const std::shared_ptr& caller, - Callback cb) - : PostedAsynchronousContinuation( - caller, cb), - loop(totalNSpecs) - {} - -public: - void attachAllSenseDevicesFromSpecsReq1_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs) - { - SenseApiManager::getInstance().attachSenseDeviceReq( - spec, - {context, std::bind( - &AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq2, - context.get(), context, - std::placeholders::_1, std::placeholders::_2)}); - } - } - - // Callback methods for the attachment sequence - void attachAllSenseDevicesFromSpecsReq2( - std::shared_ptr context, - bool success, std::shared_ptr spec - ) - { - if (!success) - { - std::cerr << __func__ << ": Failed to attach device: " - << spec->deviceIdentifier << "\n"; - // Fallthrough. - } - - if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo( - success)) - { - return; - } - - if (OptionParser::getOptions().verbose) - { - std::cout << __func__ << ": " << context->loop.nSucceeded.load() - << " devices attached, " - << context->loop.nFailed.load() << " devices failed\n"; - } - - context->callOriginalCb(loop); - } - -public: - AsynchronousLoop loop; -}; - -void SenseApiManager::attachAllSenseDevicesFromSpecsReq( - Callback cb - ) -{ - if (device::DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0) - { - AsynchronousLoop tmp(0); - cb.callbackFn(tmp); - return; - } - - const auto& caller = ComponentThread::getSelf(); - auto request = std::make_shared( - device::DeviceManager::getInstance().deviceAttachmentSpecs.size(), - caller, std::move(cb)); - - mrntt::mrntt.thread->getIoService().post( - std::bind( - &AttachAllSenseDevicesFromSpecsReq::attachAllSenseDevicesFromSpecsReq1_posted, - request.get(), request)); -} - -class SenseApiManager::DetachAllSenseDevicesReq -: public AttachAllSenseDevicesFromSpecsReq -{ -public: - using AttachAllSenseDevicesFromSpecsReq::AttachAllSenseDevicesFromSpecsReq; - - void detachAllSenseDevicesReq1_posted( - [[maybe_unused]] std::shared_ptr context - ) - { - for (const auto& spec : device::DeviceManager::deviceAttachmentSpecs) - { - SenseApiManager::getInstance().detachSenseDeviceReq( - spec, - {context, std::bind( - &DetachAllSenseDevicesReq::detachAllSenseDevicesReq2, - context.get(), context, - std::placeholders::_1, std::placeholders::_2)}); - } - } - - void detachAllSenseDevicesReq2( - std::shared_ptr context, - bool success, std::shared_ptr spec - ) - { - if (!success) - { - std::cerr << __func__ << ": Failed to detach device: " - << spec->deviceIdentifier << "\n"; - // Fallthrough. - } - - if (!context->loop.incrementSuccessOrFailureAndTestForCompletionDueTo( - success)) - { - return; - } - - if (OptionParser::getOptions().verbose) - { - std::cout << __func__ << ": " << context->loop.nSucceeded.load() - << " devices detached, " - << context->loop.nFailed.load() << " devices failed\n"; - } - - context->callOriginalCb(loop); - } -}; - -void SenseApiManager::detachAllSenseDevicesReq( - Callback cb - ) -{ - if (device::DeviceManager::getInstance().deviceAttachmentSpecs.size() == 0) - { - AsynchronousLoop tmp(0); - cb.callbackFn(tmp); - return; - } - - const auto& caller = ComponentThread::getSelf(); - auto request = std::make_shared( - device::DeviceManager::getInstance().deviceAttachmentSpecs.size(), - caller, std::move(cb)); - - mrntt::mrntt.thread->getIoService().post( - std::bind( - &DetachAllSenseDevicesReq::detachAllSenseDevicesReq1_posted, - request.get(), request)); -} } // namespace sense_api } // namespace smo