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:
parent
21ad249f74
commit
df79d61395
13 changed files with 53 additions and 54 deletions
|
@ -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();
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -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);
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -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();
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -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;
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -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;
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -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);
|
||||||
}};
|
}};
|
||||||
|
|
Loading…
Reference in a new issue