#include #include #include #include #include #include #include #include #include #include #include namespace smo { namespace body { Body::Body(Mind &parent, const std::shared_ptr &thread) : MindComponent(parent, thread) { } class Body::InitializeReq : public PostedAsynchronousContinuation { public: InitializeReq( Mind &parent, const std::shared_ptr &caller, Callback callback) : PostedAsynchronousContinuation(caller, callback), parent(parent) {} private: Mind &parent; public: void initializeReq1_posted( [[maybe_unused]] std::shared_ptr context ) { auto self = ComponentThread::getSelf(); if (self->id != ComponentThread::BODY) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Body thread"); } /** EXPLANATION: * The ComponentThread instance we pass in here is the one that will be * used by Senseapi libs to perform device-independent background * operations. * For example, liblivoxProto1's BroadcastListener will use this thread * to listen for UDP broadcast dgrams from Livox devices. * * We used to use Marionette, but there's a strong argument for using * Body instead since it's meant to handle device-management operations. */ stim_buff::StimBuffApiManager::getInstance() .loadAllStimBuffApiLibsFromOptions(parent.body.thread); /** EXPLANATION: * Consider body::initializeReq to have been called if even one of its * operations was executed at all, whether successfully or * unsuccessfully. */ context->parent.bodyComponentInitialized = true; std::cout << stim_buff::StimBuffApiManager::getInstance().stringifyLibs() << std::endl; if (OptionParser::getOptions().verbose) { std::cout << __func__ << ": About to initializeAllStimBuffApiLibs" << '\n'; } stim_buff::StimBuffApiManager::getInstance() .initializeAllStimBuffApiLibs(); if (OptionParser::getOptions().verbose) { std::cout << __func__ << ": About to attachAllSenseDevicesFromSpecs" << '\n'; } device::DeviceManager::getInstance() .attachAllUnattachedDevicesFromCmdlineReq( {context, std::bind( &InitializeReq::initializeReq2, context.get(), context, std::placeholders::_1)}); } void initializeReq2( [[maybe_unused]] std::shared_ptr context, smo::AsynchronousLoop &results ) { std::cout << "Mrntt: attached " << results.nSucceeded << " of " << results.nTotal << " sense devices." << "\n"; callOriginalCb(results.nSucceeded > 0); } }; class Body::FinalizeReq : public InitializeReq { public: using InitializeReq::InitializeReq; public: void finalizeReq1_posted( [[maybe_unused]] std::shared_ptr context ) { auto self = ComponentThread::getSelf(); if (self->id != ComponentThread::BODY) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Body thread"); } std::cout << "Mrntt: About to detach all sense devices." << "\n"; device::DeviceManager::getInstance().detachAllAttachedDeviceRoles( {context, std::bind( &FinalizeReq::finalizeReq2, context.get(), context, std::placeholders::_1)}); } void finalizeReq2( [[maybe_unused]] std::shared_ptr context, smo::AsynchronousLoop &results ) { std::cout << "Mrntt: Successfully detached " << results.nSucceeded << " of " << results.nTotal << " sense devices." << "\n"; std::cout << "Mrntt: About to finalize all stim buff api libs." << "\n"; stim_buff::StimBuffApiManager::getInstance().finalizeAllStimBuffApiLibs(); std::cout << "Mrntt: About to unload all stim buff api libs." << "\n"; stim_buff::StimBuffApiManager::getInstance().unloadAllStimBuffApiLibs(); callOriginalCb(results.nSucceeded == results.nTotal); } }; void Body::initializeReq(Callback callback) { auto mrntt = ComponentThread::getSelf(); if (mrntt->id != ComponentThread::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be invoked by Mrntt thread"); } auto request = std::make_shared( parent, mrntt, callback); thread->getIoService().post( STC(std::bind( &InitializeReq::initializeReq1_posted, request.get(), request))); } void Body::finalizeReq(Callback callback) { auto mrntt = ComponentThread::getSelf(); if (mrntt->id != ComponentThread::MRNTT) { std::cerr << __func__ << ": Must be invoked by Mrntt thread" << std::endl; callback.callbackFn(false); return; } if (!parent.bodyComponentInitialized) { std::cout << "Mrntt: Body component not initialized. " << "Skipping finalization." << "\n"; callback.callbackFn(true); return; } auto request = std::make_shared( parent, mrntt, callback); thread->getIoService().post( STC(std::bind( &FinalizeReq::finalizeReq1_posted, request.get(), request))); } } // namespace body } // namespace smo