mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 07:23:53 +01:00
ircd::ctx: Reorg continuation for core wakeup conditions.
This commit is contained in:
parent
9eabd745f5
commit
4a2ad1c186
2 changed files with 81 additions and 32 deletions
|
@ -18,10 +18,12 @@
|
|||
|
||||
namespace ircd::ctx
|
||||
{
|
||||
using yield_context = boost::asio::yield_context;
|
||||
|
||||
struct continuation;
|
||||
struct to_asio;
|
||||
|
||||
using yield_context = boost::asio::yield_context;
|
||||
using interruptor = std::function<void (ctx *const &) noexcept>;
|
||||
using predicate = std::function<bool ()>;
|
||||
}
|
||||
|
||||
namespace ircd
|
||||
|
@ -43,17 +45,37 @@ namespace ircd
|
|||
/// executes before control continues beyond the yield_context call itself and
|
||||
/// ties this sequence together neatly.
|
||||
///
|
||||
/// The instance contains references to some callables which must remain valid.
|
||||
///
|
||||
/// - predicate (NOT YET USED)
|
||||
/// A wakeup condition. This should be a simple boolean function which
|
||||
/// tests whether the context should be woken up. The continuation references
|
||||
/// this to convey the condition to a scheduler which may test many predicates
|
||||
/// while contexts are asleep and then determine a schedule. This is an
|
||||
/// alternative to waking up contexts first to test their predicates.
|
||||
///
|
||||
/// - interruptor
|
||||
/// An interruption action. This is called when a context cannot wakeup on its
|
||||
/// own after receiving an interruption without help from this action. Common
|
||||
/// use for this is with yields to asio.
|
||||
///
|
||||
struct ircd::ctx::continuation
|
||||
{
|
||||
static const predicate true_predicate;
|
||||
static const predicate false_predicate;
|
||||
static const interruptor noop_interruptor;
|
||||
|
||||
ctx *self;
|
||||
const predicate &pred;
|
||||
const interruptor &intr;
|
||||
|
||||
operator const boost::asio::yield_context &() const;
|
||||
operator boost::asio::yield_context &();
|
||||
|
||||
virtual void interrupted(ctx *const &) noexcept;
|
||||
continuation(const predicate & = true_predicate,
|
||||
const interruptor & = noop_interruptor);
|
||||
|
||||
continuation();
|
||||
virtual ~continuation() noexcept;
|
||||
~continuation() noexcept;
|
||||
};
|
||||
|
||||
/// This type of continuation should be used when yielding a context to a
|
||||
|
@ -68,12 +90,6 @@ struct ircd::ctx::continuation
|
|||
struct ircd::ctx::to_asio
|
||||
:ircd::ctx::continuation
|
||||
{
|
||||
using function = std::function<void (ctx *const &)>;
|
||||
|
||||
function handler;
|
||||
|
||||
void interrupted(ctx *const &) noexcept final override;
|
||||
|
||||
to_asio(function handler);
|
||||
to_asio(const interruptor &);
|
||||
to_asio() = default;
|
||||
};
|
||||
|
|
73
ircd/ctx.cc
73
ircd/ctx.cc
|
@ -163,14 +163,27 @@ ircd::ctx::ctx::wait()
|
|||
if(--notes > 0)
|
||||
return false;
|
||||
|
||||
const auto interruption{[this]
|
||||
// An interrupt invokes this closure to force the alarm to return.
|
||||
const interruptor interruptor{[this]
|
||||
(ctx *const &interruptor) noexcept
|
||||
{
|
||||
wake();
|
||||
}};
|
||||
|
||||
// This is currently a dummy predicate; this is where we can take the
|
||||
// user's real wakeup condition (i.e from a ctx::dock) and use it with
|
||||
// an internal scheduler.
|
||||
const predicate &predicate{[this]
|
||||
{
|
||||
return notes > 0;
|
||||
}};
|
||||
|
||||
// The register switch itself occurs inside the alarm.async_wait() call.
|
||||
// The construction of the arguments to the call on this stack comprise
|
||||
// our final control before the context switch. The destruction of the
|
||||
// arguments comprise the initial control after the context switch.
|
||||
boost::system::error_code ec;
|
||||
alarm.async_wait(boost::asio::yield_context{to_asio{interruption}}[ec]);
|
||||
alarm.async_wait(yield_context{continuation{predicate, interruptor}}[ec]);
|
||||
|
||||
assert(ec == errc::operation_canceled || ec == errc::success);
|
||||
assert(current == this);
|
||||
|
@ -363,7 +376,7 @@ ircd::ctx::terminate(ctx &ctx)
|
|||
return;
|
||||
|
||||
if(likely(&ctx != current && ctx.cont != nullptr))
|
||||
ctx.cont->interrupted(current);
|
||||
ctx.cont->intr(current);
|
||||
}
|
||||
|
||||
/// Marks `ctx` for interruption and enqueues it for resumption to receive the
|
||||
|
@ -386,7 +399,7 @@ ircd::ctx::interrupt(ctx &ctx)
|
|||
return;
|
||||
|
||||
if(likely(&ctx != current && ctx.cont != nullptr))
|
||||
ctx.cont->interrupted(current);
|
||||
ctx.cont->intr(current);
|
||||
}
|
||||
|
||||
/// Marks `ctx` for whether to allow or suppress interruption. Suppression
|
||||
|
@ -800,15 +813,45 @@ noexcept
|
|||
// ctx/continuation.h
|
||||
//
|
||||
|
||||
decltype(ircd::ctx::continuation::true_predicate)
|
||||
ircd::ctx::continuation::true_predicate{[]
|
||||
() -> bool
|
||||
{
|
||||
return true;
|
||||
}};
|
||||
|
||||
decltype(ircd::ctx::continuation::false_predicate)
|
||||
ircd::ctx::continuation::false_predicate{[]
|
||||
() -> bool
|
||||
{
|
||||
return false;
|
||||
}};
|
||||
|
||||
decltype(ircd::ctx::continuation::noop_interruptor)
|
||||
ircd::ctx::continuation::noop_interruptor{[]
|
||||
(ctx *const &interruptor) -> void
|
||||
{
|
||||
return;
|
||||
}};
|
||||
|
||||
//
|
||||
// continuation
|
||||
//
|
||||
|
||||
ircd::ctx::continuation::continuation()
|
||||
ircd::ctx::continuation::continuation(const predicate &pred,
|
||||
const interruptor &intr)
|
||||
:self
|
||||
{
|
||||
ircd::ctx::current
|
||||
}
|
||||
,pred
|
||||
{
|
||||
pred
|
||||
}
|
||||
,intr
|
||||
{
|
||||
intr
|
||||
}
|
||||
{
|
||||
mark(prof::event::CUR_YIELD);
|
||||
|
||||
|
@ -843,12 +886,6 @@ noexcept
|
|||
// pointer while the context is awake.
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ctx::continuation::interrupted(ctx *const &interruptor)
|
||||
noexcept
|
||||
{
|
||||
}
|
||||
|
||||
ircd::ctx::continuation::operator boost::asio::yield_context &()
|
||||
{
|
||||
return *self->yc;
|
||||
|
@ -864,16 +901,12 @@ const
|
|||
// to_asio
|
||||
//
|
||||
|
||||
ircd::ctx::to_asio::to_asio(function handler)
|
||||
:handler{std::move(handler)}
|
||||
{}
|
||||
|
||||
void
|
||||
ircd::ctx::to_asio::interrupted(ctx *const &interruptor)
|
||||
noexcept
|
||||
ircd::ctx::to_asio::to_asio(const interruptor &intr)
|
||||
:continuation
|
||||
{
|
||||
false_predicate, intr
|
||||
}
|
||||
{
|
||||
if(handler)
|
||||
handler(interruptor);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in a new issue