mirror of
https://github.com/matrix-construct/construct
synced 2024-09-07 09:15:19 +02:00
180 lines
3.1 KiB
C++
180 lines
3.1 KiB
C++
// Matrix Construct
|
|
//
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
//
|
|
// 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_IMPORT_H
|
|
|
|
namespace ircd::mods
|
|
{
|
|
template<class T> struct import;
|
|
struct imports extern imports;
|
|
}
|
|
|
|
struct ircd::mods::imports
|
|
:std::map<std::string, mods::module, std::less<>>
|
|
{};
|
|
|
|
/// Representation of a symbol in a loaded shared library
|
|
///
|
|
template<class T>
|
|
struct ircd::mods::import
|
|
:sym_ptr
|
|
{
|
|
std::string module_name;
|
|
std::string symbol_name;
|
|
|
|
void reload();
|
|
|
|
public:
|
|
template<class... args> auto operator()(args&&... a) const;
|
|
template<class... args> auto operator()(args&&... a);
|
|
|
|
const T *operator->() const;
|
|
const T &operator*() const;
|
|
operator const T &() const;
|
|
|
|
T *operator->();
|
|
T &operator*();
|
|
operator T &();
|
|
|
|
explicit import(const mods::module &, std::string symbol_name);
|
|
import(std::string module_name, std::string symbol_name);
|
|
};
|
|
|
|
template<class T>
|
|
ircd::mods::import<T>::import(std::string module_name,
|
|
std::string symbol_name)
|
|
:sym_ptr
|
|
{
|
|
// Note sym_ptr is purposely default constructed; this makes the import
|
|
// "lazy" and will be loaded via miss on first use. This is useful in
|
|
// the general use-case of static construction.
|
|
}
|
|
,module_name
|
|
{
|
|
std::move(module_name)
|
|
}
|
|
,symbol_name
|
|
{
|
|
std::move(symbol_name)
|
|
}
|
|
{}
|
|
|
|
template<class T>
|
|
ircd::mods::import<T>::import(const mods::module &module,
|
|
std::string symbol_name)
|
|
:sym_ptr
|
|
{
|
|
module, symbol_name
|
|
}
|
|
,module_name
|
|
{
|
|
module.name()
|
|
}
|
|
,symbol_name
|
|
{
|
|
std::move(symbol_name)
|
|
}
|
|
{}
|
|
|
|
template<class T>
|
|
ircd::mods::import<T>::operator
|
|
T &()
|
|
{
|
|
return this->operator*();
|
|
}
|
|
|
|
template<class T>
|
|
T &
|
|
ircd::mods::import<T>::operator*()
|
|
{
|
|
return *this->operator->();
|
|
}
|
|
|
|
template<class T>
|
|
T *
|
|
ircd::mods::import<T>::operator->()
|
|
{
|
|
if(unlikely(!*this))
|
|
reload();
|
|
|
|
return sym_ptr::operator-><T>();
|
|
}
|
|
|
|
template<class T>
|
|
ircd::mods::import<T>::operator
|
|
const T &()
|
|
const
|
|
{
|
|
return this->operator*();
|
|
}
|
|
|
|
template<class T>
|
|
const T &
|
|
ircd::mods::import<T>::operator*()
|
|
const
|
|
{
|
|
return this->operator->();
|
|
}
|
|
|
|
template<class T>
|
|
const T *
|
|
ircd::mods::import<T>::operator->()
|
|
const
|
|
{
|
|
return sym_ptr::operator-><T>();
|
|
}
|
|
|
|
template<class T>
|
|
template<class... args>
|
|
auto
|
|
ircd::mods::import<T>::operator()(args&&... a)
|
|
{
|
|
if(unlikely(!*this))
|
|
reload();
|
|
|
|
return sym_ptr::operator()<T>(std::forward<args>(a)...);
|
|
}
|
|
|
|
template<class T>
|
|
template<class... args>
|
|
auto
|
|
ircd::mods::import<T>::operator()(args&&... a)
|
|
const
|
|
{
|
|
return sym_ptr::operator()<T>(std::forward<args>(a)...);
|
|
}
|
|
|
|
template<class T>
|
|
void
|
|
ircd::mods::import<T>::reload()
|
|
try
|
|
{
|
|
auto &module
|
|
{
|
|
imports.at(module_name)
|
|
};
|
|
|
|
auto &sp
|
|
{
|
|
static_cast<sym_ptr &>(*this)
|
|
};
|
|
|
|
sp = { module, symbol_name };
|
|
}
|
|
catch(const std::out_of_range &e)
|
|
{
|
|
throw unavailable
|
|
{
|
|
"Sorry, %s in %s is currently unavailable.",
|
|
symbol_name,
|
|
module_name
|
|
};
|
|
}
|