mirror of
https://github.com/matrix-construct/construct
synced 2024-12-27 07:54:05 +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
|
namespace ircd::mapi
|
||||||
{
|
{
|
||||||
struct header;
|
struct header;
|
||||||
|
struct metablock;
|
||||||
using magic_t = uint16_t;
|
using magic_t = uint16_t;
|
||||||
using version_t = uint16_t;
|
using version_t = uint16_t;
|
||||||
using metadata = std::map<string_view, string_view, std::less<>>;
|
using meta_data = std::map<string_view, string_view, std::less<>>;
|
||||||
using init_function = std::function<void ()>;
|
using init_func = std::function<void ()>;
|
||||||
using fini_function = 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
|
const char *const header_symbol_name
|
||||||
{
|
{
|
||||||
"IRCD_MODULE"
|
"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
|
struct ircd::mapi::header
|
||||||
{
|
{
|
||||||
magic_t magic; // The magic must match MAGIC
|
const magic_t magic {IRCD_MAPI_MAGIC}; // The magic must match
|
||||||
version_t version; // Version indicator
|
const version_t version {IRCD_MAPI_VERSION}; // Version indicator
|
||||||
int64_t timestamp; // Module's compile epoch
|
const int32_t _reserved_ {0}; // MBZ
|
||||||
init_function init; // Executed after dlopen()
|
const int64_t timestamp {RB_DATECODE}; // Module's compile epoch
|
||||||
fini_function fini; // Executed before dlclose()
|
std::unique_ptr<metablock> meta; // Non-standard-layout header data
|
||||||
metadata meta; // Various key-value metadata
|
mods::mod *self {nullptr}; // Point to mod instance once loaded
|
||||||
mods::mod *self; // Module instance once loaded
|
|
||||||
|
|
||||||
// get and set metadata
|
// get and set metadata
|
||||||
auto &operator[](const string_view &s) const;
|
const string_view &operator[](const string_view &s) const;
|
||||||
auto &operator[](const string_view &s);
|
string_view &operator[](const string_view &s);
|
||||||
|
|
||||||
// become self
|
// become self
|
||||||
operator const mods::mod &() const;
|
operator const mods::mod &() const;
|
||||||
operator mods::mod &();
|
operator mods::mod &();
|
||||||
|
|
||||||
header(const string_view &desc = "<no description>",
|
header(const string_view & = "<no description>",
|
||||||
init_function = {},
|
init_func = {},
|
||||||
fini_function = {});
|
fini_func = {});
|
||||||
|
|
||||||
|
header(header &&) = delete;
|
||||||
|
header(const header &) = delete;
|
||||||
~header() noexcept;
|
~header() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
struct ircd::mapi::metablock
|
||||||
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
|
|
||||||
{
|
{
|
||||||
{ "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;
|
static_destruction = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ircd::mapi::header::operator
|
static_assert
|
||||||
mods::mod &()
|
(
|
||||||
{
|
std::is_standard_layout<ircd::mapi::header>(),
|
||||||
assert(self);
|
"The MAPI header must be standard layout so the magic and version numbers"
|
||||||
return *self;
|
" can be parsed from the shared object file by external applications."
|
||||||
}
|
);
|
||||||
|
|
||||||
inline ircd::mapi::header::operator
|
static_assert
|
||||||
const mods::mod &()
|
(
|
||||||
const
|
sizeof(ircd::mapi::header) == 2 + 2 + 4 + 8 + 8 + 8,
|
||||||
{
|
"The MAPI header size has changed on this platform."
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
71
ircd/mods.cc
71
ircd/mods.cc
|
@ -116,19 +116,18 @@ try
|
||||||
"Unexpected null header"
|
"Unexpected null header"
|
||||||
};
|
};
|
||||||
|
|
||||||
if(header->magic != mapi::MAGIC)
|
if(header->magic != IRCD_MAPI_MAGIC)
|
||||||
throw error
|
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.
|
// Tell the module where to find us.
|
||||||
header->self = this;
|
header->self = this;
|
||||||
|
|
||||||
// Set some basic metadata
|
// Set some basic metadata
|
||||||
auto &meta(header->meta);
|
(*this)["name"] = name();
|
||||||
meta["name"] = name();
|
(*this)["location"] = location();
|
||||||
meta["location"] = location();
|
|
||||||
|
|
||||||
if(!loading.empty())
|
if(!loading.empty())
|
||||||
{
|
{
|
||||||
|
@ -214,8 +213,10 @@ ircd::mods::mod::unload()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call the user's unloading function here.
|
// Call the user's unloading function here.
|
||||||
if(header->fini)
|
assert(header);
|
||||||
header->fini();
|
assert(header->meta);
|
||||||
|
if(header->meta->fini)
|
||||||
|
header->meta->fini();
|
||||||
|
|
||||||
// Save the children! dlclose() does not like to be called recursively during static
|
// 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
|
// 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;
|
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)
|
// mods/mods.h (misc util)
|
||||||
|
@ -594,8 +645,10 @@ try
|
||||||
// Call the user-supplied init function well after fully loading and
|
// Call the user-supplied init function well after fully loading and
|
||||||
// construction of the module. This way the init function sees the module
|
// construction of the module. This way the init function sees the module
|
||||||
// as loaded and can make shared_ptr references, etc.
|
// as loaded and can make shared_ptr references, etc.
|
||||||
if(ret->header->init)
|
assert(ret->header);
|
||||||
ret->header->init();
|
assert(ret->header->meta);
|
||||||
|
if(ret->header->meta->init)
|
||||||
|
ret->header->meta->init();
|
||||||
|
|
||||||
log::info
|
log::info
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,9 +54,10 @@ struct ircd::mods::mod
|
||||||
mapi::header *header;
|
mapi::header *header;
|
||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
auto &operator[](const std::string &s) const { return header->meta.operator[](s); }
|
const string_view &operator[](const string_view &s) const;
|
||||||
auto &operator[](const std::string &s) { return header->meta.operator[](s); }
|
string_view &operator[](const string_view &s);
|
||||||
|
|
||||||
|
// Convenience accessors
|
||||||
auto &name() const { return _name; }
|
auto &name() const { return _name; }
|
||||||
auto &location() const { return _location; }
|
auto &location() const { return _location; }
|
||||||
auto &version() const { return header->version; }
|
auto &version() const { return header->version; }
|
||||||
|
|
Loading…
Reference in a new issue