0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-09-30 12:48:54 +02: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 const boost::asio::yield_context &() const;
operator boost::asio::yield_context &(); operator boost::asio::yield_context &();
virtual void interrupted(ctx *const &) noexcept;
continuation(ctx *const &self = ircd::ctx::current); 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 /// 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 struct ircd::ctx::to_asio
:ircd::ctx::continuation :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 uintptr_t stack_base; // assigned when spawned
size_t stack_max; // User given stack size size_t stack_max; // User given stack size
int64_t notes; // norm: 0 = asleep; 1 = awake; inc by others; dec by self 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() ctx *adjoindre; // context waiting for this to join()
microseconds awake; // monotonic counter microseconds awake; // monotonic counter
ctx *next; // next node in a ctx::list ctx *next; // next node in a ctx::list
@ -76,6 +77,7 @@ ircd::ctx::ctx::ctx(const char *const &name,
,stack_base{0} ,stack_base{0}
,stack_max{stack_max} ,stack_max{stack_max}
,notes{1} ,notes{1}
,cont{nullptr}
,adjoindre{nullptr} ,adjoindre{nullptr}
,awake{0us} ,awake{0us}
,next{nullptr} ,next{nullptr}
@ -183,8 +185,14 @@ ircd::ctx::ctx::wait()
if(--notes > 0) if(--notes > 0)
return false; return false;
const auto interruption{[this]
(ctx *const &interruptor) noexcept
{
wake();
}};
boost::system::error_code ec; 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(ec == errc::operation_canceled || ec == errc::success);
assert(current == this); assert(current == this);
@ -217,7 +225,10 @@ try
} }
catch(const boost::system::system_error &e) 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 /// Throws if this context has been flagged for interruption and clears
@ -416,8 +427,15 @@ ircd::ctx::signal(ctx &ctx,
void void
ircd::ctx::interrupt(ctx &ctx) ircd::ctx::interrupt(ctx &ctx)
{ {
if(finished(ctx))
return;
if(interruption(ctx))
return;
ctx.flags |= context::INTERRUPTED; ctx.flags |= context::INTERRUPTED;
ctx.wake(); if(likely(&ctx != current && ctx.cont != nullptr))
ctx.cont->interrupted(current);
} }
/// Indicates if `ctx` was ever jumped to /// Indicates if `ctx` was ever jumped to
@ -500,6 +518,7 @@ ircd::ctx::continuation::continuation(ctx *const &self)
assert(!critical_asserted); assert(!critical_asserted);
assert(self != nullptr); assert(self != nullptr);
assert(self->notes <= 1); assert(self->notes <= 1);
self->cont = this;
ircd::ctx::current = nullptr; ircd::ctx::current = nullptr;
} }
@ -509,6 +528,15 @@ noexcept
ircd::ctx::current = self; ircd::ctx::current = self;
self->notes = 1; self->notes = 1;
mark(prof::event::CUR_CONTINUE); 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 &() ircd::ctx::continuation::operator boost::asio::yield_context &()
@ -522,6 +550,18 @@ const
return *self->yc; return *self->yc;
} }
//
// to_asio
//
void
ircd::ctx::to_asio::interrupted(ctx *const &interruptor)
noexcept
{
if(handler)
handler(interruptor);
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// ctx/context.h // ctx/context.h