From 7eda755c156c2a12ddb785937d8fe2cb8189e124 Mon Sep 17 00:00:00 2001 From: Hayodea Hekol Date: Wed, 10 Jun 2026 21:14:55 -0400 Subject: [PATCH] Add LoadableLibraryManager and refactor StimBuffApiManager to use it. Centralize dlopen/search in LoadableLibraryManager so typed library managers can share one loaded-shlib registry without duplicating load/unload logic. Co-authored-by: Cursor --- smocore/CMakeLists.txt | 3 + smocore/deviceManager/deviceManager.cpp | 15 +- .../loadableLib/loadableLibraryManager.h | 111 ++++++ smocore/include/stimBuffApis/stimBuffApiLib.h | 45 +-- .../include/stimBuffApis/stimBuffApiManager.h | 19 +- .../loadableLib/loadableLibraryManager.cpp | 150 +++++++++ smocore/stimBuffApis/stimBuffApiManager.cpp | 316 +++++++----------- 7 files changed, 418 insertions(+), 241 deletions(-) create mode 100644 smocore/include/loadableLib/loadableLibraryManager.h create mode 100644 smocore/loadableLib/loadableLibraryManager.cpp diff --git a/smocore/CMakeLists.txt b/smocore/CMakeLists.txt index 3df91d0..7b9904a 100644 --- a/smocore/CMakeLists.txt +++ b/smocore/CMakeLists.txt @@ -36,6 +36,9 @@ add_library(smocore STATIC # SenseApis stimBuffApis/stimBuffApiManager.cpp + # Loadable shared libraries + loadableLib/loadableLibraryManager.cpp + # ComputeManager computeManager/computeManager.cpp diff --git a/smocore/deviceManager/deviceManager.cpp b/smocore/deviceManager/deviceManager.cpp index 44d19dd..e48569d 100644 --- a/smocore/deviceManager/deviceManager.cpp +++ b/smocore/deviceManager/deviceManager.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -92,7 +93,7 @@ DeviceManager::attachStimBuffDeviceCReq( auto &sbam = stim_buff::StimBuffApiManager::getInstance(); auto &lib = sbam.getStimBuffApiLibByApiName(spec->stimBuffApi); - if (lib.isBeingDestroyed.load()) + if (lib.loadedSharedLibrary->isBeingDestroyed.load()) { throw std::runtime_error( std::string(__func__) + ": Library is being destroyed" @@ -103,12 +104,13 @@ DeviceManager::attachStimBuffDeviceCReq( { throw std::runtime_error( std::string(__func__) + ": attachDeviceCReq() is NULL " - "for library '" + lib.libraryPath + "'"); + "for library '" + lib.loadedSharedLibrary->libraryPath + "'"); } /* FIXME Locking here makes no sense. */ sscl::co::CoQutex::ReleaseHandle sbamGuard = - co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy(); + co_await sbam.s.lock + .getAcquireInvocationAndSuspensionPolicy(); sscl::co::CoQutex::ReleaseHandle libGuard = co_await lib.s.lock.getAcquireInvocationAndSuspensionPolicy(); sbamGuard.release(); @@ -151,7 +153,7 @@ DeviceManager::detachStimBuffDeviceCReq( auto &sbam = stim_buff::StimBuffApiManager::getInstance(); auto &lib = sbam.getStimBuffApiLibByApiName(spec->stimBuffApi); - if (lib.isBeingDestroyed.load()) + if (lib.loadedSharedLibrary->isBeingDestroyed.load()) { throw std::runtime_error( std::string(__func__) + ": Library is being destroyed" @@ -162,12 +164,13 @@ DeviceManager::detachStimBuffDeviceCReq( { throw std::runtime_error( std::string(__func__) + ": detachDeviceCReq() is NULL " - "for library '" + lib.libraryPath + "'"); + "for library '" + lib.loadedSharedLibrary->libraryPath + "'"); } /* FIXME Locking here makes no sense. */ sscl::co::CoQutex::ReleaseHandle sbamGuard = - co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy(); + co_await sbam.s.lock + .getAcquireInvocationAndSuspensionPolicy(); sscl::co::CoQutex::ReleaseHandle libGuard = co_await lib.s.lock.getAcquireInvocationAndSuspensionPolicy(); sbamGuard.release(); diff --git a/smocore/include/loadableLib/loadableLibraryManager.h b/smocore/include/loadableLib/loadableLibraryManager.h new file mode 100644 index 0000000..08ee61d --- /dev/null +++ b/smocore/include/loadableLib/loadableLibraryManager.h @@ -0,0 +1,111 @@ +#ifndef LOADABLE_LIBRARY_MANAGER_H +#define LOADABLE_LIBRARY_MANAGER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace smo { +namespace loadable_lib { + +class LoadableLibraryManager +{ +public: + struct SharedLibraryDeleter + { + void operator()(void* handle) const; + }; + + struct LoadedSharedLibrary + { + LoadedSharedLibrary( + std::string libraryPathIn, + std::string resolvedPathIn, + std::unique_ptr dlopenHandleIn) + : libraryPath(std::move(libraryPathIn)), + resolvedPath(std::move(resolvedPathIn)), + dlopenHandle(std::move(dlopenHandleIn)) + {} + + std::string libraryPath; + std::string resolvedPath; + std::unique_ptr dlopenHandle; + std::atomic isBeingDestroyed{false}; + + void* getDlopenHandle() const + { + return dlopenHandle.get(); + } + }; + + struct Resources + { + std::vector> loadedSharedLibraries; + }; + + static LoadableLibraryManager& getInstance() + { + static LoadableLibraryManager instance; + return instance; + } + + std::optional searchForLibInSmoSearchPaths( + const std::string& libraryPath) const; + + std::shared_ptr loadSharedLibrary( + const std::string& libraryPath); + + void unloadSharedLibrary( + const std::shared_ptr& loadedLibrary); + + template + static FnPtr resolveSymbol(void* handle, const char* symbolName) + { + dlerror(); + auto symbol = reinterpret_cast(dlsym(handle, symbolName)); + const char* dlerr = dlerror(); + if (dlerr != nullptr) + { + throw std::runtime_error( + std::string("dlsym('") + symbolName + "') failed: " + dlerr); + } + + if (symbol == nullptr) + { + throw std::runtime_error( + std::string("dlsym('") + symbolName + "') returned null"); + } + + return symbol; + } + +public: + sscl::SharedResourceGroup s; + +private: + LoadableLibraryManager() + : s("LoadableLibraryManager") + {} + + ~LoadableLibraryManager(); + + LoadableLibraryManager(const LoadableLibraryManager&) = delete; + LoadableLibraryManager& operator=(const LoadableLibraryManager&) = delete; + + void appendLoadedSharedLibrary( + const std::shared_ptr& loadedLibrary); + + void removeLoadedSharedLibrary( + const std::shared_ptr& loadedLibrary); +}; + +} // namespace loadable_lib +} // namespace smo + +#endif // LOADABLE_LIBRARY_MANAGER_H diff --git a/smocore/include/stimBuffApis/stimBuffApiLib.h b/smocore/include/stimBuffApis/stimBuffApiLib.h index 98f7eb2..c04469f 100644 --- a/smocore/include/stimBuffApis/stimBuffApiLib.h +++ b/smocore/include/stimBuffApis/stimBuffApiLib.h @@ -3,11 +3,10 @@ #include #include -#include #include -#include #include #include +#include #include #include @@ -18,25 +17,15 @@ class StimBuffApiLib { private: friend class StimBuffApiManager; - struct DlCloser - { - void operator()(void* handle) const - { - if (handle) { - dlclose(handle); - } - } - }; public: StimBuffApiLib( - const std::string& path, void *_dlopen_handle, + std::shared_ptr + _loadedSharedLibrary, SMO_GET_STIM_BUFF_API_DESC_FN_TYPEDEF *descFn) - : libraryPath(path), - isBeingDestroyed(false), - dlopen_handle(_dlopen_handle, DlCloser()), - SMO_GET_STIM_BUFF_API_DESC_FN_NAME(descFn), - s("StimBuffApiLib-" + path) + : loadedSharedLibrary(std::move(_loadedSharedLibrary)), + SMO_GET_STIM_BUFF_API_DESC_FN_NAME(descFn), + s("StimBuffApiLib-" + loadedSharedLibrary->libraryPath) {} void setStimBuffApiDesc(const StimBuffApiDesc &desc) @@ -45,19 +34,19 @@ public: { throw std::runtime_error( std::string(__func__) + ": Sanity check failed for stim buff API " - "descriptor in library '" + libraryPath + "'"); + "descriptor in library '" + + loadedSharedLibrary->libraryPath + "'"); } stimBuffApiDesc = desc; } public: - std::string libraryPath; - std::atomic isBeingDestroyed; - std::unique_ptr dlopen_handle; - /* UNIMPLEMENTED: API-specific cmdline options. These affect this specific - * stim buff api lib's behaviour globally. - */ + std::shared_ptr + loadedSharedLibrary; + /* UNIMPLEMENTED: API-specific cmdline options. These affect this specific + * stim buff api lib's behaviour globally. + */ std::vector options; /** @@ -80,11 +69,13 @@ public: struct StimBuffApiLibResources {}; - + sscl::SharedResourceGroup s; - std::string stringify() const { - std::string result = "Library Path: " + libraryPath + "\n"; + std::string stringify() const + { + std::string result = "Library Path: " + + loadedSharedLibrary->libraryPath + "\n"; result += "Stim Buff API Descriptor: " + stimBuffApiDesc.stringify() + "\n"; return result; } diff --git a/smocore/include/stimBuffApis/stimBuffApiManager.h b/smocore/include/stimBuffApis/stimBuffApiManager.h index b4b52d2..a7468e5 100644 --- a/smocore/include/stimBuffApis/stimBuffApiManager.h +++ b/smocore/include/stimBuffApis/stimBuffApiManager.h @@ -21,7 +21,7 @@ class StimBuffApiManager public: struct Resources { - std::vector> stimBuffApiLibs; + std::vector> libs; }; static StimBuffApiManager& getInstance() @@ -39,7 +39,7 @@ public: const std::string& libraryPath, const std::shared_ptr& componentThread); - std::optional> getStimBuffApiLib( + std::optional> findStimBuffApiLibByLibraryPath( const std::string& libraryPath); std::optional> findStimBuffApiLibByApiName( const std::string& apiName); @@ -48,19 +48,21 @@ public: void loadAllStimBuffApiLibsFromOptions( const std::shared_ptr& componentThread); - void unloadAllStimBuffApiLibs(void); body::BodyViralPostingInvoker initializeStimBuffApiLibCReq( - StimBuffApiLib &lib, bool acquireSbamLock=true); + StimBuffApiLib &lib, bool acquireListLock=true); body::BodyViralPostingInvoker finalizeStimBuffApiLibCReq( - StimBuffApiLib &lib, bool acquireSbamLock=true); + StimBuffApiLib &lib, bool acquireListLock=true); body::BodyViralPostingInvoker initializeAllStimBuffApiLibsCReq(); body::BodyViralPostingInvoker finalizeAllStimBuffApiLibsCReq(); std::string stringifyLibs() const; +public: + sscl::SharedResourceGroup s; + private: StimBuffApiManager() : s("StimBuffApiManager") @@ -70,13 +72,6 @@ private: StimBuffApiManager(const StimBuffApiManager&) = delete; StimBuffApiManager& operator=(const StimBuffApiManager&) = delete; - -public: - sscl::SharedResourceGroup s; - -public: - static std::optional searchForLibInSmoSearchPaths( - const std::string& libraryPath); }; } // namespace stim_buff diff --git a/smocore/loadableLib/loadableLibraryManager.cpp b/smocore/loadableLib/loadableLibraryManager.cpp new file mode 100644 index 0000000..f4fac4a --- /dev/null +++ b/smocore/loadableLib/loadableLibraryManager.cpp @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +namespace smo { +namespace loadable_lib { + +namespace { + +std::vector buildSmoLibrarySearchPaths() +{ + std::vector searchPaths = { + fs::current_path().string(), + fs::path("/proc/self/exe").parent_path().string() + }; + + const auto& options = OptionParser::getOptions(); + if (!options.senseApiLibPath.empty()) + { + searchPaths.insert( + searchPaths.begin(), + options.senseApiLibPath.begin(), + options.senseApiLibPath.end()); + } + + return searchPaths; +} + +void logLibraryNotInSearchPaths( + const std::string& libraryPath, + const std::vector& searchPaths) +{ + std::cerr << "searchForLibInSmoSearchPaths: library '" + << libraryPath << "' isn't in search bespoke search paths: "; + + for (const auto& path : searchPaths) { + std::cerr << path << " "; + } + std::cerr << std::endl; + std::cerr << "Trying to load " << libraryPath + << " from system default search paths\n"; +} + +std::unique_ptr +tryDlopenPath(const std::string& path) +{ + dlerror(); + void* handle = dlopen(path.c_str(), RTLD_LAZY); + if (!handle) { + return {}; + } + + return std::unique_ptr< + void, LoadableLibraryManager::SharedLibraryDeleter>(handle); +} + +} // namespace + +LoadableLibraryManager::~LoadableLibraryManager() = default; + +void LoadableLibraryManager::SharedLibraryDeleter::operator()(void* handle) const +{ + if (handle) { + dlclose(handle); + } +} + +void LoadableLibraryManager::appendLoadedSharedLibrary( + const std::shared_ptr& loadedLibrary) +{ + s.rsrc.loadedSharedLibraries.push_back(loadedLibrary); +} + +void LoadableLibraryManager::removeLoadedSharedLibrary( + const std::shared_ptr& loadedLibrary) +{ + auto& loadedLibs = s.rsrc.loadedSharedLibraries; + auto it = std::find(loadedLibs.begin(), loadedLibs.end(), loadedLibrary); + if (it != loadedLibs.end()) { + loadedLibs.erase(it); + } +} + +std::optional LoadableLibraryManager::searchForLibInSmoSearchPaths( + const std::string& libraryPath) const +{ + const std::vector searchPaths = buildSmoLibrarySearchPaths(); + + for (const auto& path : searchPaths) + { + fs::path fullPath = fs::path(path) / libraryPath; + if (fs::exists(fullPath)) { + return fullPath.string(); + } + } + + logLibraryNotInSearchPaths(libraryPath, searchPaths); + return std::nullopt; +} + +std::shared_ptr +LoadableLibraryManager::loadSharedLibrary(const std::string& libraryPath) +{ + const std::optional fullPath = + searchForLibInSmoSearchPaths(libraryPath); + const std::string resolvedPath = fullPath.value_or(libraryPath); + + auto dlopenHandle = tryDlopenPath(resolvedPath); + if (!dlopenHandle && fullPath.has_value()) { + dlopenHandle = tryDlopenPath(libraryPath); + } + + if (!dlopenHandle) + { + const char* dlerr = dlerror(); + const std::string error = (dlerr + ? dlerr + : "Unknown error while opening shlib"); + throw std::runtime_error( + std::string("loadSharedLibrary: Cannot load library '") + + libraryPath + "': " + error); + } + + auto loadedLibrary = std::make_shared( + libraryPath, + resolvedPath, + std::move(dlopenHandle)); + + appendLoadedSharedLibrary(loadedLibrary); + return loadedLibrary; +} + +void LoadableLibraryManager::unloadSharedLibrary( + const std::shared_ptr& loadedLibrary) +{ + if (!loadedLibrary) { + return; + } + + removeLoadedSharedLibrary(loadedLibrary); + loadedLibrary->dlopenHandle.reset(); +} + +} // namespace loadable_lib +} // namespace smo diff --git a/smocore/stimBuffApis/stimBuffApiManager.cpp b/smocore/stimBuffApis/stimBuffApiManager.cpp index f1b3343..9d23061 100644 --- a/smocore/stimBuffApis/stimBuffApiManager.cpp +++ b/smocore/stimBuffApis/stimBuffApiManager.cpp @@ -1,9 +1,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include @@ -13,9 +14,6 @@ #include #include - -namespace fs = std::filesystem; - namespace smo { namespace stim_buff { @@ -32,109 +30,55 @@ void assertBodyThread() } } -} // namespace - -/** - * @brief Searches for a library in predefined locations - * @param libraryPath The name or path of the library to find - * @return Optional containing the full path if found in search paths, nullopt - * if not - * - * Searches for the library in the following locations in order: - * 1. Custom path specified by --sense-api-lib-path option (if provided) - * 2. Current working directory - * 3. Directory containing the executable - * - * If the library is not found in any of these locations, returns nullopt and - * falls back to system default library search paths (LD_LIBRARY_PATH, etc.) - */ -static std::optional searchForLibInSmoSearchPaths( - const std::string& libraryPath) -{ - std::vector searchPaths = { - fs::current_path().string(), - fs::path("/proc/self/exe").parent_path().string() - }; - - const auto& options = OptionParser::getOptions(); - if (!options.senseApiLibPath.empty()) - { - // Insert all stim buff API library paths at the beginning of search paths - searchPaths.insert( - searchPaths.begin(), - options.senseApiLibPath.begin(), - options.senseApiLibPath.end()); - } - - for (const auto& path : searchPaths) - { - fs::path fullPath = fs::path(path) / libraryPath; - if (fs::exists(fullPath)) - { - return fullPath.string(); - } - } - - std::cerr << std::string(__func__) + ": library '" - + libraryPath + "' isn't in search bespoke search paths: "; - for (const auto& path : searchPaths) { - std::cerr << path << " "; - } - std::cerr << std::endl; - std::cerr << "Trying to load " + libraryPath + " from system default " - "search paths\n"; - - return std::nullopt; -} - -/* Local static function to wrap sscl::ComponentThread::getSelf for SmoCallbacks */ -static std::shared_ptr ComponentThread_getSelf() +std::shared_ptr ComponentThread_getSelf() { return sscl::ComponentThread::getSelf(); } -/* Local static function to wrap OptionParser::getOptions for SmoCallbacks */ -static OptionParser& OptionParser_getOptions() +OptionParser& OptionParser_getOptions() { return OptionParser::getOptions(); } -/* Local static functions to wrap ComputeManager methods for SmoCallbacks */ -static std::shared_ptr +std::shared_ptr ComputeManager_createUseHostPtrBuffer( - void* hostPtr, size_t size, cl_mem_flags flags - ) + void* hostPtr, size_t size, cl_mem_flags flags) { return smo::compute::ComputeManager::getInstance().createUseHostPtrBuffer( hostPtr, size, flags); } -static void ComputeManager_releaseUseHostPtrBuffer( - std::shared_ptr buffer - ) +void ComputeManager_releaseUseHostPtrBuffer( + std::shared_ptr buffer) { smo::compute::ComputeManager::getInstance().releaseUseHostPtrBuffer( buffer); } -static std::shared_ptr ComputeManager_getDevice() +std::shared_ptr ComputeManager_getDevice() { return smo::compute::ComputeManager::getInstance().getDevice(); } -static void ComputeManager_releaseDevice( - std::shared_ptr device - ) +void ComputeManager_releaseDevice( + std::shared_ptr device) { smo::compute::ComputeManager::getInstance().releaseDevice(device); } +std::optional searchForLibInSmoSearchPathsHook( + const std::string& libraryPath) +{ + return loadable_lib::LoadableLibraryManager::getInstance() + .searchForLibInSmoSearchPaths(libraryPath); +} + /* Hooks to be provided to stimBuffApiLibs, enabling them to call into Salmanoff * code. */ -static SmoCallbacks smoCallbacks = +SmoCallbacks smoCallbacks = { - .searchForLibInSmoSearchPaths = searchForLibInSmoSearchPaths, + .searchForLibInSmoSearchPaths = searchForLibInSmoSearchPathsHook, .ComponentThread_getSelf = ComponentThread_getSelf, .OptionParser_getOptions = OptionParser_getOptions, .ComputeManager_createUseHostPtrBuffer = @@ -146,104 +90,78 @@ static SmoCallbacks smoCallbacks = }; /* Static file-scope threading model object for senseApi libraries */ -static SmoThreadingModelDesc smoThreadingModelDesc = { +SmoThreadingModelDesc smoThreadingModelDesc = { .componentThread = nullptr }; -std::optional StimBuffApiManager::searchForLibInSmoSearchPaths( - const std::string& libraryPath) -{ - return ::smo::stim_buff::searchForLibInSmoSearchPaths(libraryPath); -} +} // namespace StimBuffApiLib& StimBuffApiManager::loadStimBuffApiLib( const std::string& libraryPath, - const std::shared_ptr& componentThread - ) + const std::shared_ptr& componentThread) { - std::optional fullPath = searchForLibInSmoSearchPaths( - libraryPath); - std::string resolvedPath = fullPath.value_or(libraryPath); + loadable_lib::LoadableLibraryManager& llm = + loadable_lib::LoadableLibraryManager::getInstance(); - // Clear any existing error - dlerror(); - auto dlopen_handle = std::unique_ptr( - dlopen(resolvedPath.c_str(), RTLD_LAZY)); - if (!dlopen_handle && fullPath.has_value()) - { - // Fallback to using the supplied libraryPath - dlerror(); - dlopen_handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY)); - } + if (findStimBuffApiLibByLibraryPath(libraryPath)) + { + throw std::runtime_error( + std::string(__func__) + ": StimBuffApiLib already loaded: " + + libraryPath); + } - if (!dlopen_handle) - { - const char *dlerr = dlerror(); + std::shared_ptr + loadedLibrary = llm.loadSharedLibrary(libraryPath); - std::string error = (dlerr - ? dlerr - : "Unknown error while opening shlib"); - throw std::runtime_error( - std::string(__func__) + ": Cannot load library '" - + libraryPath + "': " - + error); - } + auto descFn = loadable_lib::LoadableLibraryManager::resolveSymbol< + SMO_GET_STIM_BUFF_API_DESC_FN_TYPEDEF *>( + loadedLibrary->getDlopenHandle(), + SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR); - // Initialize getSenseApiDescriptor - auto func = reinterpret_cast( - dlsym(dlopen_handle.get(), SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR)); - if (!func) - { - throw std::runtime_error( - std::string(__func__) + ": dlsym('" - SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR "') failed for library '" - + libraryPath + "'"); - } + if (!smoThreadingModelDesc.componentThread) { + smoThreadingModelDesc.componentThread = componentThread; + } - // Check if the static threading model obj is null and initialize if needed - if (!smoThreadingModelDesc.componentThread) { - smoThreadingModelDesc.componentThread = componentThread; - } - - const StimBuffApiDesc &libApiDesc = func( + const StimBuffApiDesc& libApiDesc = descFn( smoCallbacks, smoThreadingModelDesc); - auto lib = std::make_shared( - libraryPath, dlopen_handle.release(), func); - lib->setStimBuffApiDesc(libApiDesc); - getInstance().s.rsrc.stimBuffApiLibs.push_back(lib); - return *getInstance().s.rsrc.stimBuffApiLibs.back(); + auto lib = std::make_shared(loadedLibrary, descFn); + lib->setStimBuffApiDesc(libApiDesc); + s.rsrc.libs.push_back(lib); + + return *lib; } std::optional> -StimBuffApiManager::getStimBuffApiLib(const std::string& libraryPath) +StimBuffApiManager::findStimBuffApiLibByLibraryPath( + const std::string& libraryPath) { - auto &libs = getInstance().s.rsrc.stimBuffApiLibs; - auto it = std::find_if(libs.begin(), libs.end(), - [&libPath = libraryPath](const std::shared_ptr& lib) { - return lib->libraryPath == libPath; - } - ); + auto& libs = s.rsrc.libs; + auto it = std::find_if( + libs.begin(), libs.end(), + [&libraryPath](const std::shared_ptr& lib) { + return lib->loadedSharedLibrary->libraryPath == libraryPath; + }); - if (it != libs.end()) { return *it; } - return std::nullopt; + if (it != libs.end()) { return *it; } + return std::nullopt; } std::optional> StimBuffApiManager::findStimBuffApiLibByApiName(const std::string& apiName) { - auto &libs = getInstance().s.rsrc.stimBuffApiLibs; - auto it = std::find_if(libs.begin(), libs.end(), - [&apiName](const std::shared_ptr& lib) { - return lib->stimBuffApiDesc.name == apiName; - } - ); + auto& libs = s.rsrc.libs; + auto it = std::find_if( + libs.begin(), libs.end(), + [&apiName](const std::shared_ptr& lib) { + return lib->stimBuffApiDesc.name == apiName; + }); - if (it != libs.end()) { return *it; } - return std::nullopt; + if (it != libs.end()) { return *it; } + return std::nullopt; } -StimBuffApiLib &StimBuffApiManager::getStimBuffApiLibByApiName( +StimBuffApiLib& StimBuffApiManager::getStimBuffApiLibByApiName( const std::string& apiName) { auto libOpt = findStimBuffApiLibByApiName(apiName); @@ -258,66 +176,76 @@ StimBuffApiLib &StimBuffApiManager::getStimBuffApiLibByApiName( void StimBuffApiManager::unloadStimBuffApiLib(const std::string& libraryPath) { - auto &libs = getInstance().s.rsrc.stimBuffApiLibs; - auto it = std::find_if(libs.begin(), libs.end(), - [&lpath = libraryPath](const std::shared_ptr& lib) { - return lib->libraryPath == lpath; - } - ); + auto& libs = s.rsrc.libs; + auto it = std::find_if( + libs.begin(), libs.end(), + [&libraryPath](const std::shared_ptr& lib) { + return lib->loadedSharedLibrary->libraryPath == libraryPath; + }); - if (it != libs.end()) - { - libs.erase(it); - return; - } + if (it == libs.end()) + { + std::cerr << std::string(__func__) + ": Library not found: " + << libraryPath << '\n'; + return; + } - std::cerr << std::string(__func__) + ": Library not found: " - << libraryPath << '\n'; + std::shared_ptr + loadedLibrary = (*it)->loadedSharedLibrary; + libs.erase(it); + + loadable_lib::LoadableLibraryManager::getInstance() + .unloadSharedLibrary(loadedLibrary); } void StimBuffApiManager::unloadAllStimBuffApiLibs(void) { - getInstance().s.rsrc.stimBuffApiLibs.clear(); + auto libs = s.rsrc.libs; + s.rsrc.libs.clear(); + + for (const auto& lib : libs) + { + loadable_lib::LoadableLibraryManager::getInstance() + .unloadSharedLibrary(lib->loadedSharedLibrary); + } } void StimBuffApiManager::loadAllStimBuffApiLibsFromOptions( - const std::shared_ptr& componentThread - ) + const std::shared_ptr& componentThread) { - const auto& options = OptionParser::getOptions(); - for (const auto& libPath : options.senseApiLibs) { - loadStimBuffApiLib(libPath, componentThread); - } + const auto& options = OptionParser::getOptions(); + for (const auto& libPath : options.senseApiLibs) { + loadStimBuffApiLib(libPath, componentThread); + } } std::string StimBuffApiManager::stringifyLibs() const { - std::string result; - for (const auto& lib : getInstance().s.rsrc.stimBuffApiLibs) { - result += lib->stringify() + "\n"; - } - return result; + std::string result; + for (const auto& lib : s.rsrc.libs) { + result += lib->stringify() + "\n"; + } + return result; } body::BodyViralPostingInvoker StimBuffApiManager::initializeStimBuffApiLibCReq( - StimBuffApiLib &lib, bool acquireSbamLock) + StimBuffApiLib& lib, bool acquireListLock) { assertBodyThread(); - StimBuffApiManager &sbam = getInstance(); - std::optional sbamGuard; - if (acquireSbamLock) + std::optional listGuard; + if (acquireListLock) { - sbamGuard.emplace( - co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy()); + listGuard.emplace( + co_await s.lock.getAcquireInvocationAndSuspensionPolicy()); } if (!lib.stimBuffApiDesc.sal_mgmt_libOps.initializeCInd) { throw std::runtime_error( std::string(__func__) + ": initializeCInd() is NULL for library '" - + lib.libraryPath + "'"); + + lib.loadedSharedLibrary->libraryPath + "'"); } sscl::co::CoQutex::ReleaseHandle libGuard = @@ -330,29 +258,28 @@ StimBuffApiManager::initializeStimBuffApiLibCReq( body::BodyViralPostingInvoker StimBuffApiManager::finalizeStimBuffApiLibCReq( - StimBuffApiLib &lib, bool acquireSbamLock) + StimBuffApiLib& lib, bool acquireListLock) { assertBodyThread(); - StimBuffApiManager &sbam = getInstance(); - std::optional sbamGuard; - if (acquireSbamLock) + std::optional listGuard; + if (acquireListLock) { - sbamGuard.emplace( - co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy()); + listGuard.emplace( + co_await s.lock.getAcquireInvocationAndSuspensionPolicy()); } if (!lib.stimBuffApiDesc.sal_mgmt_libOps.finalizeCInd) { throw std::runtime_error( std::string(__func__) + ": finalizeCInd() is NULL for library '" - + lib.libraryPath + "'"); + + lib.loadedSharedLibrary->libraryPath + "'"); } sscl::co::CoQutex::ReleaseHandle libGuard = co_await lib.s.lock.getAcquireInvocationAndSuspensionPolicy(); - lib.isBeingDestroyed.store(true); + lib.loadedSharedLibrary->isBeingDestroyed.store(true); co_await lib.stimBuffApiDesc.sal_mgmt_libOps.finalizeCInd(); co_return; @@ -363,11 +290,10 @@ StimBuffApiManager::initializeAllStimBuffApiLibsCReq() { assertBodyThread(); - StimBuffApiManager &sbam = getInstance(); - sscl::co::CoQutex::ReleaseHandle sbamGuard = - co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy(); + sscl::co::CoQutex::ReleaseHandle listGuard = + co_await s.lock.getAcquireInvocationAndSuspensionPolicy(); - for (auto &lib : sbam.s.rsrc.stimBuffApiLibs) { + for (auto& lib : s.rsrc.libs) { co_await initializeStimBuffApiLibCReq(*lib, false); } @@ -379,17 +305,15 @@ StimBuffApiManager::finalizeAllStimBuffApiLibsCReq() { assertBodyThread(); - StimBuffApiManager &sbam = getInstance(); - sscl::co::CoQutex::ReleaseHandle sbamGuard = - co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy(); + sscl::co::CoQutex::ReleaseHandle listGuard = + co_await s.lock.getAcquireInvocationAndSuspensionPolicy(); - for (auto &lib : sbam.s.rsrc.stimBuffApiLibs) { + for (auto& lib : s.rsrc.libs) { co_await finalizeStimBuffApiLibCReq(*lib, false); } co_return; } - } // namespace stim_buff } // namespace smo