0
0
Fork 0
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:
Jason Volk 2019-09-22 12:49:56 -07:00
parent 3de5381d61
commit 0fff520a72
2 changed files with 40 additions and 25 deletions

View file

@ -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()

View file

@ -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;