Files
salmanoff/smocore/include/loadableLib/loadableLibraryManager.h
T
hayodea 7eda755c15 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 <cursoragent@cursor.com>
2026-06-10 21:14:55 -04:00

112 lines
2.5 KiB
C++

#ifndef LOADABLE_LIBRARY_MANAGER_H
#define LOADABLE_LIBRARY_MANAGER_H
#include <dlfcn.h>
#include <atomic>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <vector>
#include <spinscale/co/coQutex.h>
#include <spinscale/sharedResourceGroup.h>
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<void, SharedLibraryDeleter> dlopenHandleIn)
: libraryPath(std::move(libraryPathIn)),
resolvedPath(std::move(resolvedPathIn)),
dlopenHandle(std::move(dlopenHandleIn))
{}
std::string libraryPath;
std::string resolvedPath;
std::unique_ptr<void, SharedLibraryDeleter> dlopenHandle;
std::atomic<bool> isBeingDestroyed{false};
void* getDlopenHandle() const
{
return dlopenHandle.get();
}
};
struct Resources
{
std::vector<std::shared_ptr<LoadedSharedLibrary>> loadedSharedLibraries;
};
static LoadableLibraryManager& getInstance()
{
static LoadableLibraryManager instance;
return instance;
}
std::optional<std::string> searchForLibInSmoSearchPaths(
const std::string& libraryPath) const;
std::shared_ptr<LoadedSharedLibrary> loadSharedLibrary(
const std::string& libraryPath);
void unloadSharedLibrary(
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary);
template<typename FnPtr>
static FnPtr resolveSymbol(void* handle, const char* symbolName)
{
dlerror();
auto symbol = reinterpret_cast<FnPtr>(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<sscl::co::CoQutex, Resources> s;
private:
LoadableLibraryManager()
: s("LoadableLibraryManager")
{}
~LoadableLibraryManager();
LoadableLibraryManager(const LoadableLibraryManager&) = delete;
LoadableLibraryManager& operator=(const LoadableLibraryManager&) = delete;
void appendLoadedSharedLibrary(
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary);
void removeLoadedSharedLibrary(
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary);
};
} // namespace loadable_lib
} // namespace smo
#endif // LOADABLE_LIBRARY_MANAGER_H