mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd::mods: Improve MAPI header layout; various cleanup.
This commit is contained in:
parent
30d938530a
commit
d19edbda98
3 changed files with 131 additions and 73 deletions
|
@ -15,66 +15,85 @@
|
|||
namespace ircd::mapi
|
||||
{
|
||||
struct header;
|
||||
struct metablock;
|
||||
using magic_t = uint16_t;
|
||||
using version_t = uint16_t;
|
||||
using metadata = std::map<string_view, string_view, std::less<>>;
|
||||
using init_function = std::function<void ()>;
|
||||
using fini_function = std::function<void ()>;
|
||||
using meta_data = std::map<string_view, string_view, std::less<>>;
|
||||
using init_func = std::function<void ()>;
|
||||
using fini_func = std::function<void ()>;
|
||||
|
||||
/// Used to communicate whether a module unload actually took place. dlclose() is allowed to return
|
||||
/// success but the actual static destruction of the module's contents doesn't lie. (mods.cc)
|
||||
extern bool static_destruction;
|
||||
|
||||
/// The name of the header variable in the module must match this string
|
||||
const char *const header_symbol_name
|
||||
{
|
||||
"IRCD_MODULE"
|
||||
};
|
||||
|
||||
constexpr const magic_t MAGIC
|
||||
{
|
||||
0x4D41
|
||||
};
|
||||
|
||||
// Used to communicate whether a module unload actually took place. dlclose() is allowed to return
|
||||
// success but the actual static destruction of the module's contents doesn't lie. (mods.cc)
|
||||
extern bool static_destruction;
|
||||
}
|
||||
|
||||
/// The magic number at the front of the header
|
||||
constexpr const ircd::mapi::magic_t
|
||||
IRCD_MAPI_MAGIC
|
||||
{
|
||||
0x4D41
|
||||
};
|
||||
|
||||
/// The version number of this module's header.
|
||||
constexpr const ircd::mapi::version_t
|
||||
IRCD_MAPI_VERSION
|
||||
{
|
||||
4
|
||||
};
|
||||
|
||||
struct ircd::mapi::header
|
||||
{
|
||||
magic_t magic; // The magic must match MAGIC
|
||||
version_t version; // Version indicator
|
||||
int64_t timestamp; // Module's compile epoch
|
||||
init_function init; // Executed after dlopen()
|
||||
fini_function fini; // Executed before dlclose()
|
||||
metadata meta; // Various key-value metadata
|
||||
mods::mod *self; // Module instance once loaded
|
||||
const magic_t magic {IRCD_MAPI_MAGIC}; // The magic must match
|
||||
const version_t version {IRCD_MAPI_VERSION}; // Version indicator
|
||||
const int32_t _reserved_ {0}; // MBZ
|
||||
const int64_t timestamp {RB_DATECODE}; // Module's compile epoch
|
||||
std::unique_ptr<metablock> meta; // Non-standard-layout header data
|
||||
mods::mod *self {nullptr}; // Point to mod instance once loaded
|
||||
|
||||
// get and set metadata
|
||||
auto &operator[](const string_view &s) const;
|
||||
auto &operator[](const string_view &s);
|
||||
const string_view &operator[](const string_view &s) const;
|
||||
string_view &operator[](const string_view &s);
|
||||
|
||||
// become self
|
||||
operator const mods::mod &() const;
|
||||
operator mods::mod &();
|
||||
|
||||
header(const string_view &desc = "<no description>",
|
||||
init_function = {},
|
||||
fini_function = {});
|
||||
header(const string_view & = "<no description>",
|
||||
init_func = {},
|
||||
fini_func = {});
|
||||
|
||||
header(header &&) = delete;
|
||||
header(const header &) = delete;
|
||||
~header() noexcept;
|
||||
};
|
||||
|
||||
inline
|
||||
ircd::mapi::header::header(const string_view &desc,
|
||||
init_function init,
|
||||
fini_function fini)
|
||||
:magic(MAGIC)
|
||||
,version(4)
|
||||
,timestamp(RB_DATECODE)
|
||||
,init{std::move(init)}
|
||||
,fini{std::move(fini)}
|
||||
,meta
|
||||
struct ircd::mapi::metablock
|
||||
{
|
||||
{ "description", desc }
|
||||
init_func init; // Executed after dlopen()
|
||||
fini_func fini; // Executed before dlclose()
|
||||
meta_data meta; // Various key-value metadata
|
||||
};
|
||||
|
||||
inline
|
||||
ircd::mapi::header::header(const string_view &description,
|
||||
init_func init,
|
||||
fini_func fini)
|
||||
:meta
|
||||
{
|
||||
new metablock
|
||||
{
|
||||
std::move(init), std::move(fini), meta_data
|
||||
{
|
||||
{ "description", description }
|
||||
}
|
||||
}
|
||||
}
|
||||
,self{nullptr}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -85,30 +104,15 @@ noexcept
|
|||
static_destruction = true;
|
||||
}
|
||||
|
||||
inline ircd::mapi::header::operator
|
||||
mods::mod &()
|
||||
{
|
||||
assert(self);
|
||||
return *self;
|
||||
}
|
||||
static_assert
|
||||
(
|
||||
std::is_standard_layout<ircd::mapi::header>(),
|
||||
"The MAPI header must be standard layout so the magic and version numbers"
|
||||
" can be parsed from the shared object file by external applications."
|
||||
);
|
||||
|
||||
inline ircd::mapi::header::operator
|
||||
const mods::mod &()
|
||||
const
|
||||
{
|
||||
assert(self);
|
||||
return *self;
|
||||
}
|
||||
|
||||
inline auto &
|
||||
ircd::mapi::header::operator[](const string_view &key)
|
||||
{
|
||||
return meta[key];
|
||||
}
|
||||
|
||||
inline auto &
|
||||
ircd::mapi::header::operator[](const string_view &key)
|
||||
const
|
||||
{
|
||||
return meta.at(key);
|
||||
}
|
||||
static_assert
|
||||
(
|
||||
sizeof(ircd::mapi::header) == 2 + 2 + 4 + 8 + 8 + 8,
|
||||
"The MAPI header size has changed on this platform."
|
||||
);
|
||||
|
|
71
ircd/mods.cc
71
ircd/mods.cc
|
@ -116,19 +116,18 @@ try
|
|||
"Unexpected null header"
|
||||
};
|
||||
|
||||
if(header->magic != mapi::MAGIC)
|
||||
if(header->magic != IRCD_MAPI_MAGIC)
|
||||
throw error
|
||||
{
|
||||
"Bad magic [%04x] need: [%04x]", header->magic, mapi::MAGIC
|
||||
"Bad magic [%04x] need: [%04x]", header->magic, IRCD_MAPI_MAGIC
|
||||
};
|
||||
|
||||
// Tell the module where to find us.
|
||||
header->self = this;
|
||||
|
||||
// Set some basic metadata
|
||||
auto &meta(header->meta);
|
||||
meta["name"] = name();
|
||||
meta["location"] = location();
|
||||
(*this)["name"] = name();
|
||||
(*this)["location"] = location();
|
||||
|
||||
if(!loading.empty())
|
||||
{
|
||||
|
@ -214,8 +213,10 @@ ircd::mods::mod::unload()
|
|||
};
|
||||
|
||||
// Call the user's unloading function here.
|
||||
if(header->fini)
|
||||
header->fini();
|
||||
assert(header);
|
||||
assert(header->meta);
|
||||
if(header->meta->fini)
|
||||
header->meta->fini();
|
||||
|
||||
// Save the children! dlclose() does not like to be called recursively during static
|
||||
// destruction of a module. The mod ctor recorded all of the modules loaded while this
|
||||
|
@ -256,6 +257,56 @@ ircd::mods::mod::unload()
|
|||
return true;
|
||||
}
|
||||
|
||||
ircd::string_view &
|
||||
ircd::mods::mod::operator[](const string_view &key)
|
||||
{
|
||||
assert(header);
|
||||
return header->operator[](key);
|
||||
}
|
||||
|
||||
const ircd::string_view &
|
||||
ircd::mods::mod::operator[](const string_view &key)
|
||||
const
|
||||
{
|
||||
assert(header);
|
||||
return header->operator[](key);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// mods/mapi.h
|
||||
//
|
||||
|
||||
ircd::mapi::header::operator
|
||||
mods::mod &()
|
||||
{
|
||||
assert(self);
|
||||
return *self;
|
||||
}
|
||||
|
||||
ircd::mapi::header::operator
|
||||
const mods::mod &()
|
||||
const
|
||||
{
|
||||
assert(self);
|
||||
return *self;
|
||||
}
|
||||
|
||||
ircd::string_view &
|
||||
ircd::mapi::header::operator[](const string_view &key)
|
||||
{
|
||||
assert(meta);
|
||||
return meta->meta[key];
|
||||
}
|
||||
|
||||
const ircd::string_view &
|
||||
ircd::mapi::header::operator[](const string_view &key)
|
||||
const
|
||||
{
|
||||
assert(meta);
|
||||
return meta->meta.at(key);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// mods/mods.h (misc util)
|
||||
|
@ -594,8 +645,10 @@ try
|
|||
// Call the user-supplied init function well after fully loading and
|
||||
// construction of the module. This way the init function sees the module
|
||||
// as loaded and can make shared_ptr references, etc.
|
||||
if(ret->header->init)
|
||||
ret->header->init();
|
||||
assert(ret->header);
|
||||
assert(ret->header->meta);
|
||||
if(ret->header->meta->init)
|
||||
ret->header->meta->init();
|
||||
|
||||
log::info
|
||||
{
|
||||
|
|
|
@ -54,9 +54,10 @@ struct ircd::mods::mod
|
|||
mapi::header *header;
|
||||
|
||||
// Metadata
|
||||
auto &operator[](const std::string &s) const { return header->meta.operator[](s); }
|
||||
auto &operator[](const std::string &s) { return header->meta.operator[](s); }
|
||||
const string_view &operator[](const string_view &s) const;
|
||||
string_view &operator[](const string_view &s);
|
||||
|
||||
// Convenience accessors
|
||||
auto &name() const { return _name; }
|
||||
auto &location() const { return _location; }
|
||||
auto &version() const { return header->version; }
|
||||
|
|
Loading…
Reference in a new issue