#include #include #include #include #include #include #include #include #include #include namespace smo { namespace mrntt { class MarionetteComponent::MrnttLifetimeMgmtOp : public PostedAsynchronousContinuation { public: MrnttLifetimeMgmtOp( MarionetteComponent &parent, const std::shared_ptr &caller, Callback callback) : PostedAsynchronousContinuation( caller, callback), parent(parent) {} private: MarionetteComponent &parent; public: void initializeReq1_posted( [[maybe_unused]] std::shared_ptr context ) { auto self = ComponentThread::getSelf(); if (self->id != ComponentThread::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); } smo::mind::globalMind = std::make_shared(); smo::mind::globalMind->initializeReq({context, std::bind( &MrnttLifetimeMgmtOp::initializeReq2, this, context, std::placeholders::_1)}); } void initializeReq2( std::shared_ptr context, bool success ) { if (!success) { std::cerr << __func__ << ": Failed to initialize globalMind" << std::endl; context->callOriginalCb(false); return; } device::DeviceManager::getInstance().initializeDeviceReattacher(); // Call negtrinEventInd on the Director in the final callback smo::mind::globalMind->director.negtrinEventInd(); context->callOriginalCb(success); } void finalizeReq1_posted( [[maybe_unused]] std::shared_ptr context ) { auto self = ComponentThread::getSelf(); if (self->id != ComponentThread::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); } device::DeviceManager::getInstance().finalizeDeviceReattacher(); /** FIXME: * It may be necessary to add a delay here to ensure that all in-flight * timer timeouts have finished executing? Or some other mechanism. * * We need some way to ensure that in-flight timeouts don't get fired * during the finalize sequence. This is because they may depend on * state that is being finalized or has been finalized at the point * when they timeout. * * This seems to be actually happening with the delayed calls to * AttachDeviceReq::attachDeviceReq2() inside of livoxGen1.cpp. * * One tactic might be to shut down device reattacher before finalizing * and pause for a bit before continuing to shutdown other components. */ smo::mind::globalMind->finalizeReq({context, std::bind( &MrnttLifetimeMgmtOp::finalizeReq2, this, context, std::placeholders::_1)}); } void finalizeReq2( std::shared_ptr context, bool success ) { if (!success) { std::cerr << __func__ << ": globalMind finalization failed" << std::endl; context->callOriginalCb(false); return; } context->callOriginalCb(success); } }; class MarionetteComponent::TerminationEvent : public PostedAsynchronousContinuation { public: TerminationEvent( const std::shared_ptr &caller) : PostedAsynchronousContinuation( caller, {nullptr, nullptr}) {} public: void exceptionInd1_posted( [[maybe_unused]] std::shared_ptr context ) { auto self = ComponentThread::getSelf(); if (self->id != ComponentThread::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); } mrntt::mrntt.finalizeReq({nullptr, std::bind( &mrntt::marionetteFinalizeReqCb, std::placeholders::_1)}); } }; void MarionetteComponent::initializeReq( Callback callback) { auto mrntt = ComponentThread::getSelf(); if (mrntt->id != ComponentThread::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); } auto request = std::make_shared( *this, mrntt, callback); mrntt->getIoService().post( STC(std::bind( &MrnttLifetimeMgmtOp::initializeReq1_posted, request.get(), request))); } void MarionetteComponent::finalizeReq( Callback callback) { auto mrntt = ComponentThread::getSelf(); if (mrntt->id != ComponentThread::MRNTT) { throw std::runtime_error(std::string(__func__) + ": Must be executed on Marionette thread"); } auto request = std::make_shared( *this, mrntt, callback); mrntt->getIoService().post( STC(std::bind( &MrnttLifetimeMgmtOp::finalizeReq1_posted, request.get(), request))); } void MarionetteComponent::exceptionInd() { auto faultyThread = ComponentThread::getSelf(); auto mrntt = ComponentThread::getMrntt(); auto request = std::make_shared( faultyThread); mrntt->getIoService().post( STC(std::bind( &TerminationEvent::exceptionInd1_posted, request.get(), request))); } } // namespace mrntt } // namespace smo