diff --git a/include/ircd/mods.h b/include/ircd/mods.h index dfaf6a9b7..d3fc51326 100644 --- a/include/ircd/mods.h +++ b/include/ircd/mods.h @@ -41,6 +41,8 @@ using mapi::version_t; IRCD_EXCEPTION(ircd::error, error) IRCD_EXCEPTION(error, filesystem_error) IRCD_EXCEPTION(error, invalid_export) +IRCD_EXCEPTION(error, expired_symbol) +IRCD_EXCEPTION(error, undefined_symbol) extern struct log::log log; @@ -80,6 +82,38 @@ struct module template<> const uint8_t *module::ptr(const std::string &name) const; template<> uint8_t *module::ptr(const std::string &name); +class sym_ptr +:std::weak_ptr +{ + void *ptr; + + public: + operator bool() const { return !expired(); } + bool operator!() const { return expired(); } + + template const T *get() const; + template T *get(); + + template const T *operator->() const; + template T *operator->(); + + template const T &operator*() const; + template T &operator*(); + + sym_ptr(const std::string &modname, const std::string &symname); + ~sym_ptr() noexcept; +}; + +template +struct sym_ref +:protected sym_ptr +{ + operator const T &() const { return sym_ptr::operator*(); } + operator T &() { return sym_ptr::operator*(); } + + using sym_ptr::sym_ptr; +}; + std::vector symbols(const std::string &fullpath, const std::string §ion); std::vector symbols(const std::string &fullpath); std::vector sections(const std::string &fullpath); @@ -114,6 +148,57 @@ using mods::module; // Bring struct module into mai } // namespace ircd +template +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(); +} + +template +T * +ircd::mods::sym_ptr::operator->() +{ + return get(); +} + +template +T * +ircd::mods::sym_ptr::get() +{ + return reinterpret_cast(ptr); +} + +template +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(); +} + +template +const T * +ircd::mods::sym_ptr::operator->() +const +{ + return get(); +} + +template +const T * +ircd::mods::sym_ptr::get() +const +{ + return reinterpret_cast(ptr); +} + template T & ircd::mods::module::get(const std::string &name) diff --git a/ircd/ircd.cc b/ircd/ircd.cc index 2f1d99d21..cee263bcd 100644 --- a/ircd/ircd.cc +++ b/ircd/ircd.cc @@ -105,8 +105,8 @@ try module listener("listen.so"); module client_versions("client_versions.so"); - module client_login("client_login.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 // to shutdown, but it can do other things eventually. Other subsystems may have diff --git a/ircd/mods.cc b/ircd/mods.cc index eb2076029..c39e133f7 100644 --- a/ircd/mods.cc +++ b/ircd/mods.cc @@ -174,8 +174,8 @@ const template<> uint8_t * ircd::mods::module::ptr(const std::string &name) { - const auto &mod(**this); - return &mod.handle.get(name); + auto &mod(**this); + return mod.ptr(name); } template<> @@ -184,7 +184,7 @@ ircd::mods::module::ptr(const std::string &name) const { const auto &mod(**this); - return &mod.handle.get(name); + return mod.ptr(name); } bool @@ -195,7 +195,35 @@ const return false; 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 +{ + module(modname) +} +,ptr{[this, &modname, &symname] +{ + const life_guard 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 +{ } ///////////////////////////////////////////////////////////////////////////////