0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-29 10:12:39 +01:00

ircd::mods: Add sym_ptr/sym_ref to link symbols with a typed object.

This commit is contained in:
Jason Volk 2017-03-20 20:38:34 -07:00
parent a8fc400130
commit 6a0e5e4de5
3 changed files with 118 additions and 5 deletions

View file

@ -41,6 +41,8 @@ using mapi::version_t;
IRCD_EXCEPTION(ircd::error, error) IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, filesystem_error) IRCD_EXCEPTION(error, filesystem_error)
IRCD_EXCEPTION(error, invalid_export) IRCD_EXCEPTION(error, invalid_export)
IRCD_EXCEPTION(error, expired_symbol)
IRCD_EXCEPTION(error, undefined_symbol)
extern struct log::log log; extern struct log::log log;
@ -80,6 +82,38 @@ struct module
template<> const uint8_t *module::ptr<const uint8_t>(const std::string &name) const; template<> const uint8_t *module::ptr<const uint8_t>(const std::string &name) const;
template<> uint8_t *module::ptr<uint8_t>(const std::string &name); template<> uint8_t *module::ptr<uint8_t>(const std::string &name);
class sym_ptr
:std::weak_ptr<mod>
{
void *ptr;
public:
operator bool() const { return !expired(); }
bool operator!() const { return expired(); }
template<class T> const T *get() const;
template<class T> T *get();
template<class T> const T *operator->() const;
template<class T> T *operator->();
template<class T> const T &operator*() const;
template<class T> T &operator*();
sym_ptr(const std::string &modname, const std::string &symname);
~sym_ptr() noexcept;
};
template<class T>
struct sym_ref
:protected sym_ptr
{
operator const T &() const { return sym_ptr::operator*<T>(); }
operator T &() { return sym_ptr::operator*<T>(); }
using sym_ptr::sym_ptr;
};
std::vector<std::string> symbols(const std::string &fullpath, const std::string &section); std::vector<std::string> symbols(const std::string &fullpath, const std::string &section);
std::vector<std::string> symbols(const std::string &fullpath); std::vector<std::string> symbols(const std::string &fullpath);
std::vector<std::string> sections(const std::string &fullpath); std::vector<std::string> sections(const std::string &fullpath);
@ -114,6 +148,57 @@ using mods::module; // Bring struct module into mai
} // namespace ircd } // namespace ircd
template<class T>
T &
ircd::mods::sym_ptr::operator*()
{
if(unlikely(expired()))
throw expired_symbol("The reference to a symbol in another module is no longer valid");
return *get<T>();
}
template<class T>
T *
ircd::mods::sym_ptr::operator->()
{
return get<T>();
}
template<class T>
T *
ircd::mods::sym_ptr::get()
{
return reinterpret_cast<T *>(ptr);
}
template<class T>
const T &
ircd::mods::sym_ptr::operator*()
const
{
if(unlikely(expired()))
throw expired_symbol("The const reference to a symbol in another module is no longer valid");
return *get<T>();
}
template<class T>
const T *
ircd::mods::sym_ptr::operator->()
const
{
return get<T>();
}
template<class T>
const T *
ircd::mods::sym_ptr::get()
const
{
return reinterpret_cast<const T *>(ptr);
}
template<class T> template<class T>
T & T &
ircd::mods::module::get(const std::string &name) ircd::mods::module::get(const std::string &name)

View file

@ -105,8 +105,8 @@ try
module listener("listen.so"); module listener("listen.so");
module client_versions("client_versions.so"); module client_versions("client_versions.so");
module client_login("client_login.so");
module client_register("client_register.so"); module client_register("client_register.so");
module client_login("client_login.so");
// This is the main program loop. Right now all it does is sleep until notified // This is the main program loop. Right now all it does is sleep until notified
// to shutdown, but it can do other things eventually. Other subsystems may have // to shutdown, but it can do other things eventually. Other subsystems may have

View file

@ -174,8 +174,8 @@ const
template<> uint8_t * template<> uint8_t *
ircd::mods::module::ptr<uint8_t>(const std::string &name) ircd::mods::module::ptr<uint8_t>(const std::string &name)
{ {
const auto &mod(**this); auto &mod(**this);
return &mod.handle.get<uint8_t>(name); return mod.ptr<uint8_t>(name);
} }
template<> template<>
@ -184,7 +184,7 @@ ircd::mods::module::ptr<const uint8_t>(const std::string &name)
const const
{ {
const auto &mod(**this); const auto &mod(**this);
return &mod.handle.get<const uint8_t>(name); return mod.ptr<const uint8_t>(name);
} }
bool bool
@ -195,7 +195,35 @@ const
return false; return false;
const auto &mod(**this); const auto &mod(**this);
return mod.handle.has(name); return mod.has(name);
}
///////////////////////////////////////////////////////////////////////////////
//
// sym_ptr
//
ircd::mods::sym_ptr::sym_ptr(const std::string &modname,
const std::string &symname)
:std::weak_ptr<mod>
{
module(modname)
}
,ptr{[this, &modname, &symname]
{
const life_guard<mods::mod> mod(*this);
if(unlikely(!mod->has(symname)))
throw undefined_symbol("Could not find symbol '%s' in module '%s'", symname, mod->name());
return mod->ptr(symname);
}()}
{
}
ircd::mods::sym_ptr::~sym_ptr()
noexcept
{
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////