0
0
Fork 0
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:
Jason Volk 2018-05-06 14:53:00 -07:00
parent 003ecf6357
commit e90603b762
3 changed files with 51 additions and 26 deletions

View file

@ -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 &);

View file

@ -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))

View file

@ -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