mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd::ctx: Partial inline continuation.
This commit is contained in:
parent
9bb4936625
commit
7afb295c09
2 changed files with 69 additions and 53 deletions
|
@ -21,7 +21,6 @@ namespace ircd::ctx
|
|||
struct continuation;
|
||||
|
||||
using yield_context = boost::asio::yield_context;
|
||||
using yield_closure = std::function<void (yield_context &)>;
|
||||
using interruptor = std::function<void (ctx *const &)>;
|
||||
using predicate = std::function<bool ()>;
|
||||
}
|
||||
|
@ -54,21 +53,75 @@ struct ircd::ctx::continuation
|
|||
static const predicate false_predicate;
|
||||
static const interruptor noop_interruptor;
|
||||
|
||||
ctx *const self;
|
||||
const predicate *const pred;
|
||||
const interruptor *const intr;
|
||||
const void *const frame_address;
|
||||
const uint uncaught_exceptions;
|
||||
const void *const return_address;
|
||||
const interruptor *const intr;
|
||||
const predicate *const pred;
|
||||
const size_t uncaught_exceptions;
|
||||
ctx *const self;
|
||||
|
||||
operator const boost::asio::yield_context &() const noexcept;
|
||||
operator boost::asio::yield_context &() noexcept;
|
||||
|
||||
void enter();
|
||||
void leave() noexcept;
|
||||
|
||||
template<class yield_closure>
|
||||
continuation(const predicate &,
|
||||
const interruptor &,
|
||||
const yield_closure &);
|
||||
yield_closure&&);
|
||||
|
||||
continuation(continuation &&) = delete;
|
||||
continuation(const continuation &) = delete;
|
||||
continuation &operator=(continuation &&) = delete;
|
||||
continuation &operator=(const continuation &) = delete;
|
||||
};
|
||||
|
||||
template<class yield_closure>
|
||||
inline
|
||||
__attribute__((always_inline))
|
||||
ircd::ctx::continuation::continuation(const predicate &pred,
|
||||
const interruptor &intr,
|
||||
yield_closure&& closure)
|
||||
:frame_address
|
||||
{
|
||||
__builtin_frame_address(0)
|
||||
}
|
||||
,return_address
|
||||
{
|
||||
__builtin_return_address(0)
|
||||
}
|
||||
,intr
|
||||
{
|
||||
&intr
|
||||
}
|
||||
,pred
|
||||
{
|
||||
&pred
|
||||
}
|
||||
,uncaught_exceptions
|
||||
{
|
||||
exception_handler::uncaught_exceptions(0)
|
||||
}
|
||||
,self
|
||||
{
|
||||
ircd::ctx::current
|
||||
}
|
||||
{
|
||||
// Run the provided routine which performs the actual context switch.
|
||||
// Everything happening in this closure is no longer considered part
|
||||
// of this context, but it is technically operating on this stack.
|
||||
leave();
|
||||
std::exception_ptr eptr; try
|
||||
{
|
||||
closure(static_cast<yield_context &>(*this));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
eptr = std::current_exception();
|
||||
}
|
||||
|
||||
enter();
|
||||
if(unlikely(eptr))
|
||||
std::rethrow_exception(eptr);
|
||||
}
|
||||
|
|
57
ircd/ctx.cc
57
ircd/ctx.cc
|
@ -181,7 +181,7 @@ ircd::ctx::ctx::jump()
|
|||
continuation
|
||||
{
|
||||
continuation::false_predicate, continuation::noop_interruptor, [&target]
|
||||
(auto &yield)
|
||||
(auto &yield) noexcept
|
||||
{
|
||||
target();
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ ircd::ctx::ctx::wait()
|
|||
boost::system::error_code ec; continuation
|
||||
{
|
||||
predicate, interruptor, [this, &ec]
|
||||
(auto &yield)
|
||||
(auto &yield) noexcept
|
||||
{
|
||||
alarm.async_wait(yield[ec]);
|
||||
}
|
||||
|
@ -1080,34 +1080,10 @@ ircd::ctx::continuation::noop_interruptor{[]
|
|||
return;
|
||||
}};
|
||||
|
||||
//
|
||||
// continuation
|
||||
//
|
||||
|
||||
[[gnu::hot]]
|
||||
ircd::ctx::continuation::continuation(const predicate &pred,
|
||||
const interruptor &intr,
|
||||
const yield_closure &closure)
|
||||
:self
|
||||
{
|
||||
ircd::ctx::current
|
||||
}
|
||||
,pred
|
||||
{
|
||||
&pred
|
||||
}
|
||||
,intr
|
||||
{
|
||||
&intr
|
||||
}
|
||||
,frame_address
|
||||
{
|
||||
__builtin_frame_address(0)
|
||||
}
|
||||
,uncaught_exceptions
|
||||
{
|
||||
exception_handler::uncaught_exceptions(0)
|
||||
}
|
||||
void
|
||||
ircd::ctx::continuation::leave()
|
||||
noexcept
|
||||
{
|
||||
assert(self != nullptr);
|
||||
assert(self->notes <= 1);
|
||||
|
@ -1150,19 +1126,12 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
|||
// restore this register; otherwise it remains null for executions on
|
||||
// the program's main stack.
|
||||
ircd::ctx::current = nullptr;
|
||||
}
|
||||
|
||||
// Run the provided routine which performs the actual context switch.
|
||||
// Everything happening in this closure is no longer considered part
|
||||
// of this context, but it is technically operating on this stack.
|
||||
std::exception_ptr eptr; try
|
||||
{
|
||||
closure(*self->yc);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
eptr = std::current_exception();
|
||||
}
|
||||
|
||||
[[gnu::hot]]
|
||||
void
|
||||
ircd::ctx::continuation::enter()
|
||||
{
|
||||
// Restore the current context register.
|
||||
ircd::ctx::current = self;
|
||||
|
||||
|
@ -1185,13 +1154,8 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
|||
self->interruption_point();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
// Check if the operation failed; it's now safe to throw that.
|
||||
if(unlikely(eptr))
|
||||
std::rethrow_exception(eptr);
|
||||
}
|
||||
|
||||
[[gnu::hot]]
|
||||
ircd::ctx::continuation::operator
|
||||
boost::asio::yield_context &()
|
||||
noexcept
|
||||
|
@ -1201,7 +1165,6 @@ noexcept
|
|||
return *self->yc;
|
||||
}
|
||||
|
||||
[[gnu::hot]]
|
||||
ircd::ctx::continuation::operator
|
||||
const boost::asio::yield_context &()
|
||||
const noexcept
|
||||
|
|
Loading…
Reference in a new issue