19#include <unordered_map>
27#define DLLOADER_MAC_LINUX(mac, linux) mac
29#define DLLOADER_MAC_LINUX(mac, linux) linux
41template <
typename DerivedType>
46 static constexpr const char*
prefix =
"lib";
67 using library_t = std::unique_ptr<handle_t, HandleDeleter>;
75 return DerivedType::sInstance;
82 const std::lock_guard lock(mLock);
84 if (mLibraries.find(library) != mLibraries.end()) {
88 if (mO2Path.empty()) {
89 if (
const auto*
path = std::getenv(
"O2_ROOT")) {
92 LOGP(error,
"$O2_ROOT not set!");
97 auto path = getO2Path(library);
98 if (!std::filesystem::exists(
path)) {
99 LOGP(error,
"Library under '{}' does not exist!",
path);
104 auto lib = std::unique_ptr<handle_t, HandleDeleter>(dlopen(
path.c_str(), mLoadPolicy));
105 if (lib ==
nullptr) {
106 throw std::runtime_error(
"Library handle is nullptr!");
108 mLibraries[library] = std::move(lib);
109 LOGP(info,
"Loaded dynamic library '{}' from '{}'", library,
path);
111 }
catch (std::exception& e) {
112 LOGP(error,
"Failed to load library (path='{}'), failed reason: '{}'",
path, e.what());
115 LOGP(error,
"Failed to load library (path='{}') for unknown reason!",
path.c_str());
128 const std::lock_guard lock(mLock);
130 if (
auto it = mLibraries.find(library); it != mLibraries.end()) {
131 mLibraries.erase(it);
135 LOGP(error,
"No '{}' library found, cannot unload it!", library);
148 bool hasSymbol(
const std::string& library,
const std::string& symbol)
150 const std::lock_guard lock(mLock);
152 if (mLibraries.find(library) == mLibraries.end()) {
163 if (
const auto* err = dlerror(); err !=
nullptr) {
164 LOGP(error,
"Did not get {} from {}; error: {}", symbol, library, err);
167 return ptr !=
nullptr;
171 template <
typename Ret,
typename... Args>
172 std::optional<Ret>
executeFunction(
const std::string& library,
const std::string& fname, Args... args)
174 using Func_t = Ret (*)(Args...);
176 const std::lock_guard lock(mLock);
179 LOGP(error,
"Function name cannot be empty!");
183 if (mLibraries.find(library) == mLibraries.end()) {
190 const auto& lib = mLibraries[library].get();
192 LOGP(error,
"Library '{}' does not have a symbol '{}'", library, fname);
198 auto func = (Func_t)dlsym(lib, fname.c_str());
199 if (
const auto* err = dlerror(); err !=
nullptr) {
200 LOGP(error,
"Did not get {} from {}; error: {}", fname, library, err);
204 if (
func ==
nullptr) {
205 LOGP(error,
"Library '{}' does not have a symbol '{}' with {}", library, fname, getTypeName<Func_t>());
210 return func(args...);
214 template <
typename Ret,
typename... Args>
217 if (
auto opt = executeFunction<Ret, Args...>(library, fname, args...)) {
221 LOGP(fatal,
"Execution of '{}' from '{}' failed spectaculary!", fname, library);
222 __builtin_unreachable();
238 [[nodiscard]] std::string getO2Path(
const std::string& library)
const
244 template <
typename ProtoType>
245 [[nodiscard]]
auto getTypeName() -> std::string
247 return typeid(ProtoType).
name();
250 std::unordered_map<std::string, library_t> mLibraries{};
251 std::recursive_mutex mLock{};
252 std::string mO2Path{};
253 Options mLoadPolicy{Options::lazy};
258#define O2DLLoaderDef(classname) \
260 static classname sInstance; \
261 classname() = default; \
262 friend class o2::utils::DLLoaderBase<classname>;
264#define O2DLLoaderImpl(classname) classname classname::sInstance;
#define DLLOADER_MAC_LINUX(mac, linux)
static DerivedType & Instance()
DLLoaderBase(const DLLoaderBase &)=delete
bool unloadLibrary(const std::string &library)
bool addLibrary(const std::string &library)
std::optional< Ret > executeFunction(const std::string &library, const std::string &fname, Args... args)
bool hasSymbol(const std::string &library, const std::string &symbol)
std::unique_ptr< handle_t, HandleDeleter > library_t
DLLoaderBase & operator=(const DLLoaderBase &)=delete
DLLoaderBase & operator=(DLLoaderBase &&)=delete
Ret executeFunctionAlias(const std::string &library, const std::string &fname, Args... args)
DLLoaderBase(DLLoaderBase &&)=delete
GLuint const GLchar * name
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLsizei const GLchar *const * path
void operator()(handle_ptr_t p)
static constexpr const char * prefix
static constexpr const char * suffix