0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-25 08:12:37 +01:00

ircd::util: Elide std::function overhead for util::unwind suite.

This commit is contained in:
Jason Volk 2019-12-03 13:05:32 -08:00
parent 21ad249f74
commit df79d61395
13 changed files with 53 additions and 54 deletions

View file

@ -52,7 +52,7 @@ ircd::ctx::dock::wait_for(const duration &dur)
static const duration zero(0); static const duration zero(0);
assert(current); assert(current);
const unwind::exceptional renotify{[this] const unwind_exceptional renotify{[this]
{ {
notify_one(); notify_one();
}}; }};
@ -78,7 +78,7 @@ ircd::ctx::dock::wait_for(const duration &dur,
return true; return true;
assert(current); assert(current);
const unwind::exceptional renotify{[this] const unwind_exceptional renotify{[this]
{ {
notify_one(); notify_one();
}}; }};
@ -110,7 +110,7 @@ bool
ircd::ctx::dock::wait_until(time_point&& tp) ircd::ctx::dock::wait_until(time_point&& tp)
{ {
assert(current); assert(current);
const unwind::exceptional renotify{[this] const unwind_exceptional renotify{[this]
{ {
notify_one(); notify_one();
}}; }};
@ -134,7 +134,7 @@ ircd::ctx::dock::wait_until(time_point&& tp,
return true; return true;
assert(current); assert(current);
const unwind::exceptional renotify{[this] const unwind_exceptional renotify{[this]
{ {
notify_one(); notify_one();
}}; }};

View file

@ -11,11 +11,18 @@
#pragma once #pragma once
#define HAVE_IRCD_UTIL_UNWIND_H #define HAVE_IRCD_UTIL_UNWIND_H
namespace ircd { namespace ircd
{
inline namespace util inline namespace util
{ {
struct unwind; template<class F> struct unwind;
}} template<class F> struct unwind_nominal;
template<class F> struct unwind_exceptional;
struct unwind_defer;
struct unwind_nominal_assertion;
struct unwind_exceptional_assertion;
}
}
// //
// Fundamental scope-unwind utilities establishing actions during destruction // Fundamental scope-unwind utilities establishing actions during destruction
@ -23,15 +30,11 @@ inline namespace util
/// Unconditionally executes the provided code when the object goes out of scope. /// Unconditionally executes the provided code when the object goes out of scope.
/// ///
template<class F = void (*)()>
struct ircd::util::unwind struct ircd::util::unwind
{ {
struct defer; F func;
struct nominal;
struct exceptional;
const std::function<void ()> func;
template<class F>
unwind(F&& func) unwind(F&& func)
:func{std::forward<F>(func)} :func{std::forward<F>(func)}
{} {}
@ -49,24 +52,22 @@ struct ircd::util::unwind
/// The function is expected to be executed and the likely() should pipeline /// The function is expected to be executed and the likely() should pipeline
/// that branch and make this device cheaper to use under normal circumstances. /// that branch and make this device cheaper to use under normal circumstances.
/// ///
struct ircd::util::unwind::nominal template<class F = void (*)()>
struct ircd::util::unwind_nominal
{ {
struct assertion; F func;
const std::function<void ()> func; unwind_nominal(F&& func)
template<class F>
nominal(F&& func)
:func{std::forward<F>(func)} :func{std::forward<F>(func)}
{} {}
~nominal() noexcept __attribute__((always_inline)) ~unwind_nominal() noexcept __attribute__((always_inline))
{ {
if(likely(!std::uncaught_exceptions())) if(likely(!std::uncaught_exceptions()))
func(); func();
} }
nominal(const nominal &) = delete; unwind_nominal(const unwind_nominal &) = delete;
}; };
/// Executes function only if unwind is taking place because exception thrown /// Executes function only if unwind is taking place because exception thrown
@ -76,40 +77,38 @@ struct ircd::util::unwind::nominal
/// optimize the pipeline for the nominal path, making this device as cheap /// optimize the pipeline for the nominal path, making this device as cheap
/// as possible to use. /// as possible to use.
/// ///
struct ircd::util::unwind::exceptional template<class F = void (*)()>
struct ircd::util::unwind_exceptional
{ {
struct assertion; F func;
const std::function<void ()> func; unwind_exceptional(F&& func)
template<class F>
exceptional(F&& func)
:func{std::forward<F>(func)} :func{std::forward<F>(func)}
{} {}
~exceptional() noexcept __attribute__((always_inline)) ~unwind_exceptional() noexcept __attribute__((always_inline))
{ {
if(unlikely(std::uncaught_exceptions())) if(unlikely(std::uncaught_exceptions()))
func(); func();
} }
exceptional(const exceptional &) = delete; unwind_exceptional(const unwind_exceptional &) = delete;
}; };
/// Posts function to the event loop at the unwind rather than executing it /// Posts function to the event loop at the unwind rather than executing it
/// as with nominal/exceptional. /// as with nominal/exceptional.
/// ///
struct ircd::util::unwind::defer struct ircd::util::unwind_defer
{ {
std::function<void ()> func; std::function<void ()> func;
template<class F> template<class F>
defer(F&& func) unwind_defer(F&& func)
:func{std::forward<F>(func)} :func{std::forward<F>(func)}
{} {}
defer(const defer &) = delete; unwind_defer(const unwind_defer &) = delete;
~defer() noexcept; ~unwind_defer() noexcept;
}; };
/// Asserts that unwind is occurring without any exception. This allows some /// Asserts that unwind is occurring without any exception. This allows some
@ -118,9 +117,9 @@ struct ircd::util::unwind::defer
/// exception is expected thus placing other guarantees should not be required /// exception is expected thus placing other guarantees should not be required
/// if this guarantee is met. /// if this guarantee is met.
/// ///
struct ircd::util::unwind::nominal::assertion struct ircd::util::unwind_nominal_assertion
{ {
~assertion() noexcept ~unwind_nominal_assertion() noexcept
{ {
assert(likely(!std::uncaught_exceptions())); assert(likely(!std::uncaught_exceptions()));
} }
@ -129,9 +128,9 @@ struct ircd::util::unwind::nominal::assertion
/// Complements exceptional::assertion. This triggers an assertion when /// Complements exceptional::assertion. This triggers an assertion when
/// unwinding WITHOUT an exception. /// unwinding WITHOUT an exception.
/// ///
struct ircd::util::unwind::exceptional::assertion struct ircd::util::unwind_exceptional_assertion
{ {
~assertion() noexcept ~unwind_exceptional_assertion() noexcept
{ {
assert(likely(std::uncaught_exceptions())); assert(likely(std::uncaught_exceptions()));
} }

View file

@ -1264,7 +1264,7 @@ ircd::ctx::context::context(const string_view &name,
// we expect the context to be committed to entry. If the POST flag is // we expect the context to be committed to entry. If the POST flag is
// supplied and it gets lost in the asio queue it will not be entered, and // supplied and it gets lost in the asio queue it will not be entered, and
// will not be able to free itself; that will leak. // will not be able to free itself; that will leak.
const unwind::nominal release{[this] const unwind_nominal release{[this]
{ {
assert(c); assert(c);
if(c->flags & context::DETACH) if(c->flags & context::DETACH)
@ -2729,7 +2729,7 @@ void
ircd::ctx::dock::wait() ircd::ctx::dock::wait()
{ {
assert(current); assert(current);
const unwind::exceptional renotify{[this] const unwind_exceptional renotify{[this]
{ {
notify_one(); notify_one();
}}; }};
@ -2750,7 +2750,7 @@ ircd::ctx::dock::wait(const predicate &pred)
return; return;
assert(current); assert(current);
const unwind::exceptional renotify{[this] const unwind_exceptional renotify{[this]
{ {
notify_one(); notify_one();
}}; }};

View file

@ -270,7 +270,7 @@ noexcept try
// When this function completes without exception, subsystems are done shutting down and IRCd // When this function completes without exception, subsystems are done shutting down and IRCd
// transitions to HALT. // transitions to HALT.
const unwind::defer halted{[] const unwind_defer halted{[]
{ {
run::set(run::level::HALT); run::set(run::level::HALT);
}}; }};

View file

@ -3153,7 +3153,7 @@ try
assert(!fini); assert(!fini);
set_timeout(opts.timeout); set_timeout(opts.timeout);
const unwind::exceptional unset{[this] const unwind_exceptional unset{[this]
{ {
cancel_timeout(); cancel_timeout();
}}; }};

View file

@ -529,7 +529,7 @@ try
client.request.param, tokens(pathparm, '/', client.request.param) client.request.param, tokens(pathparm, '/', client.request.param)
}; };
const unwind::nominal completions{[this] const unwind_nominal completions{[this]
{ {
++stats->completions; ++stats->completions;
}}; }};

View file

@ -1174,7 +1174,7 @@ try
if(op_fini) if(op_fini)
return; return;
const unwind::exceptional failure{[this] const unwind_exceptional failure{[this]
{ {
op_resolve = false; op_resolve = false;
err_set(std::current_exception()); err_set(std::current_exception());
@ -1850,7 +1850,7 @@ ircd::server::link::open(const net::open_opts &open_opts)
op_init = true; op_init = true;
op_open = true; op_open = true;
const unwind::exceptional unhandled{[this] const unwind_exceptional unhandled{[this]
{ {
op_init = false; op_init = false;
op_open = false; op_open = false;
@ -1938,7 +1938,7 @@ ircd::server::link::wait_writable()
assert(ready()); assert(ready());
op_write = true; op_write = true;
const unwind::exceptional unhandled{[this] const unwind_exceptional unhandled{[this]
{ {
op_write = false; op_write = false;
}}; }};
@ -2119,7 +2119,7 @@ ircd::server::link::wait_readable()
assert(ready()); assert(ready());
op_read = true; op_read = true;
const unwind::exceptional unhandled{[this] const unwind_exceptional unhandled{[this]
{ {
op_read = false; op_read = false;
}}; }};

View file

@ -509,7 +509,7 @@ ircd::util::a2u(const mutable_buffer &out,
// util/unwind.h // util/unwind.h
// //
ircd::util::unwind::defer::~defer() ircd::util::unwind_defer::~unwind_defer()
noexcept noexcept
{ {
ircd::defer ircd::defer

View file

@ -247,7 +247,7 @@ catch(const m::error &e)
/* /*
ircd::m::init::modules::modules() ircd::m::init::modules::modules()
{ {
const unwind::exceptional unload{[this] const unwind_exceptional unload{[this]
{ {
this->fini_imports(); this->fini_imports();
}}; }};

View file

@ -161,7 +161,7 @@ put__invite(client &client,
// We don't want this eval throwing an exception because the response has // We don't want this eval throwing an exception because the response has
// already been made for this request. // already been made for this request.
const unwind::nominal::assertion na; const unwind_nominal_assertion na;
vmopts.nothrows = -1; vmopts.nothrows = -1;
m::vm::eval m::vm::eval

View file

@ -345,7 +345,7 @@ try
}; };
txns.emplace_back(*this, std::move(content), std::move(opts)); txns.emplace_back(*this, std::move(content), std::move(opts));
const unwind::nominal::assertion na; const unwind_nominal_assertion na;
curtxn = &txns.back(); curtxn = &txns.back();
q.clear(); q.clear();
log::debug log::debug

View file

@ -307,7 +307,7 @@ try
}; };
create(room, user_id, "file"); create(room, user_id, "file");
const unwind::exceptional purge{[&room] const unwind_exceptional purge{[&room]
{ {
m::room::purge(room); m::room::purge(room);
}}; }};

View file

@ -234,7 +234,7 @@ try
file_size file_size
}; };
const unwind::exceptional terminate{[&client] const unwind_exceptional terminate{[&client]
{ {
client.close(net::dc::RST, net::close_ignore); client.close(net::dc::RST, net::close_ignore);
}}; }};