0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-26 15:33:54 +01:00

ircd::ctx: Integrate custom interruption action.

This commit is contained in:
Jason Volk 2018-03-23 15:35:09 -07:00
parent 980d24b38e
commit db8810e397
2 changed files with 59 additions and 5 deletions

View file

@ -50,8 +50,10 @@ struct ircd::ctx::continuation
operator const boost::asio::yield_context &() const;
operator boost::asio::yield_context &();
virtual void interrupted(ctx *const &) noexcept;
continuation(ctx *const &self = ircd::ctx::current);
~continuation() noexcept;
virtual ~continuation() noexcept;
};
/// This type of continuation should be used when yielding a context to a
@ -66,5 +68,17 @@ struct ircd::ctx::continuation
struct ircd::ctx::to_asio
:ircd::ctx::continuation
{
using continuation::continuation;
using function = std::function<void (ctx *const &) noexcept>;
function handler;
void interrupted(ctx *const &) noexcept final override;
to_asio(const function &handler = {});
};
inline
ircd::ctx::to_asio::to_asio(const function &handler)
:continuation{ircd::ctx::current}
,handler{handler}
{}

View file

@ -28,6 +28,7 @@ struct ircd::ctx::ctx
uintptr_t stack_base; // assigned when spawned
size_t stack_max; // User given stack size
int64_t notes; // norm: 0 = asleep; 1 = awake; inc by others; dec by self
continuation *cont; // valid when asleep; invalid when awake
ctx *adjoindre; // context waiting for this to join()
microseconds awake; // monotonic counter
ctx *next; // next node in a ctx::list
@ -76,6 +77,7 @@ ircd::ctx::ctx::ctx(const char *const &name,
,stack_base{0}
,stack_max{stack_max}
,notes{1}
,cont{nullptr}
,adjoindre{nullptr}
,awake{0us}
,next{nullptr}
@ -183,8 +185,14 @@ ircd::ctx::ctx::wait()
if(--notes > 0)
return false;
const auto interruption{[this]
(ctx *const &interruptor) noexcept
{
wake();
}};
boost::system::error_code ec;
alarm.async_wait(boost::asio::yield_context{to_asio{this}}[ec]);
alarm.async_wait(boost::asio::yield_context{to_asio{interruption}}[ec]);
assert(ec == errc::operation_canceled || ec == errc::success);
assert(current == this);
@ -217,7 +225,10 @@ try
}
catch(const boost::system::system_error &e)
{
ircd::log::error("ctx::wake(%p): %s", this, e.what());
log::error
{
"ctx::wake(%p): %s", this, e.what()
};
}
/// Throws if this context has been flagged for interruption and clears
@ -416,8 +427,15 @@ ircd::ctx::signal(ctx &ctx,
void
ircd::ctx::interrupt(ctx &ctx)
{
if(finished(ctx))
return;
if(interruption(ctx))
return;
ctx.flags |= context::INTERRUPTED;
ctx.wake();
if(likely(&ctx != current && ctx.cont != nullptr))
ctx.cont->interrupted(current);
}
/// Indicates if `ctx` was ever jumped to
@ -500,6 +518,7 @@ ircd::ctx::continuation::continuation(ctx *const &self)
assert(!critical_asserted);
assert(self != nullptr);
assert(self->notes <= 1);
self->cont = this;
ircd::ctx::current = nullptr;
}
@ -509,6 +528,15 @@ noexcept
ircd::ctx::current = self;
self->notes = 1;
mark(prof::event::CUR_CONTINUE);
// self->continuation is not null'ed here; it remains an invalid
// pointer while the context is awake.
}
void
ircd::ctx::continuation::interrupted(ctx *const &interruptor)
noexcept
{
}
ircd::ctx::continuation::operator boost::asio::yield_context &()
@ -522,6 +550,18 @@ const
return *self->yc;
}
//
// to_asio
//
void
ircd::ctx::to_asio::interrupted(ctx *const &interruptor)
noexcept
{
if(handler)
handler(interruptor);
}
///////////////////////////////////////////////////////////////////////////////
//
// ctx/context.h