diff --git a/include/ircd/util/unwind.h b/include/ircd/util/unwind.h index c74b936ac..666840143 100644 --- a/include/ircd/util/unwind.h +++ b/include/ircd/util/unwind.h @@ -24,6 +24,7 @@ namespace ircd::util /// struct ircd::util::unwind { + struct defer; struct nominal; struct exceptional; @@ -94,6 +95,22 @@ struct ircd::util::unwind::exceptional exceptional(const exceptional &) = delete; }; +/// Posts function to the event loop at the unwind rather than executing it +/// as with nominal/exceptional. +/// +struct ircd::util::unwind::defer +{ + std::function func; + + template + defer(F&& func) + :func{std::forward(func)} + {} + + defer(const defer &) = delete; + ~defer() noexcept; +}; + /// Asserts that unwind is occurring without any exception. This allows some /// section of code, for example, the latter half of a function, to assert that /// it is not throwing and disrupting the other half. This is useful when no diff --git a/ircd/util.cc b/ircd/util.cc index 88d7168f9..a66207676 100644 --- a/ircd/util.cc +++ b/ircd/util.cc @@ -582,6 +582,20 @@ ircd::util::a2u(const mutable_buffer &out, return { data(out), len }; } +/////////////////////////////////////////////////////////////////////////////// +// +// util/unwind.h +// + +ircd::util::unwind::defer::~defer() +noexcept +{ + ircd::defer + { + std::move(func) + }; +} + /////////////////////////////////////////////////////////////////////////////// // // util/what.h