Mind: Implement initialize/finalizeBodyReq()
We've done a lot of general work on the init sequencing.
This commit is contained in:
@@ -361,6 +361,7 @@ public:
|
|||||||
[[maybe_unused]] std::shared_ptr<MindShutdownIndOp> context
|
[[maybe_unused]] std::shared_ptr<MindShutdownIndOp> context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
std::cout << "Mrntt: About to exit marionette loop." << "\n";
|
||||||
/** FIXME:
|
/** FIXME:
|
||||||
* When we eventually support multiple minds, we should remove this
|
* When we eventually support multiple minds, we should remove this
|
||||||
* since it causes marionette to exit, even if there are other minds
|
* since it causes marionette to exit, even if there are other minds
|
||||||
|
|||||||
@@ -37,6 +37,14 @@ struct DeviceAttachmentContinuation {
|
|||||||
> cb)
|
> cb)
|
||||||
: spec(s), callback(cb)
|
: spec(s), callback(cb)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void callOriginalCallback(
|
||||||
|
bool success,
|
||||||
|
std::shared_ptr<Device> device,
|
||||||
|
std::shared_ptr<DeviceAttachmentSpec> deviceSpec)
|
||||||
|
{
|
||||||
|
callback(success, device, deviceSpec);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string DeviceManager::stringifyDeviceSpecs(void)
|
const std::string DeviceManager::stringifyDeviceSpecs(void)
|
||||||
@@ -71,7 +79,7 @@ void DeviceManager::newDeviceAttachmentSpecInd(
|
|||||||
{
|
{
|
||||||
if (!(*existingSpec == *spec)) { continue; }
|
if (!(*existingSpec == *spec)) { continue; }
|
||||||
// Already exists, callback with error
|
// Already exists, callback with error
|
||||||
callback(false, nullptr, nullptr);
|
continuation->callOriginalCallback(false, nullptr, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,10 +112,10 @@ void DeviceManager::newDeviceAttachmentSpecInd(
|
|||||||
deviceAttachmentSpecs.push_back(spec);
|
deviceAttachmentSpecs.push_back(spec);
|
||||||
|
|
||||||
// Callback with success
|
// Callback with success
|
||||||
callback(true, device, spec);
|
continuation->callOriginalCallback(true, device, spec);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
// Attach failed, callback with error
|
// Attach failed, callback with error
|
||||||
callback(false, nullptr, nullptr);
|
continuation->callOriginalCallback(false, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ public:
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initialize(void)
|
||||||
|
{};
|
||||||
|
void finalize(void)
|
||||||
|
{};
|
||||||
|
|
||||||
std::string readDapSpecFile(const std::string& filename);
|
std::string readDapSpecFile(const std::string& filename);
|
||||||
void collateAllDapSpecs(void);
|
void collateAllDapSpecs(void);
|
||||||
void parseAllDapSpecs(void);
|
void parseAllDapSpecs(void);
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ public:
|
|||||||
typedef std::function<void(bool)> mindLifetimeMgmtOpCbFn;
|
typedef std::function<void(bool)> mindLifetimeMgmtOpCbFn;
|
||||||
void initializeReq(mindLifetimeMgmtOpCbFn callback);
|
void initializeReq(mindLifetimeMgmtOpCbFn callback);
|
||||||
void finalizeReq(mindLifetimeMgmtOpCbFn callback);
|
void finalizeReq(mindLifetimeMgmtOpCbFn callback);
|
||||||
|
void initializeBodyReq(mindLifetimeMgmtOpCbFn callback);
|
||||||
|
void finalizeBodyReq(mindLifetimeMgmtOpCbFn callback);
|
||||||
|
|
||||||
// ComponentThread access methods
|
// ComponentThread access methods
|
||||||
std::shared_ptr<ComponentThread> getComponentThread(
|
std::shared_ptr<ComponentThread> getComponentThread(
|
||||||
@@ -77,6 +79,8 @@ private:
|
|||||||
|
|
||||||
class MindLifetimeMgmtOp;
|
class MindLifetimeMgmtOp;
|
||||||
class MindThreadLifetimeMgmtOp;
|
class MindThreadLifetimeMgmtOp;
|
||||||
|
class InitializeBodyReq;
|
||||||
|
class FinalizeBodyReq;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global Mind instance will be defined in marionette.cpp
|
// Global Mind instance will be defined in marionette.cpp
|
||||||
|
|||||||
@@ -7,10 +7,8 @@
|
|||||||
|
|
||||||
namespace smo {
|
namespace smo {
|
||||||
|
|
||||||
typedef std::function<void(bool)> initializeSalmanoffCbFn;
|
void initializeSalmanoff(void);
|
||||||
typedef initializeSalmanoffCbFn shutdownSalmanoffCbFn;
|
void shutdownSalmanoff(void);
|
||||||
void initializeSalmanoff(initializeSalmanoffCbFn callback);
|
|
||||||
void shutdownSalmanoff(shutdownSalmanoffCbFn callback);
|
|
||||||
|
|
||||||
} // namespace smo
|
} // namespace smo
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,14 @@ public:
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initialize(void)
|
||||||
|
{};
|
||||||
|
void finalize(void)
|
||||||
|
{};
|
||||||
|
|
||||||
SenseApiLib& loadSenseApiLib(
|
SenseApiLib& loadSenseApiLib(
|
||||||
const std::string& libraryPath,
|
const std::string& libraryPath,
|
||||||
std::shared_ptr<ComponentThread>& componentThread);
|
const std::shared_ptr<ComponentThread>& componentThread);
|
||||||
|
|
||||||
std::optional<std::shared_ptr<SenseApiLib>> getSenseApiLib(
|
std::optional<std::shared_ptr<SenseApiLib>> getSenseApiLib(
|
||||||
const std::string& libraryPath);
|
const std::string& libraryPath);
|
||||||
@@ -38,7 +43,7 @@ public:
|
|||||||
void finalizeSenseApiLib(SenseApiLib& lib);
|
void finalizeSenseApiLib(SenseApiLib& lib);
|
||||||
|
|
||||||
void loadAllSenseApiLibsFromOptions(
|
void loadAllSenseApiLibsFromOptions(
|
||||||
std::shared_ptr<ComponentThread>& componentThread);
|
const std::shared_ptr<ComponentThread>& componentThread);
|
||||||
|
|
||||||
void unloadAllSenseApiLibs(void);
|
void unloadAllSenseApiLibs(void);
|
||||||
void initializeAllSenseApiLibs(void);
|
void initializeAllSenseApiLibs(void);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void ComponentThread::marionetteMain(ComponentThread& self)
|
|||||||
self.initializeTls();
|
self.initializeTls();
|
||||||
mrntt::exitCode = EXIT_SUCCESS;
|
mrntt::exitCode = EXIT_SUCCESS;
|
||||||
static boost::asio::signal_set signals(self.getIoService(), SIGINT);
|
static boost::asio::signal_set signals(self.getIoService(), SIGINT);
|
||||||
bool callFinalizeReq = false, callShutdownSalmanoffReq = false;
|
bool callFinalizeReq = false, callShutdownSalmanoff = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Register SIGINT (Ctrl+C) and SIGSEGV handlers
|
// Register SIGINT (Ctrl+C) and SIGSEGV handlers
|
||||||
@@ -88,6 +88,9 @@ void ComponentThread::marionetteMain(ComponentThread& self)
|
|||||||
throw JustPrintUsageNoError(options);
|
throw JustPrintUsageNoError(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initializeSalmanoff();
|
||||||
|
callShutdownSalmanoff = true;
|
||||||
|
|
||||||
self.getIoService().post([]()
|
self.getIoService().post([]()
|
||||||
{
|
{
|
||||||
/** EXPLANATION:
|
/** EXPLANATION:
|
||||||
@@ -109,22 +112,17 @@ void ComponentThread::marionetteMain(ComponentThread& self)
|
|||||||
* easier to implement.
|
* easier to implement.
|
||||||
*/
|
*/
|
||||||
globalMind->initializeReq(
|
globalMind->initializeReq(
|
||||||
[](bool success)
|
[](bool success)
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
{
|
{
|
||||||
if (success) {
|
std::cerr << "Failed to initialize Mind object "
|
||||||
initializeSalmanoff([](bool success) {
|
"(threads)" << '\n';
|
||||||
if (!success) {
|
|
||||||
std::cerr << "Failed to initialize "
|
|
||||||
"Salmanoff" << '\n';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Failed to initialize Mind object "
|
|
||||||
"(threads)" << '\n';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
std::cout << "Mrntt: Mind object (threads) initialized."
|
||||||
|
<< '\n';
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
std::cout << __func__ << ": Entering event loop" << "\n";
|
std::cout << __func__ << ": Entering event loop" << "\n";
|
||||||
@@ -188,43 +186,26 @@ void ComponentThread::marionetteMain(ComponentThread& self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*out << outUsageMsg << e.what() << std::endl;
|
*out << outUsageMsg << e.what() << std::endl;
|
||||||
callShutdownSalmanoffReq = callFinalizeReq = true;
|
callFinalizeReq = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << __func__ << ": Exception occurred: " << e.what()
|
std::cerr << __func__ << ": Exception occurred: " << e.what()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
mrntt::exitCode = EXIT_FAILURE;
|
mrntt::exitCode = EXIT_FAILURE;
|
||||||
callShutdownSalmanoffReq = callFinalizeReq = true;
|
callShutdownSalmanoff = callFinalizeReq = true;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
std::cerr << __func__ << ": Unknown exception occurred" << std::endl;
|
std::cerr << __func__ << ": Unknown exception occurred" << std::endl;
|
||||||
mrntt::exitCode = EXIT_FAILURE;
|
mrntt::exitCode = EXIT_FAILURE;
|
||||||
callShutdownSalmanoffReq = callFinalizeReq = true;
|
callShutdownSalmanoff = callFinalizeReq = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (callShutdownSalmanoffReq)
|
|
||||||
{
|
|
||||||
shutdownSalmanoff(
|
|
||||||
[](bool success)
|
|
||||||
{
|
|
||||||
if (success) {
|
|
||||||
std::cout << "Salmanoff shutdown completed successfully"
|
|
||||||
<< std::endl;
|
|
||||||
} else {
|
|
||||||
std::cerr << "Salmanoff shutdown failed" << std::endl;
|
|
||||||
}
|
|
||||||
mrntt::mrntt->getIoService().stop();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
self.getIoService().reset();
|
|
||||||
self.getIoService().run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callFinalizeReq)
|
if (callFinalizeReq)
|
||||||
{
|
{
|
||||||
globalMind->finalizeReq([](bool success) {
|
globalMind->finalizeReq([](bool success)
|
||||||
|
{
|
||||||
if (!success) {
|
if (!success) {
|
||||||
std::cerr << "Failed to finalize Mind object (threads)" << '\n';
|
std::cerr << "Failed to finalize Mind object (threads)" << '\n';
|
||||||
}
|
}
|
||||||
@@ -233,6 +214,11 @@ void ComponentThread::marionetteMain(ComponentThread& self)
|
|||||||
self.getIoService().reset();
|
self.getIoService().reset();
|
||||||
self.getIoService().run();
|
self.getIoService().run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (callShutdownSalmanoff) {
|
||||||
|
shutdownSalmanoff();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace smo
|
} // namespace smo
|
||||||
|
|||||||
@@ -7,100 +7,22 @@
|
|||||||
|
|
||||||
namespace smo {
|
namespace smo {
|
||||||
|
|
||||||
class InitializeSalmanoffReq
|
void initializeSalmanoff(void)
|
||||||
: public AsynchronousContinuation<initializeSalmanoffCbFn>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
InitializeSalmanoffReq(initializeSalmanoffCbFn cb)
|
|
||||||
: AsynchronousContinuation(std::move(cb))
|
|
||||||
{}
|
|
||||||
|
|
||||||
// Callback methods for the initialization sequence
|
|
||||||
void initializeSalmanoffReq1(
|
|
||||||
std::shared_ptr<InitializeSalmanoffReq> context,
|
|
||||||
smo::AsynchronousLoop &results
|
|
||||||
)
|
|
||||||
{
|
|
||||||
std::cout << __func__ << ": Done. " << results.nSucceeded
|
|
||||||
<< " succeeded, " << results.nFailed << " failed." << std::endl;
|
|
||||||
context->originalCbFn(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void initializeSalmanoff(
|
|
||||||
initializeSalmanoffCbFn callback)
|
|
||||||
{
|
{
|
||||||
std::cout << __func__ << ": Entered." << std::endl;
|
std::cout << __func__ << ": Entered." << std::endl;
|
||||||
|
|
||||||
std::shared_ptr<ComponentThread> mrntt = ComponentThread::getMrntt();
|
sense_api::SenseApiManager::getInstance().initialize();
|
||||||
auto request = std::make_shared<InitializeSalmanoffReq>(
|
device::DeviceManager::getInstance().initialize();
|
||||||
std::move(callback));
|
|
||||||
|
|
||||||
device::DeviceManager::getInstance().collateAllDapSpecs();
|
device::DeviceManager::getInstance().collateAllDapSpecs();
|
||||||
device::DeviceManager::getInstance().parseAllDapSpecs();
|
device::DeviceManager::getInstance().parseAllDapSpecs();
|
||||||
std::cout << device::DeviceManager::stringifyDeviceSpecs() << std::endl;
|
std::cout << device::DeviceManager::stringifyDeviceSpecs() << std::endl;
|
||||||
|
|
||||||
/** 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.
|
|
||||||
*
|
|
||||||
* Right now we use Marionette, but there's a strong argument for using
|
|
||||||
* Body instead since it's meant to handle device-management operations.
|
|
||||||
*/
|
|
||||||
sense_api::SenseApiManager::getInstance().loadAllSenseApiLibsFromOptions(
|
|
||||||
mrntt);
|
|
||||||
|
|
||||||
std::cout << sense_api::SenseApiManager::getInstance().stringifyLibs()
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
if (OptionParser::getOptions().verbose) {
|
|
||||||
std::cout << __func__ << ": About to initializeAllSenseApiLibs" << '\n';
|
|
||||||
}
|
|
||||||
sense_api::SenseApiManager::getInstance().initializeAllSenseApiLibs();
|
|
||||||
|
|
||||||
if (OptionParser::getOptions().verbose) {
|
|
||||||
std::cout << __func__ << ": About to attachAllSenseDevicesFromSpecs" << '\n';
|
|
||||||
}
|
|
||||||
sense_api::SenseApiManager::getInstance().attachAllSenseDevicesFromSpecsReq(
|
|
||||||
std::bind(
|
|
||||||
&InitializeSalmanoffReq::initializeSalmanoffReq1,
|
|
||||||
request.get(), request,
|
|
||||||
std::placeholders::_1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ShutdownSalmanoffReq
|
void shutdownSalmanoff(void)
|
||||||
: public InitializeSalmanoffReq
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using InitializeSalmanoffReq::InitializeSalmanoffReq;
|
|
||||||
|
|
||||||
// Callback methods for the shutdown sequence
|
|
||||||
void shutdownSalmanoffReq1(
|
|
||||||
std::shared_ptr<ShutdownSalmanoffReq> context,
|
|
||||||
smo::AsynchronousLoop &results
|
|
||||||
)
|
|
||||||
{
|
|
||||||
sense_api::SenseApiManager::getInstance().finalizeAllSenseApiLibs();
|
|
||||||
std::cout << __func__ << ": Done. " << results.nSucceeded
|
|
||||||
<< " succeeded, " << results.nFailed << " failed." << std::endl;
|
|
||||||
context->originalCbFn(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void shutdownSalmanoff(shutdownSalmanoffCbFn callback)
|
|
||||||
{
|
{
|
||||||
std::cout << __func__ << ": Entered." << std::endl;
|
std::cout << __func__ << ": Entered." << std::endl;
|
||||||
|
device::DeviceManager::getInstance().finalize();
|
||||||
// Create the shutdown request object to hold state and callbacks
|
sense_api::SenseApiManager::getInstance().finalize();
|
||||||
auto request = std::make_shared<ShutdownSalmanoffReq>(std::move(callback));
|
|
||||||
|
|
||||||
sense_api::SenseApiManager::getInstance().detachAllSenseDevicesReq(
|
|
||||||
std::bind(
|
|
||||||
&ShutdownSalmanoffReq::shutdownSalmanoffReq1,
|
|
||||||
request.get(), request,
|
|
||||||
std::placeholders::_1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace smo
|
} // namespace smo
|
||||||
|
|||||||
+217
-27
@@ -4,6 +4,7 @@
|
|||||||
#include <asynchronousLoop.h>
|
#include <asynchronousLoop.h>
|
||||||
#include <mind.h>
|
#include <mind.h>
|
||||||
#include <componentThread.h>
|
#include <componentThread.h>
|
||||||
|
#include <senseApis/senseApiManager.h>
|
||||||
|
|
||||||
namespace smo {
|
namespace smo {
|
||||||
|
|
||||||
@@ -65,10 +66,10 @@ public:
|
|||||||
parent(parent)
|
parent(parent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void callOriginalCbFn(void)
|
void callOriginalCbFn(bool success)
|
||||||
{
|
{
|
||||||
if (originalCbFn) {
|
if (originalCbFn) {
|
||||||
originalCbFn(true);
|
originalCbFn(success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,27 +94,71 @@ public:
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
std::cout << "Mrntt: All mind threads started." << "\n";
|
std::cout << "Mrntt: All mind threads started." << "\n";
|
||||||
callOriginalCbFn();
|
|
||||||
|
parent.initializeBodyReq(
|
||||||
|
std::bind(
|
||||||
|
&MindLifetimeMgmtOp::initializeReq3,
|
||||||
|
context.get(), context, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeReq3(
|
||||||
|
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context,
|
||||||
|
bool success
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "Mrntt: Body component initialized." << "\n";
|
||||||
|
callOriginalCbFn(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalizeReq1(
|
void finalizeReq1(
|
||||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context,
|
||||||
|
bool success
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
std::cout << "Mrntt: All mind threads JOLTed." << "\n";
|
if (!success) {
|
||||||
|
std::cerr << "Mrntt: Body component failed to finalize." << "\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "Mrntt: Body component finalized." << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
parent.exitAllMindThreadsReq(
|
/* If the threads haven't been jolted, we need to do that first, because
|
||||||
std::bind(
|
* otherwise they'll just enter their main loops and wait for control
|
||||||
&MindLifetimeMgmtOp::finalizeReq2,
|
* messages from mrntt after processing the exit request.
|
||||||
context.get(), context));
|
*/
|
||||||
|
if (!parent.threadsHaveBeenJolted)
|
||||||
|
{
|
||||||
|
parent.joltAllMindThreadsReq(
|
||||||
|
std::bind(
|
||||||
|
&MindLifetimeMgmtOp::finalizeReq2,
|
||||||
|
context.get(), context));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent.exitAllMindThreadsReq(
|
||||||
|
std::bind(
|
||||||
|
&MindLifetimeMgmtOp::finalizeReq3,
|
||||||
|
context.get(), context));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalizeReq2(
|
void finalizeReq2(
|
||||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
||||||
)
|
)
|
||||||
|
{
|
||||||
|
std::cout << "Mrntt: All mind threads JOLTed for finalization." << "\n";
|
||||||
|
|
||||||
|
parent.exitAllMindThreadsReq(
|
||||||
|
std::bind(
|
||||||
|
&MindLifetimeMgmtOp::finalizeReq3,
|
||||||
|
context.get(), context));
|
||||||
|
}
|
||||||
|
|
||||||
|
void finalizeReq3(
|
||||||
|
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
||||||
|
)
|
||||||
{
|
{
|
||||||
std::cout << "Mrntt: All mind threads exited." << "\n";
|
std::cout << "Mrntt: All mind threads exited." << "\n";
|
||||||
callOriginalCbFn();
|
callOriginalCbFn(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -146,24 +191,169 @@ void Mind::finalizeReq(mindLifetimeMgmtOpCbFn callback)
|
|||||||
auto request = std::make_shared<MindLifetimeMgmtOp>(
|
auto request = std::make_shared<MindLifetimeMgmtOp>(
|
||||||
*this, callback);
|
*this, callback);
|
||||||
|
|
||||||
/* If the threads haven't been jolted, we need to do that first, because
|
finalizeBodyReq(
|
||||||
* otherwise they'll just enter their main loops and wait for control
|
std::bind(
|
||||||
* messages from mrntt after processing the exit request.
|
&MindLifetimeMgmtOp::finalizeReq1,
|
||||||
*/
|
request.get(), request, std::placeholders::_1));
|
||||||
if (!threadsHaveBeenJolted)
|
}
|
||||||
{
|
|
||||||
joltAllMindThreadsReq(
|
class Mind::InitializeBodyReq
|
||||||
|
: public MindLifetimeMgmtOp, public ContinuationTarget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InitializeBodyReq(
|
||||||
|
Mind &parent, const std::shared_ptr<ComponentThread> &caller,
|
||||||
|
mindLifetimeMgmtOpCbFn callback)
|
||||||
|
: MindLifetimeMgmtOp(parent, callback), ContinuationTarget(caller)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void callOriginalCbFn(bool success)
|
||||||
|
{
|
||||||
|
if (originalCbFn)
|
||||||
|
{
|
||||||
|
caller->getIoService().post(
|
||||||
|
std::bind(originalCbFn, success));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void initializeBodyReq1(
|
||||||
|
[[maybe_unused]] std::shared_ptr<InitializeBodyReq> 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.
|
||||||
|
*
|
||||||
|
* Right now we use Marionette, but there's a strong argument for using
|
||||||
|
* Body instead since it's meant to handle device-management operations.
|
||||||
|
*/
|
||||||
|
sense_api::SenseApiManager::getInstance()
|
||||||
|
.loadAllSenseApiLibsFromOptions(caller);
|
||||||
|
|
||||||
|
std::cout << sense_api::SenseApiManager::getInstance().stringifyLibs()
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
if (OptionParser::getOptions().verbose)
|
||||||
|
{
|
||||||
|
std::cout << __func__ << ": About to initializeAllSenseApiLibs"
|
||||||
|
<< '\n';
|
||||||
|
}
|
||||||
|
sense_api::SenseApiManager::getInstance().initializeAllSenseApiLibs();
|
||||||
|
|
||||||
|
if (OptionParser::getOptions().verbose)
|
||||||
|
{
|
||||||
|
std::cout << __func__ << ": About to attachAllSenseDevicesFromSpecs"
|
||||||
|
<< '\n';
|
||||||
|
}
|
||||||
|
sense_api::SenseApiManager::getInstance()
|
||||||
|
.attachAllSenseDevicesFromSpecsReq(
|
||||||
|
std::bind(
|
||||||
|
&InitializeBodyReq::initializeBodyReq2,
|
||||||
|
context.get(), context,
|
||||||
|
std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeBodyReq2(
|
||||||
|
[[maybe_unused]] std::shared_ptr<InitializeBodyReq> context,
|
||||||
|
smo::AsynchronousLoop &results
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "Mrntt: attached "
|
||||||
|
<< results.nSucceeded << " of " << results.nTotal
|
||||||
|
<< " sense devices." << "\n";
|
||||||
|
|
||||||
|
callOriginalCbFn(results.nSucceeded == results.nTotal);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Mind::FinalizeBodyReq
|
||||||
|
: public InitializeBodyReq
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using InitializeBodyReq::InitializeBodyReq;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void finalizeBodyReq1(
|
||||||
|
[[maybe_unused]] std::shared_ptr<FinalizeBodyReq> 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";
|
||||||
|
sense_api::SenseApiManager::getInstance().detachAllSenseDevicesReq(
|
||||||
std::bind(
|
std::bind(
|
||||||
&MindLifetimeMgmtOp::finalizeReq1,
|
&FinalizeBodyReq::finalizeBodyReq2,
|
||||||
request.get(), request));
|
context.get(), context,
|
||||||
}
|
std::placeholders::_1));
|
||||||
else
|
}
|
||||||
{
|
|
||||||
exitAllMindThreadsReq(
|
void finalizeBodyReq2(
|
||||||
std::bind(
|
[[maybe_unused]] std::shared_ptr<FinalizeBodyReq> context,
|
||||||
&MindLifetimeMgmtOp::finalizeReq1,
|
smo::AsynchronousLoop &results
|
||||||
request.get(), request));
|
)
|
||||||
}
|
{
|
||||||
|
std::cout << "Mrntt: Successfully detached "
|
||||||
|
<< results.nSucceeded << " of " << results.nTotal
|
||||||
|
<< " sense devices." << "\n";
|
||||||
|
|
||||||
|
std::cout << "Mrntt: About to unload all sense api libs." << "\n";
|
||||||
|
sense_api::SenseApiManager::getInstance().unloadAllSenseApiLibs();
|
||||||
|
callOriginalCbFn(results.nSucceeded == results.nTotal);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Mind::initializeBodyReq(mindLifetimeMgmtOpCbFn 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<InitializeBodyReq>(
|
||||||
|
*this, mrntt, callback);
|
||||||
|
|
||||||
|
this->getComponentThread(ComponentThread::BODY)->getIoService().post(
|
||||||
|
std::bind(
|
||||||
|
&InitializeBodyReq::initializeBodyReq1,
|
||||||
|
request.get(), request));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mind::finalizeBodyReq(mindLifetimeMgmtOpCbFn 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<FinalizeBodyReq>(
|
||||||
|
*this, mrntt, callback);
|
||||||
|
|
||||||
|
this->getComponentThread(ComponentThread::BODY)->getIoService().post(
|
||||||
|
std::bind(
|
||||||
|
&FinalizeBodyReq::finalizeBodyReq1,
|
||||||
|
request.get(), request));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mind::distributeAndPinThreadsAcrossCpus()
|
void Mind::distributeAndPinThreadsAcrossCpus()
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ std::optional<std::string> SenseApiManager::searchForLibInSmoSearchPaths(
|
|||||||
|
|
||||||
SenseApiLib& SenseApiManager::loadSenseApiLib(
|
SenseApiLib& SenseApiManager::loadSenseApiLib(
|
||||||
const std::string& libraryPath,
|
const std::string& libraryPath,
|
||||||
std::shared_ptr<ComponentThread>& componentThread
|
const std::shared_ptr<ComponentThread>& componentThread
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
std::optional<std::string> fullPath = searchForLibInSmoSearchPaths(
|
std::optional<std::string> fullPath = searchForLibInSmoSearchPaths(
|
||||||
@@ -204,7 +204,7 @@ void SenseApiManager::unloadAllSenseApiLibs(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SenseApiManager::loadAllSenseApiLibsFromOptions(
|
void SenseApiManager::loadAllSenseApiLibsFromOptions(
|
||||||
std::shared_ptr<ComponentThread>& componentThread
|
const std::shared_ptr<ComponentThread>& componentThread
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const auto& options = OptionParser::getOptions();
|
const auto& options = OptionParser::getOptions();
|
||||||
@@ -351,6 +351,11 @@ public:
|
|||||||
context->originalCbFn(context->loop);
|
context->originalCbFn(context->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void callOriginalCallback()
|
||||||
|
{
|
||||||
|
originalCbFn(loop);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AsynchronousLoop loop;
|
AsynchronousLoop loop;
|
||||||
};
|
};
|
||||||
@@ -365,7 +370,7 @@ void SenseApiManager::attachAllSenseDevicesFromSpecsReq(
|
|||||||
|
|
||||||
if (request->loop.nTotalIsZero())
|
if (request->loop.nTotalIsZero())
|
||||||
{
|
{
|
||||||
cb(request->loop);
|
request->callOriginalCallback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +386,7 @@ void SenseApiManager::attachAllSenseDevicesFromSpecsReq(
|
|||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << __func__ << ": Exception: " << e.what() << "\n";
|
std::cerr << __func__ << ": Exception: " << e.what() << "\n";
|
||||||
if (request->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(false))
|
if (request->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(false))
|
||||||
{ cb(request->loop); }
|
{ request->callOriginalCallback(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,6 +423,11 @@ public:
|
|||||||
|
|
||||||
context->originalCbFn(context->loop);
|
context->originalCbFn(context->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void callOriginalCallback()
|
||||||
|
{
|
||||||
|
originalCbFn(loop);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void SenseApiManager::detachAllSenseDevicesReq(
|
void SenseApiManager::detachAllSenseDevicesReq(
|
||||||
@@ -429,7 +439,7 @@ void SenseApiManager::detachAllSenseDevicesReq(
|
|||||||
|
|
||||||
if (request->loop.nTotalIsZero())
|
if (request->loop.nTotalIsZero())
|
||||||
{
|
{
|
||||||
cb(request->loop);
|
request->callOriginalCallback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,7 +455,9 @@ void SenseApiManager::detachAllSenseDevicesReq(
|
|||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << __func__ << ": Exception: " << e.what() << "\n";
|
std::cerr << __func__ << ": Exception: " << e.what() << "\n";
|
||||||
if (request->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(false))
|
if (request->loop.incrementSuccessOrFailureAndTestForCompletionDueTo(false))
|
||||||
{ cb(request->loop); }
|
{
|
||||||
|
request->callOriginalCallback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user