mirror of
https://github.com/matrix-construct/construct
synced 2024-06-11 06:28:55 +02:00
ircd:Ⓜ️🪝 Support arbitrary creation and deletion of hook::site instances.
This commit is contained in:
parent
003ecf6357
commit
e90603b762
|
@ -46,6 +46,10 @@ struct ircd::m::hook
|
|||
/// and registers itself with the master extern hook::list. Each hook
|
||||
/// then registers itself with a hook::site. The site contains internal
|
||||
/// state to manage the efficient calling of the participating hooks.
|
||||
///
|
||||
/// A hook::site can be created or destroyed at any time (for example if it's
|
||||
/// in a module which is reloaded) while being agnostic to the hooks it
|
||||
/// cooperates with.
|
||||
struct ircd::m::hook::site
|
||||
{
|
||||
json::strung _feature;
|
||||
|
@ -81,8 +85,10 @@ struct ircd::m::hook::site
|
|||
/// class with an extern instance. Each hook::site will register itself here
|
||||
/// by human readable name.
|
||||
struct ircd::m::hook::list
|
||||
:std::map<string_view, hook::site *>
|
||||
{
|
||||
std::map<string_view, hook::site *> sites;
|
||||
std::set<hook *> hooks;
|
||||
|
||||
friend class site;
|
||||
bool add(site &);
|
||||
bool del(site &);
|
||||
|
|
67
ircd/m/m.cc
67
ircd/m/m.cc
|
@ -2484,6 +2484,11 @@ try
|
|||
list.add(*this)
|
||||
}
|
||||
{
|
||||
// Find and register all of the orphan hooks which were constructed before
|
||||
// this site was constructed.
|
||||
for(auto *const &hook : list.hooks)
|
||||
if(hook->site_name() == name())
|
||||
add(*hook);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -2653,45 +2658,59 @@ ircd::m::hook::list
|
|||
|
||||
bool
|
||||
ircd::m::hook::list::del(hook &hook)
|
||||
try
|
||||
{
|
||||
const auto site(at(hook.site_name()));
|
||||
assert(site != nullptr);
|
||||
return site->del(hook);
|
||||
}
|
||||
catch(const std::out_of_range &e)
|
||||
{
|
||||
log::critical
|
||||
const auto erased
|
||||
{
|
||||
"Tried to unregister hook(%p) from missing hook::site '%s'",
|
||||
&hook,
|
||||
hook.site_name()
|
||||
hooks.erase(&hook)
|
||||
};
|
||||
assert(erased);
|
||||
|
||||
const auto it
|
||||
{
|
||||
sites.find(hook.site_name())
|
||||
};
|
||||
|
||||
assert(0);
|
||||
return false;
|
||||
if(it == end(sites))
|
||||
return false;
|
||||
|
||||
auto *const &site(it->second);
|
||||
assert(site != nullptr);
|
||||
return site->del(hook);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::hook::list::add(hook &hook)
|
||||
try
|
||||
{
|
||||
const auto site(at(hook.site_name()));
|
||||
if(!hooks.emplace(&hook).second)
|
||||
log::warning
|
||||
{
|
||||
"Hook %p already registered", &hook
|
||||
};
|
||||
|
||||
const auto it
|
||||
{
|
||||
sites.find(hook.site_name())
|
||||
};
|
||||
|
||||
if(it == end(sites))
|
||||
{
|
||||
log::dwarning
|
||||
{
|
||||
"Hook %p found no site for '%s'", &hook, hook.site_name()
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto *const &site(it->second);
|
||||
assert(site != nullptr);
|
||||
return site->add(hook);
|
||||
}
|
||||
catch(const std::out_of_range &e)
|
||||
{
|
||||
throw error
|
||||
{
|
||||
"No hook::site named '%s' is registered...", hook.site_name()
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::hook::list::del(site &site)
|
||||
{
|
||||
return erase(site.name());
|
||||
return sites.erase(site.name());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2699,7 +2718,7 @@ ircd::m::hook::list::add(site &site)
|
|||
{
|
||||
const auto iit
|
||||
{
|
||||
emplace(site.name(), &site)
|
||||
sites.emplace(site.name(), &site)
|
||||
};
|
||||
|
||||
if(unlikely(!iit.second))
|
||||
|
|
|
@ -577,7 +577,7 @@ console_cmd__conf__get(opt &out, const string_view &line)
|
|||
bool
|
||||
console_cmd__hook__list(opt &out, const string_view &line)
|
||||
{
|
||||
for(const auto &p : m::hook::list)
|
||||
for(const auto &p : m::hook::list.sites)
|
||||
{
|
||||
const auto &site(*p.second);
|
||||
out << std::setw(24) << std::left << p.first
|
||||
|
|
Loading…
Reference in a new issue