mirror of
https://github.com/matrix-construct/construct
synced 2024-11-16 15:00:51 +01:00
ircd::ctx::ctx: Split the interruption condition check from the throwing code.
This commit is contained in:
parent
3de5381d61
commit
0fff520a72
2 changed files with 40 additions and 25 deletions
64
ircd/ctx.cc
64
ircd/ctx.cc
|
@ -269,44 +269,32 @@ catch(const std::exception &e)
|
|||
|
||||
/// Throws if this context has been flagged for interruption and clears
|
||||
/// the flag.
|
||||
[[gnu::hot]]
|
||||
void
|
||||
ircd::ctx::ctx::interruption_point()
|
||||
{
|
||||
static const auto &flags
|
||||
if(unlikely(interruption()))
|
||||
{
|
||||
context::TERMINATED | context::INTERRUPTED
|
||||
};
|
||||
if(termination_point(std::nothrow))
|
||||
throw terminated{};
|
||||
|
||||
// Fast test-and-bail for the very likely case there is no interrupt.
|
||||
if(likely((this->flags & flags) == 0))
|
||||
return;
|
||||
|
||||
// The NOINTERRUPT flag works by pretending there is no interrupt flag
|
||||
// set and also does not clear the flag. This allows the interrupt
|
||||
// to remain pending until the uninterruptible section is complete.
|
||||
if(this->flags & context::NOINTERRUPT)
|
||||
return;
|
||||
|
||||
// Termination shouldn't be used for normal operation so please eat this
|
||||
// branch misprediction.
|
||||
if(unlikely(termination_point(std::nothrow)))
|
||||
throw terminated{};
|
||||
|
||||
if(interruption_point(std::nothrow))
|
||||
throw interrupted
|
||||
{
|
||||
"ctx:%lu '%s'", id, name
|
||||
};
|
||||
if(likely(interruption_point(std::nothrow)))
|
||||
throw interrupted
|
||||
{
|
||||
"ctx:%lu '%s'", id, name
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this context has been flagged for termination. Does not
|
||||
/// clear the flag. Sets the NOINTERRUPT flag so the context cannot be further
|
||||
// interrupted which simplifies the termination process.
|
||||
[[gnu::hot]]
|
||||
bool
|
||||
ircd::ctx::ctx::termination_point(std::nothrow_t)
|
||||
noexcept
|
||||
{
|
||||
if(flags & context::TERMINATED)
|
||||
if(unlikely(flags & context::TERMINATED))
|
||||
{
|
||||
assert(~flags & context::NOINTERRUPT);
|
||||
flags |= context::NOINTERRUPT;
|
||||
|
@ -318,11 +306,12 @@ noexcept
|
|||
|
||||
/// Returns true if this context has been flagged for interruption and
|
||||
/// clears the flag.
|
||||
[[gnu::hot]]
|
||||
bool
|
||||
ircd::ctx::ctx::interruption_point(std::nothrow_t)
|
||||
noexcept
|
||||
{
|
||||
if(flags & context::INTERRUPTED)
|
||||
if(unlikely(flags & context::INTERRUPTED))
|
||||
{
|
||||
assert(~flags & context::NOINTERRUPT);
|
||||
flags &= ~context::INTERRUPTED;
|
||||
|
@ -332,6 +321,31 @@ noexcept
|
|||
else return false;
|
||||
}
|
||||
|
||||
/// True if this context has been flagged for interruption or termination
|
||||
/// and interrupts are not blocked.
|
||||
[[gnu::hot]]
|
||||
bool
|
||||
ircd::ctx::ctx::interruption()
|
||||
const noexcept
|
||||
{
|
||||
static const auto &flags
|
||||
{
|
||||
context::TERMINATED | context::INTERRUPTED
|
||||
};
|
||||
|
||||
// Fast test-and-bail for the very likely case there is no interrupt.
|
||||
if(likely((this->flags & flags) == 0))
|
||||
return false;
|
||||
|
||||
// The NOINTERRUPT flag works by pretending there is no interrupt flag
|
||||
// set and also does not clear the flag. This allows the interrupt
|
||||
// to remain pending until the uninterruptible section is complete.
|
||||
if(this->flags & context::NOINTERRUPT)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[[gnu::hot]]
|
||||
bool
|
||||
ircd::ctx::ctx::started()
|
||||
|
|
|
@ -64,6 +64,7 @@ struct ircd::ctx::ctx
|
|||
|
||||
bool started() const noexcept; // context was ever entered
|
||||
bool finished() const noexcept; // context will not be further entered.
|
||||
bool interruption() const noexcept;
|
||||
|
||||
bool interruption_point(std::nothrow_t) noexcept;
|
||||
bool termination_point(std::nothrow_t) noexcept;
|
||||
|
|
Loading…
Reference in a new issue