0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-15 14:31:11 +01:00

ircd::mods: Interface modernization; various cleanup; reorg.

This commit is contained in:
Jason Volk 2018-03-25 14:32:24 -07:00
parent 8050628748
commit f36af09789
8 changed files with 265 additions and 250 deletions

View file

@ -32,13 +32,13 @@ struct ircd::mods::import_shared
operator T &() { return std::shared_ptr<T>::operator*(); } operator T &() { return std::shared_ptr<T>::operator*(); }
import_shared() = default; import_shared() = default;
import_shared(module, const std::string &symname); import_shared(module, const string_view &symname);
import_shared(const std::string &modname, const std::string &symname); import_shared(const string_view &modname, const string_view &symname);
}; };
template<class T> template<class T>
ircd::mods::import_shared<T>::import_shared(const std::string &modname, ircd::mods::import_shared<T>::import_shared(const string_view &modname,
const std::string &symname) const string_view &symname)
:import_shared :import_shared
{ {
module(modname), symname module(modname), symname
@ -47,7 +47,7 @@ ircd::mods::import_shared<T>::import_shared(const std::string &modname,
template<class T> template<class T>
ircd::mods::import_shared<T>::import_shared(module module, ircd::mods::import_shared<T>::import_shared(module module,
const std::string &symname) const string_view &symname)
:import<std::shared_ptr<T>> :import<std::shared_ptr<T>>
{ {
module, symname module, symname

View file

@ -24,6 +24,14 @@ namespace ircd::mods
string_view name(const mod &); string_view name(const mod &);
string_view path(const mod &); string_view path(const mod &);
bool has(const mod &, const string_view &sym);
template<class T = uint8_t> const T *ptr(const mod &, const string_view &sym);
template<class T = uint8_t> T *ptr(mod &, const string_view &sym);
template<class T> const T &get(const mod &, const string_view &sym);
template<class T> T &get(mod &, const string_view &sym);
} }
#include "paths.h" #include "paths.h"
@ -36,17 +44,17 @@ namespace ircd::mods
// misc util // misc util
namespace ircd::mods namespace ircd::mods
{ {
bool loaded(const std::string &name); bool loaded(const string_view &name);
bool available(const std::string &name); bool available(const string_view &name);
bool is_module(const std::string &fullpath); bool is_module(const string_view &fullpath);
bool is_module(const std::string &fullpath, std::nothrow_t); bool is_module(const string_view &fullpath, std::nothrow_t);
bool is_module(const std::string &fullpath, std::string &why); bool is_module(const string_view &fullpath, std::string &why);
// returns dir/name of first dir containing 'name' (and this will be // returns dir/name of first dir containing 'name' (and this will be
// a loadable module). Unlike libltdl, the reason each individual // a loadable module). Unlike libltdl, the reason each individual
// candidate failed is presented in a vector. // candidate failed is presented in a vector.
std::string search(const std::string &name, std::vector<std::string> &why); std::string search(const string_view &name, std::vector<std::string> &why);
std::string search(const std::string &name); std::string search(const string_view &name);
// Potential modules available to load // Potential modules available to load
std::forward_list<std::string> available(); std::forward_list<std::string> available();
@ -59,3 +67,41 @@ namespace ircd
using mods::import; using mods::import;
using mods::import_shared; using mods::import_shared;
} }
namespace ircd::mods
{
template<> const uint8_t *ptr<const uint8_t>(const mod &, const string_view &sym);
template<> uint8_t *ptr<uint8_t>(mod &, const string_view &sym);
}
template<class T>
T &
ircd::mods::get(mod &mod,
const string_view &sym)
{
return *ptr<T>(mod, sym);
}
template<class T>
const T &
ircd::mods::get(const mod &mod,
const string_view &sym)
{
return *ptr<T>(mod, sym);
}
template<class T>
T *
ircd::mods::ptr(mod &mod,
const string_view &sym)
{
return reinterpret_cast<T *>(ptr<uint8_t>(mod, sym));
}
template<class T>
const T *
ircd::mods::ptr(const mod &mod,
const string_view &sym)
{
return reinterpret_cast<const T *>(ptr<const uint8_t>(mod, sym));
}

View file

@ -19,58 +19,71 @@ namespace ircd::mods
struct ircd::mods::module struct ircd::mods::module
:std::shared_ptr<mod> :std::shared_ptr<mod>
{ {
const std::string &name() const; operator const mod &() const;
const std::string &path() const; operator mod &();
const std::string &mangle(const std::string &) const;
bool has(const std::string &name) const; string_view name() const;
string_view path() const;
template<class T = uint8_t> const T *ptr(const std::string &name) const; bool has(const string_view &sym) const;
template<class T = uint8_t> T *ptr(const std::string &name);
template<class T> const T &get(const std::string &name) const; template<class T = uint8_t> const T *ptr(const string_view &sym) const;
template<class T> T &get(const std::string &name); template<class T = uint8_t> T *ptr(const string_view &sym);
module(std::shared_ptr<mod> ptr = {}) template<class T> const T &get(const string_view &sym) const;
:std::shared_ptr<mod>{std::move(ptr)} template<class T> T &get(const string_view &sym);
{}
module(const std::string &name); module(std::shared_ptr<mod> ptr = {});
module(const string_view &name);
~module() noexcept; ~module() noexcept;
}; };
namespace ircd::mods inline
{ ircd::mods::module::module(std::shared_ptr<mod> ptr)
template<> const uint8_t *module::ptr<const uint8_t>(const std::string &name) const; :std::shared_ptr<mod>{std::move(ptr)}
template<> uint8_t *module::ptr<uint8_t>(const std::string &name); {}
}
template<class T> template<class T>
T & T &
ircd::mods::module::get(const std::string &name) ircd::mods::module::get(const string_view &sym)
{ {
return *ptr<T>(name); return mods::get<T>(*this, sym);
} }
template<class T> template<class T>
const T & const T &
ircd::mods::module::get(const std::string &name) ircd::mods::module::get(const string_view &sym)
const const
{ {
return *ptr<T>(name); return mods::get<T>(*this, sym);
} }
template<class T> template<class T>
T * T *
ircd::mods::module::ptr(const std::string &name) ircd::mods::module::ptr(const string_view &sym)
{ {
return reinterpret_cast<T *>(ptr<uint8_t>(name)); return mods::ptr<T>(*this, sym);
} }
template<class T> template<class T>
const T * const T *
ircd::mods::module::ptr(const std::string &name) ircd::mods::module::ptr(const string_view &sym)
const const
{ {
return reinterpret_cast<const T *>(ptr<const uint8_t>(name)); return mods::ptr<T>(*this, sym);
}
inline ircd::mods::module::operator
mod &()
{
assert(bool(*this));
return std::shared_ptr<mod>::operator*();
}
inline ircd::mods::module::operator
const mod &()
const
{
assert(bool(*this));
return std::shared_ptr<mod>::operator*();
} }

View file

@ -16,18 +16,20 @@ namespace ircd::mods
struct paths extern paths; struct paths extern paths;
// Platform (.so|.dll) postfixing // Platform (.so|.dll) postfixing
std::string postfixed(const std::string &name); std::string postfixed(std::string name);
std::string unpostfixed(const std::string &name); std::string postfixed(const string_view &);
std::string unpostfixed(std::string name);
std::string unpostfixed(const string_view &);
} }
struct ircd::mods::paths struct ircd::mods::paths
:std::vector<std::string> :std::vector<std::string>
{ {
bool added(const std::string &dir) const; bool added(const string_view &dir) const;
bool del(const std::string &dir); bool del(const string_view &dir);
bool add(const std::string &dir, std::nothrow_t); bool add(const string_view &dir, std::nothrow_t);
bool add(const std::string &dir); bool add(const string_view &dir);
paths(); paths();
}; };

View file

@ -37,9 +37,8 @@ class ircd::mods::sym_ptr
template<class T> T &operator*(); template<class T> T &operator*();
sym_ptr() = default; sym_ptr() = default;
sym_ptr(module, const std::string &symname); sym_ptr(module, const string_view &symname);
sym_ptr(const std::string &modname, const std::string &symname); sym_ptr(const string_view &modname, const string_view &symname);
~sym_ptr() noexcept;
}; };
template<class T> template<class T>

View file

@ -14,16 +14,16 @@
namespace ircd::mods namespace ircd::mods
{ {
// Section & Symbol utilites // Section & Symbol utilites
std::vector<std::string> sections(const std::string &fullpath); std::vector<std::string> sections(const string_view &fullpath);
std::vector<std::string> symbols(const std::string &fullpath, const std::string &section); std::vector<std::string> symbols(const string_view &fullpath, const string_view &section);
std::vector<std::string> symbols(const std::string &fullpath); std::vector<std::string> symbols(const string_view &fullpath);
std::unordered_map<std::string, std::string> mangles(const std::vector<std::string> &); std::unordered_map<std::string, std::string> mangles(const std::vector<std::string> &);
std::unordered_map<std::string, std::string> mangles(const std::string &fullpath, const std::string &section); std::unordered_map<std::string, std::string> mangles(const string_view &fullpath, const string_view &section);
std::unordered_map<std::string, std::string> mangles(const std::string &fullpath); std::unordered_map<std::string, std::string> mangles(const string_view &fullpath);
// Find module names where symbol resides // Find module names where symbol resides
bool has_symbol(const std::string &name, const std::string &symbol); bool has_symbol(const string_view &name, const string_view &symbol);
std::vector<std::string> find_symbol(const std::string &symbol); std::vector<std::string> find_symbol(const string_view &symbol);
} }

View file

@ -30,14 +30,6 @@ ircd::mods::suffix
boost::dll::shared_library::suffix() boost::dll::shared_library::suffix()
}; };
std::stack<ircd::mods::mod *>
ircd::mods::mod::loading
{};
std::map<std::string, ircd::mods::mod *>
ircd::mods::mod::loaded
{};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// mods/mods.h (misc util) // mods/mods.h (misc util)
@ -58,7 +50,9 @@ ircd::mods::available()
} }
catch(const filesystem::filesystem_error &e) catch(const filesystem::filesystem_error &e)
{ {
log.warning("Module path [%s]: %s", dir, e.what()); log.warning("Module path [%s]: %s",
dir,
e.what());
continue; continue;
} }
@ -66,14 +60,16 @@ ircd::mods::available()
} }
filesystem::path filesystem::path
ircd::mods::fullpath(const std::string &name) ircd::mods::fullpath(const string_view &name)
{ {
std::vector<std::string> why; std::vector<std::string> why;
const filesystem::path path(search(name, why)); const filesystem::path path(search(name, why));
if(path.empty()) if(path.empty())
{ {
for(const auto &str : why) for(const auto &str : why)
log.error("candidate for module '%s' failed: %s", name, str); log.error("candidate for module '%s' failed: %s",
name,
str);
throw error throw error
{ {
@ -85,23 +81,29 @@ ircd::mods::fullpath(const std::string &name)
} }
std::string std::string
ircd::mods::search(const std::string &name) ircd::mods::search(const string_view &name)
{ {
std::vector<std::string> why; std::vector<std::string> why;
return search(name, why); return search(name, why);
} }
std::string std::string
ircd::mods::search(const std::string &name, ircd::mods::search(const string_view &name,
std::vector<std::string> &why) std::vector<std::string> &why)
{ {
using filesystem::path; using filesystem::path;
const path path(postfixed(name)); const path path
{
postfixed(name)
};
if(!path.is_relative()) if(!path.is_relative())
{ {
why.resize(why.size() + 1); why.resize(why.size() + 1);
return is_module(path, why.back())? name : std::string{}; return is_module(path, why.back())?
std::string{name}:
std::string{};
} }
else for(const auto &dir : paths) else for(const auto &dir : paths)
{ {
@ -114,23 +116,23 @@ ircd::mods::search(const std::string &name,
} }
bool bool
ircd::mods::is_module(const std::string &fullpath) ircd::mods::is_module(const string_view &fullpath)
{ {
return is_module(filesystem::path(fullpath)); return is_module(filesystem::path(std::string{fullpath}));
} }
bool bool
ircd::mods::is_module(const std::string &fullpath, ircd::mods::is_module(const string_view &fullpath,
std::nothrow_t) std::nothrow_t)
{ {
return is_module(filesystem::path(fullpath), std::nothrow); return is_module(filesystem::path(std::string{fullpath}), std::nothrow);
} }
bool bool
ircd::mods::is_module(const std::string &fullpath, ircd::mods::is_module(const string_view &fullpath,
std::string &why) std::string &why)
{ {
return is_module(filesystem::path(fullpath), why); return is_module(filesystem::path(std::string{fullpath}), why);
} }
bool bool
@ -174,7 +176,7 @@ ircd::mods::is_module(const filesystem::path &path)
} }
bool bool
ircd::mods::available(const std::string &name) ircd::mods::available(const string_view &name)
{ {
using filesystem::path; using filesystem::path;
@ -183,7 +185,7 @@ ircd::mods::available(const std::string &name)
} }
bool bool
ircd::mods::loaded(const std::string &name) ircd::mods::loaded(const string_view &name)
{ {
return mod::loaded.count(name); return mod::loaded.count(name);
} }
@ -193,8 +195,8 @@ ircd::mods::loaded(const std::string &name)
// mods/sym_ptr.h // mods/sym_ptr.h
// //
ircd::mods::sym_ptr::sym_ptr(const std::string &modname, ircd::mods::sym_ptr::sym_ptr(const string_view &modname,
const std::string &symname) const string_view &symname)
:sym_ptr :sym_ptr
{ {
module(modname), symname module(modname), symname
@ -203,40 +205,33 @@ ircd::mods::sym_ptr::sym_ptr(const std::string &modname,
} }
ircd::mods::sym_ptr::sym_ptr(module module, ircd::mods::sym_ptr::sym_ptr(module module,
const std::string &symname) const string_view &symname)
:std::weak_ptr<mod> :std::weak_ptr<mod>
{ {
module module
} }
,ptr{[this, &symname] ,ptr{[this, &module, &symname]
{ {
const life_guard<mods::mod> mod{*this}; if(unlikely(!module.has(symname)))
const auto &mangled(mod->mangle(symname));
if(unlikely(!mod->has(mangled)))
throw undefined_symbol throw undefined_symbol
{ {
"Could not find symbol '%s' (%s) in module '%s'", "Could not find symbol '%s' (%s) in module '%s'",
demangle(symname),
symname, symname,
mangled, module.name()
mod->name()
}; };
return mod->ptr(mangled); return module.ptr(symname);
}()} }()}
{ {
} }
ircd::mods::sym_ptr::~sym_ptr()
noexcept
{
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// mods/module.h // mods/module.h
// //
ircd::mods::module::module(const std::string &name) ircd::mods::module::module(const string_view &name)
try try
:std::shared_ptr<mod>{[&name] :std::shared_ptr<mod>{[&name]
{ {
@ -255,14 +250,19 @@ try
}; };
const auto path(fullpath(name)); const auto path(fullpath(name));
log.debug("Attempting to load '%s' @ `%s'", name, path.string()); log.debug("Attempting to load '%s' @ `%s'",
name,
path.string());
return std::make_shared<mod>(path, flags); return std::make_shared<mod>(path, flags);
}()} }()}
{ {
} }
catch(const std::exception &e) catch(const std::exception &e)
{ {
log.error("Failed to load '%s': %s", name, e.what()); log.error("Failed to load '%s': %s",
name,
e.what());
throw; throw;
} }
@ -271,73 +271,25 @@ noexcept
{ {
} }
const std::string & ircd::string_view
ircd::mods::module::path() ircd::mods::module::path()
const const
{ {
if(unlikely(!*this)) return mods::path(*this);
{
static const std::string empty;
return empty;
}
auto &mod(**this);
return mod.location();
} }
const std::string & ircd::string_view
ircd::mods::module::name() ircd::mods::module::name()
const const
{ {
if(unlikely(!*this)) return mods::name(*this);
{
static const std::string empty;
return empty;
}
auto &mod(**this);
return mod.name();
}
template<> uint8_t *
ircd::mods::module::ptr<uint8_t>(const std::string &name)
{
auto &mod(**this);
return mod.ptr<uint8_t>(mangle(name));
}
template<>
const uint8_t *
ircd::mods::module::ptr<const uint8_t>(const std::string &name)
const
{
const auto &mod(**this);
return mod.ptr<const uint8_t>(mangle(name));
} }
bool bool
ircd::mods::module::has(const std::string &name) ircd::mods::module::has(const string_view &name)
const const
{ {
if(unlikely(!*this)) return mods::has(*this, name);
return false;
const auto &mod(**this);
return mod.has(mangle(name));
}
const std::string &
ircd::mods::module::mangle(const std::string &name)
const
{
if(unlikely(!*this))
{
static const std::string empty;
return empty;
}
const auto &mod(**this);
return mod.mangle(name);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -346,7 +298,7 @@ const
// //
std::vector<std::string> std::vector<std::string>
ircd::mods::find_symbol(const std::string &symbol) ircd::mods::find_symbol(const string_view &symbol)
{ {
std::vector<std::string> ret; std::vector<std::string> ret;
const auto av(available()); const auto av(available());
@ -360,8 +312,8 @@ ircd::mods::find_symbol(const std::string &symbol)
} }
bool bool
ircd::mods::has_symbol(const std::string &name, ircd::mods::has_symbol(const string_view &name,
const std::string &symbol) const string_view &symbol)
{ {
const auto path(fullpath(name)); const auto path(fullpath(name));
if(path.empty()) if(path.empty())
@ -372,16 +324,16 @@ ircd::mods::has_symbol(const std::string &name,
} }
std::unordered_map<std::string, std::string> std::unordered_map<std::string, std::string>
ircd::mods::mangles(const std::string &fullpath) ircd::mods::mangles(const string_view &fullpath)
{ {
return mangles(filesystem::path(fullpath)); return mangles(filesystem::path(std::string{fullpath}));
} }
std::unordered_map<std::string, std::string> std::unordered_map<std::string, std::string>
ircd::mods::mangles(const std::string &fullpath, ircd::mods::mangles(const string_view &fullpath,
const std::string &section) const string_view &section)
{ {
return mangles(filesystem::path(fullpath), section); return mangles(filesystem::path(std::string{fullpath}), section);
} }
std::unordered_map<std::string, std::string> std::unordered_map<std::string, std::string>
@ -392,7 +344,7 @@ ircd::mods::mangles(const filesystem::path &path)
std::unordered_map<std::string, std::string> std::unordered_map<std::string, std::string>
ircd::mods::mangles(const filesystem::path &path, ircd::mods::mangles(const filesystem::path &path,
const std::string &section) const string_view &section)
{ {
return mangles(mods::symbols(path, section)); return mangles(mods::symbols(path, section));
} }
@ -414,16 +366,16 @@ ircd::mods::mangles(const std::vector<std::string> &symbols)
} }
std::vector<std::string> std::vector<std::string>
ircd::mods::symbols(const std::string &fullpath) ircd::mods::symbols(const string_view &fullpath)
{ {
return symbols(filesystem::path(fullpath)); return symbols(filesystem::path(std::string{fullpath}));
} }
std::vector<std::string> std::vector<std::string>
ircd::mods::symbols(const std::string &fullpath, ircd::mods::symbols(const string_view &fullpath,
const std::string &section) const string_view &section)
{ {
return symbols(filesystem::path(fullpath), section); return symbols(filesystem::path(std::string{fullpath}), std::string{section});
} }
std::vector<std::string> std::vector<std::string>
@ -438,19 +390,19 @@ ircd::mods::symbols(const filesystem::path &path)
std::vector<std::string> std::vector<std::string>
ircd::mods::symbols(const filesystem::path &path, ircd::mods::symbols(const filesystem::path &path,
const std::string &section) const string_view &section)
{ {
return info<std::vector<std::string>>(path, [&section] return info<std::vector<std::string>>(path, [&section]
(boost::dll::library_info &info) (boost::dll::library_info &info)
{ {
return info.symbols(section); return info.symbols(std::string{section});
}); });
} }
std::vector<std::string> std::vector<std::string>
ircd::mods::sections(const std::string &fullpath) ircd::mods::sections(const string_view &fullpath)
{ {
return sections(filesystem::path(fullpath)); return sections(filesystem::path(std::string{fullpath}));
} }
std::vector<std::string> std::vector<std::string>
@ -470,10 +422,16 @@ ircd::mods::info(const filesystem::path &path,
F&& closure) F&& closure)
{ {
if(!exists(path)) if(!exists(path))
throw filesystem_error("`%s' does not exist", path.string()); throw filesystem_error
{
"`%s' does not exist", path.string()
};
if(!is_regular_file(path)) if(!is_regular_file(path))
throw filesystem_error("`%s' is not a file", path.string()); throw filesystem_error
{
"`%s' is not a file", path.string()
};
boost::dll::library_info info(path); boost::dll::library_info info(path);
return closure(info); return closure(info);
@ -500,15 +458,27 @@ ircd::mods::paths
{}; {};
std::string std::string
ircd::mods::unpostfixed(const std::string &name) ircd::mods::unpostfixed(const string_view &name)
{ {
return unpostfixed(filesystem::path(name)).string(); return unpostfixed(std::string{name});
} }
std::string std::string
ircd::mods::postfixed(const std::string &name) ircd::mods::unpostfixed(std::string name)
{ {
return postfixed(filesystem::path(name)).string(); return unpostfixed(filesystem::path(std::move(name))).string();
}
std::string
ircd::mods::postfixed(const string_view &name)
{
return postfixed(std::string{name});
}
std::string
ircd::mods::postfixed(std::string name)
{
return postfixed(filesystem::path(std::move(name))).string();
} }
filesystem::path filesystem::path
@ -549,11 +519,14 @@ ircd::mods::paths::paths()
} }
bool bool
ircd::mods::paths::add(const std::string &dir) ircd::mods::paths::add(const string_view &dir)
{ {
using filesystem::path; using filesystem::path;
const path path(prefix_if_relative(dir)); const path path
{
prefix_if_relative(std::string{dir})
};
if(!exists(path)) if(!exists(path))
throw filesystem_error throw filesystem_error
@ -575,7 +548,7 @@ ircd::mods::paths::add(const std::string &dir)
} }
bool bool
ircd::mods::paths::add(const std::string &dir, ircd::mods::paths::add(const string_view &dir,
std::nothrow_t) std::nothrow_t)
try try
{ {
@ -588,14 +561,14 @@ catch(const std::exception &e)
} }
bool bool
ircd::mods::paths::del(const std::string &dir) ircd::mods::paths::del(const string_view &dir)
{ {
std::remove(begin(), end(), prefix_if_relative(dir).string()); std::remove(begin(), end(), prefix_if_relative(std::string{dir}).string());
return true; return true;
} }
bool bool
ircd::mods::paths::added(const std::string &dir) ircd::mods::paths::added(const string_view &dir)
const const
{ {
return std::find(begin(), end(), dir) != end(); return std::find(begin(), end(), dir) != end();
@ -606,6 +579,28 @@ const
// mods/mods.h // mods/mods.h
// //
template<> uint8_t *
ircd::mods::ptr<uint8_t>(mod &mod,
const string_view &sym)
{
return &mod.handle.get<uint8_t>(std::string{sym});
}
template<>
const uint8_t *
ircd::mods::ptr<const uint8_t>(const mod &mod,
const string_view &sym)
{
return &mod.handle.get<const uint8_t>(std::string{sym});
}
bool
ircd::mods::has(const mod &mod,
const string_view &name)
{
return mod.handle.has(std::string{name});
}
ircd::string_view ircd::string_view
ircd::mods::name(const mod &mod) ircd::mods::name(const mod &mod)
{ {
@ -623,6 +618,14 @@ ircd::mods::path(const mod &mod)
// (internal) mods.h // (internal) mods.h
// //
decltype(ircd::mods::mod::loading)
ircd::mods::mod::loading
{};
decltype(ircd::mods::mod::loaded)
ircd::mods::mod::loaded
{};
ircd::mods::mod::mod(const filesystem::path &path, ircd::mods::mod::mod(const filesystem::path &path,
const load_mode::type &mode) const load_mode::type &mode)
try try
@ -718,6 +721,7 @@ try
description().size()? description() : "<no description>"s); description().size()? description() : "<no description>"s);
// Without init exception, the module is now considered loaded. // Without init exception, the module is now considered loaded.
assert(!loaded.count(name()));
loaded.emplace(name(), this); loaded.emplace(name(), this);
} }
catch(const boost::system::system_error &e) catch(const boost::system::system_error &e)
@ -758,11 +762,20 @@ bool ircd::mapi::static_destruction;
ircd::mods::mod::~mod() ircd::mods::mod::~mod()
noexcept try noexcept try
{ {
log.debug("Attempting unload module '%s' @ `%s'",
name(),
location());
unload(); unload();
const size_t erased(loaded.erase(name()));
assert(erased == 1);
} }
catch(const std::exception &e) catch(const std::exception &e)
{ {
log::critical("Module @%p unload: %s", (const void *)this, e.what()); log.critical("Module @%p unload: %s",
(const void *)this,
e.what());
if(!ircd::debugmode) if(!ircd::debugmode)
return; return;
@ -774,11 +787,6 @@ ircd::mods::mod::unload()
if(!handle.is_loaded()) if(!handle.is_loaded())
return false; return false;
const auto name(this->name());
log.debug("Attempting unload module '%s' @ `%s'", name, location());
const size_t erased(loaded.erase(name));
assert(erased == 1);
if(header->fini) if(header->fini)
header->fini(); header->fini();
@ -794,66 +802,21 @@ ircd::mods::mod::unload()
ptr->unload(); ptr->unload();
}); });
log.debug("Attempting static unload for '%s' @ `%s'", name, location()); log.debug("Attempting static unload for '%s' @ `%s'",
name(),
location());
mapi::static_destruction = false; mapi::static_destruction = false;
handle.unload(); handle.unload();
assert(!handle.is_loaded()); assert(!handle.is_loaded());
if(!mapi::static_destruction) if(!mapi::static_destruction)
{ {
log.error("Module \"%s\" is stuck and failing to unload.", name); log.critical("Module \"%s\" is stuck and failing to unload.", name());
log.warning("Module \"%s\" may result in undefined behavior if not fixed.", name); log.critical("Module \"%s\" may result in undefined behavior if not fixed.", name());
} else { } else {
log.info("Unloaded '%s'", name); log.info("Unloaded '%s'", name());
} }
return true; return true;
} }
const std::string &
ircd::mods::mod::mangle(const std::string &name)
const
{
const auto it(mangles.find(name));
if(it == end(mangles))
return name;
const auto &mangled(it->second);
return mangled;
}
template<class T>
T *
ircd::mods::mod::ptr(const std::string &name)
{
return &handle.get<T>(name);
}
template<class T>
const T *
ircd::mods::mod::ptr(const std::string &name)
const
{
return &handle.get<T>(name);
}
template<class T>
T &
ircd::mods::mod::get(const std::string &name)
{
handle.get<T>(name);
}
template<class T>
const T &
ircd::mods::mod::get(const std::string &name)
const
{
handle.get<T>(name);
}
bool
ircd::mods::mod::has(const std::string &name)
const
{
return handle.has(name);
}

View file

@ -22,13 +22,13 @@ namespace ircd::mods
template<class R, class F> R info(const filesystem::path &, F&& closure); template<class R, class F> R info(const filesystem::path &, F&& closure);
std::vector<std::string> sections(const filesystem::path &path); std::vector<std::string> sections(const filesystem::path &path);
std::vector<std::string> symbols(const filesystem::path &path); std::vector<std::string> symbols(const filesystem::path &path);
std::vector<std::string> symbols(const filesystem::path &path, const std::string &section); std::vector<std::string> symbols(const filesystem::path &path, const string_view &section);
std::unordered_map<std::string, std::string> mangles(const std::vector<std::string> &); std::unordered_map<std::string, std::string> mangles(const std::vector<std::string> &);
std::unordered_map<std::string, std::string> mangles(const filesystem::path &path); std::unordered_map<std::string, std::string> mangles(const filesystem::path &path);
std::unordered_map<std::string, std::string> mangles(const filesystem::path &path, const std::string &section); std::unordered_map<std::string, std::string> mangles(const filesystem::path &path, const string_view &section);
// Get the full path of a [valid] available module by name // Get the full path of a [valid] available module by name
filesystem::path fullpath(const std::string &name); filesystem::path fullpath(const string_view &name);
// Checks if loadable module containing a mapi header (does not verify the magic) // Checks if loadable module containing a mapi header (does not verify the magic)
bool is_module(const filesystem::path &); bool is_module(const filesystem::path &);
@ -40,8 +40,8 @@ namespace ircd::mods
struct ircd::mods::mod struct ircd::mods::mod
:std::enable_shared_from_this<mod> :std::enable_shared_from_this<mod>
{ {
static std::stack<mod *> loading; // State of current dlopen() recursion. static std::stack<mod *> loading; // State of current dlopen() recursion.
static std::map<std::string, mod *> loaded; static std::map<string_view, mod *, std::less<>> loaded;
filesystem::path path; filesystem::path path;
load_mode::type mode; load_mode::type mode;
@ -61,14 +61,6 @@ struct ircd::mods::mod
auto &version() const { return header->version; } auto &version() const { return header->version; }
auto &description() const { return (*this)["description"]; } auto &description() const { return (*this)["description"]; }
const std::string &mangle(const std::string &name) const;
bool has(const std::string &name) const;
template<class T> const T &get(const std::string &name) const;
template<class T> T &get(const std::string &name);
template<class T = uint8_t> const T *ptr(const std::string &name) const;
template<class T = uint8_t> T *ptr(const std::string &name);
bool unload(); bool unload();
mod(const filesystem::path &, mod(const filesystem::path &,