// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_IRCD_MODS_SYM_PTR_H namespace ircd::mods { struct sym_ptr; template::value>::type * = nullptr> decltype(auto) invoke(F *const &f, args&&... a); template::value>::type * = nullptr> decltype(auto) invoke(F *const &f, O *const &o, args&&... a); } /// Representation of a symbol in a loaded library (non-template; low level). /// class ircd::mods::sym_ptr :std::weak_ptr { void *ptr {nullptr}; public: bool operator!() const; explicit operator bool() const; template const T *get() const; template const T *operator->() const; template const T &operator*() const; template decltype(auto) operator()(args&&... a) const; void *&get(); template T *get(); template T *operator->(); template T &operator*(); explicit sym_ptr(mod &, const string_view &symname); sym_ptr(module, const string_view &symname); sym_ptr(const string_view &modname, const string_view &symname); sym_ptr() = default; }; 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" }; assert(ptr); return *operator->(); } template T * ircd::mods::sym_ptr::operator->() { return get(); } template T * ircd::mods::sym_ptr::get() { return reinterpret_cast(ptr); } inline void *& ircd::mods::sym_ptr::get() { return ptr; } template __attribute__((always_inline, artificial)) inline decltype(auto) ircd::mods::sym_ptr::operator()(args&&... a) const { return invoke(get(), std::forward(a)...); } 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" }; assert(ptr); return *operator->(); } template const T * ircd::mods::sym_ptr::operator->() const { return get(); } template const T * ircd::mods::sym_ptr::get() const { return reinterpret_cast(ptr); } inline ircd::mods::sym_ptr::operator bool() const { return !operator!(); } inline bool ircd::mods::sym_ptr::operator!() const { return !ptr || expired(); } template::value>::type *> __attribute__((always_inline, gnu_inline, artificial)) inline extern decltype(auto) ircd::mods::invoke(F *const &f, O *const &o, args&&... a) { const void *const nv(f); const F mfp(*reinterpret_cast(&nv)); O *const volatile that(o); return std::invoke(mfp, that, std::forward(a)...); } template::value>::type *> __attribute__((always_inline, gnu_inline, artificial)) inline extern decltype(auto) ircd::mods::invoke(F *const &f, args&&... a) { return std::invoke(f, std::forward(a)...); }