mirror of
https://github.com/matrix-construct/construct
synced 2024-12-28 00:14:07 +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;
|
struct continuation;
|
||||||
|
|
||||||
using yield_context = boost::asio::yield_context;
|
using yield_context = boost::asio::yield_context;
|
||||||
using yield_closure = std::function<void (yield_context &)>;
|
|
||||||
using interruptor = std::function<void (ctx *const &)>;
|
using interruptor = std::function<void (ctx *const &)>;
|
||||||
using predicate = std::function<bool ()>;
|
using predicate = std::function<bool ()>;
|
||||||
}
|
}
|
||||||
|
@ -54,21 +53,75 @@ struct ircd::ctx::continuation
|
||||||
static const predicate false_predicate;
|
static const predicate false_predicate;
|
||||||
static const interruptor noop_interruptor;
|
static const interruptor noop_interruptor;
|
||||||
|
|
||||||
ctx *const self;
|
|
||||||
const predicate *const pred;
|
|
||||||
const interruptor *const intr;
|
|
||||||
const void *const frame_address;
|
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 const boost::asio::yield_context &() const noexcept;
|
||||||
operator boost::asio::yield_context &() noexcept;
|
operator boost::asio::yield_context &() noexcept;
|
||||||
|
|
||||||
|
void enter();
|
||||||
|
void leave() noexcept;
|
||||||
|
|
||||||
|
template<class yield_closure>
|
||||||
continuation(const predicate &,
|
continuation(const predicate &,
|
||||||
const interruptor &,
|
const interruptor &,
|
||||||
const yield_closure &);
|
yield_closure&&);
|
||||||
|
|
||||||
continuation(continuation &&) = delete;
|
continuation(continuation &&) = delete;
|
||||||
continuation(const continuation &) = delete;
|
continuation(const continuation &) = delete;
|
||||||
continuation &operator=(continuation &&) = delete;
|
continuation &operator=(continuation &&) = delete;
|
||||||
continuation &operator=(const 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);
|
||||||
|
}
|
||||||
|
|
55
ircd/ctx.cc
55
ircd/ctx.cc
|
@ -181,7 +181,7 @@ ircd::ctx::ctx::jump()
|
||||||
continuation
|
continuation
|
||||||
{
|
{
|
||||||
continuation::false_predicate, continuation::noop_interruptor, [&target]
|
continuation::false_predicate, continuation::noop_interruptor, [&target]
|
||||||
(auto &yield)
|
(auto &yield) noexcept
|
||||||
{
|
{
|
||||||
target();
|
target();
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,7 @@ ircd::ctx::ctx::wait()
|
||||||
boost::system::error_code ec; continuation
|
boost::system::error_code ec; continuation
|
||||||
{
|
{
|
||||||
predicate, interruptor, [this, &ec]
|
predicate, interruptor, [this, &ec]
|
||||||
(auto &yield)
|
(auto &yield) noexcept
|
||||||
{
|
{
|
||||||
alarm.async_wait(yield[ec]);
|
alarm.async_wait(yield[ec]);
|
||||||
}
|
}
|
||||||
|
@ -1080,34 +1080,10 @@ ircd::ctx::continuation::noop_interruptor{[]
|
||||||
return;
|
return;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//
|
|
||||||
// continuation
|
|
||||||
//
|
|
||||||
|
|
||||||
[[gnu::hot]]
|
[[gnu::hot]]
|
||||||
ircd::ctx::continuation::continuation(const predicate &pred,
|
void
|
||||||
const interruptor &intr,
|
ircd::ctx::continuation::leave()
|
||||||
const yield_closure &closure)
|
noexcept
|
||||||
:self
|
|
||||||
{
|
|
||||||
ircd::ctx::current
|
|
||||||
}
|
|
||||||
,pred
|
|
||||||
{
|
|
||||||
&pred
|
|
||||||
}
|
|
||||||
,intr
|
|
||||||
{
|
|
||||||
&intr
|
|
||||||
}
|
|
||||||
,frame_address
|
|
||||||
{
|
|
||||||
__builtin_frame_address(0)
|
|
||||||
}
|
|
||||||
,uncaught_exceptions
|
|
||||||
{
|
|
||||||
exception_handler::uncaught_exceptions(0)
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
assert(self != nullptr);
|
assert(self != nullptr);
|
||||||
assert(self->notes <= 1);
|
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
|
// restore this register; otherwise it remains null for executions on
|
||||||
// the program's main stack.
|
// the program's main stack.
|
||||||
ircd::ctx::current = nullptr;
|
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.
|
// Restore the current context register.
|
||||||
ircd::ctx::current = self;
|
ircd::ctx::current = self;
|
||||||
|
|
||||||
|
@ -1185,13 +1154,8 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
||||||
self->interruption_point();
|
self->interruption_point();
|
||||||
__builtin_unreachable();
|
__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
|
ircd::ctx::continuation::operator
|
||||||
boost::asio::yield_context &()
|
boost::asio::yield_context &()
|
||||||
noexcept
|
noexcept
|
||||||
|
@ -1201,7 +1165,6 @@ noexcept
|
||||||
return *self->yc;
|
return *self->yc;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[gnu::hot]]
|
|
||||||
ircd::ctx::continuation::operator
|
ircd::ctx::continuation::operator
|
||||||
const boost::asio::yield_context &()
|
const boost::asio::yield_context &()
|
||||||
const noexcept
|
const noexcept
|
||||||
|
|
Loading…
Reference in a new issue