diff --git a/include/user/senseApiDesc.h b/include/user/senseApiDesc.h index 855d63c..39563e0 100644 --- a/include/user/senseApiDesc.h +++ b/include/user/senseApiDesc.h @@ -6,11 +6,34 @@ #include #include #include +#include #include namespace smo { namespace sense_api { +/** + * @brief Threading model descriptor for senseApi libraries. + * + * This structure provides senseApi libraries with access to the information and + * resources they need to operate with SMO's threading model. + */ +struct SmoThreadingModelDesc +{ + /** + * @brief Shared pointer to ComponentThread for device-independent state management. + * + * This ComponentThread should be used by senseApis for state management + * that's independent of any particular device or attachment spec. + * SMO will usually pass in the Marionette thread here. + * + * State management that's tied to a particular attachment spec should be + * done on the ComponentThread for the thread that SMO provided in the + * attachDeviceReq call. + */ + std::shared_ptr componentThread; +}; + typedef int (sal_mlo_initializeIndFn)(void); typedef int (sal_mlo_finalizeIndFn)(void); typedef int (sal_mlo_attachDeviceReqFn)( @@ -134,9 +157,12 @@ public: * * The SalmanoffCallbacks parameter provides the library with access to * Salmanoff's hooks. + * The SmoThreadingModelDesc parameter provides the library with access to + * the io_service for network operations and event handling. */ typedef const SenseApiDesc &(SMO_GET_SENSE_API_DESC_FN_TYPEDEF)( - const SalmanoffCallbacks& callbacks); + const SalmanoffCallbacks& callbacks, + const SmoThreadingModelDesc& threadingModel); } // namespace sense_api } // namespace smo diff --git a/senseApis/xcbWindow/xcbWindow.cpp b/senseApis/xcbWindow/xcbWindow.cpp index 902bb1b..2606059 100644 --- a/senseApis/xcbWindow/xcbWindow.cpp +++ b/senseApis/xcbWindow/xcbWindow.cpp @@ -29,6 +29,7 @@ static XcbXorgDllState xcbXorg; // Salmanoff hooks, obtained from SMO_GET_SENSE_API_DESC_FN_NAME(). static const smo::sense_api::SalmanoffCallbacks* smoHooksPtr = nullptr; +static smo::sense_api::SmoThreadingModelDesc smoThreadingModelDesc; // Attached windows. static std::vector> @@ -348,8 +349,10 @@ extern "C" smo::sense_api::SMO_GET_SENSE_API_DESC_FN_TYPEDEF SMO_GET_SENSE_API_DESC_FN_NAME; const smo::sense_api::SenseApiDesc& SMO_GET_SENSE_API_DESC_FN_NAME( - const smo::sense_api::SalmanoffCallbacks& callbacks) + const smo::sense_api::SalmanoffCallbacks& callbacks, + const smo::sense_api::SmoThreadingModelDesc& threadingModel) { smoHooksPtr = &callbacks; + smoThreadingModelDesc = threadingModel; return xcbWindowApiDesc; } diff --git a/smocore/include/salmanoff.h b/smocore/include/salmanoff.h index 703a095..b3b1878 100644 --- a/smocore/include/salmanoff.h +++ b/smocore/include/salmanoff.h @@ -1,9 +1,12 @@ #ifndef _SALMANOFF_H #define _SALMANOFF_H +#include +#include + namespace smo { -void initializeSalmanoff(void); +void initializeSalmanoff(std::shared_ptr& componentThread); void shutdownSalmanoff(void); } // namespace smo diff --git a/smocore/include/senseApis/senseApiManager.h b/smocore/include/senseApis/senseApiManager.h index 69519a0..eeb4309 100644 --- a/smocore/include/senseApis/senseApiManager.h +++ b/smocore/include/senseApis/senseApiManager.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -22,7 +23,10 @@ public: return instance; } - SenseApiLib& loadSenseApiLib(const std::string& libraryPath); + SenseApiLib& loadSenseApiLib( + const std::string& libraryPath, + std::shared_ptr& componentThread); + std::optional> getSenseApiLib( const std::string& libraryPath); std::optional> getSenseApiLibByApiName( @@ -32,7 +36,9 @@ public: void initializeSenseApiLib(SenseApiLib& lib); void finalizeSenseApiLib(SenseApiLib& lib); - void loadAllSenseApiLibsFromOptions(void); + void loadAllSenseApiLibsFromOptions( + std::shared_ptr& componentThread); + void unloadAllSenseApiLibs(void); void initializeAllSenseApiLibs(void); void finalizeAllSenseApiLibs(void); diff --git a/smocore/marionette/marionette.cpp b/smocore/marionette/marionette.cpp index 2ff50ca..a2a9872 100644 --- a/smocore/marionette/marionette.cpp +++ b/smocore/marionette/marionette.cpp @@ -75,7 +75,7 @@ void ComponentThread::marionetteMain(ComponentThread& self) throw JustPrintUsageNoError(options); } - initializeSalmanoff(); + initializeSalmanoff(mrntt::mrntt); self.getIoService().post([]() { // Initialize the global Mind object diff --git a/smocore/marionette/salmanoff.cpp b/smocore/marionette/salmanoff.cpp index fb45a7b..c016a80 100644 --- a/smocore/marionette/salmanoff.cpp +++ b/smocore/marionette/salmanoff.cpp @@ -4,14 +4,14 @@ namespace smo { -void initializeSalmanoff(void) +void initializeSalmanoff(std::shared_ptr& componentThread) { std::cout << __func__ << ": Entered." << std::endl; device::DeviceManager::getInstance().collateAllDapSpecs(); device::DeviceManager::getInstance().parseAllDapSpecs(); std::cout << device::DeviceManager::stringifyDeviceSpecs() << std::endl; - sense_api::SenseApiManager::getInstance().loadAllSenseApiLibsFromOptions(); + sense_api::SenseApiManager::getInstance().loadAllSenseApiLibsFromOptions(componentThread); std::cout << sense_api::SenseApiManager::getInstance().stringifyLibs() << std::endl; std::cerr << "About to initializeAllSenseApiLibs" << std::endl; diff --git a/smocore/senseApis/senseApiManager.cpp b/smocore/senseApis/senseApiManager.cpp index 5737de6..7ab768e 100644 --- a/smocore/senseApis/senseApiManager.cpp +++ b/smocore/senseApis/senseApiManager.cpp @@ -74,13 +74,21 @@ static SalmanoffCallbacks salmanoffCallbacks = .searchForLibInSmoSearchPaths = searchForLibInSmoSearchPaths }; +/* Static file-scope threading model object for senseApi libraries */ +static SmoThreadingModelDesc smoThreadingModelDesc = { + .componentThread = nullptr +}; + std::optional SenseApiManager::searchForLibInSmoSearchPaths( const std::string& libraryPath) { return ::smo::sense_api::searchForLibInSmoSearchPaths(libraryPath); } -SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath) +SenseApiLib& SenseApiManager::loadSenseApiLib( + const std::string& libraryPath, + std::shared_ptr& componentThread + ) { std::optional fullPath = searchForLibInSmoSearchPaths( libraryPath); @@ -121,8 +129,15 @@ SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath) + libraryPath + "'"); } - const SenseApiDesc &libApiDesc = func(salmanoffCallbacks); - auto lib = std::make_shared( + // Check if the static threading model obj is null and initialize if needed + if (!smoThreadingModelDesc.componentThread) { + smoThreadingModelDesc.componentThread = componentThread; + } + + const SenseApiDesc &libApiDesc = func( + salmanoffCallbacks, smoThreadingModelDesc); + + auto lib = std::make_shared( libraryPath, dlopen_handle.release(), func); lib->setSenseApiDesc(libApiDesc); senseApiLibs.push_back(lib); @@ -178,11 +193,13 @@ void SenseApiManager::unloadAllSenseApiLibs(void) senseApiLibs.clear(); } -void SenseApiManager::loadAllSenseApiLibsFromOptions() +void SenseApiManager::loadAllSenseApiLibsFromOptions( + std::shared_ptr& componentThread + ) { const auto& options = OptionParser::getOptions(); for (const auto& libPath : options.senseApiLibs) { - loadSenseApiLib(libPath); + loadSenseApiLib(libPath, componentThread); } }