1
0
forked from Alepha/Alepha

Interlock for mailbox.

This commit is contained in:
2023-12-12 17:37:03 -05:00
parent bf207244b6
commit 94596d0d7d
3 changed files with 146 additions and 16 deletions

View File

@ -91,6 +91,92 @@ namespace Alepha::Hydrogen::detail::Thread_m
state()->interruption_point();
}
namespace
{
enum State
{
Open,
Waiting,
Synchronizing,
Opening,
};
}
struct Interlock::Impl
{
State state= Open;
ConditionVariable var;
};
Interlock::Interlock() : pimpl( std::make_unique< Impl >() ) {}
Interlock::~Interlock()= default;
bool
Interlock::waiter( unique_lock< mutex > &lock )
{
// Defensively, if a thread called `checkpoint`, we
// might encounter that thread here, and need
// that thread to terminate the previous interlock
// phase.
while( impl().state == Opening )
{
impl().var.wait( lock );
}
if( impl().state == Open )
{
impl().state= Waiting;
return false;
}
else if( impl().state == Waiting )
{
impl().state= Synchronizing;
return true;
}
else { abort(); }
}
void
Interlock::noblock( unique_lock< mutex > &lock )
{
if( impl().state == Waiting )
{
// Nolock form will just leave the bit set.
}
else if( impl().state == Synchronizing )
{
impl().state= Opening;
impl().var.notify_one();
}
else { abort(); }
}
void
Interlock::interlock( unique_lock< mutex > &lock )
{
if( impl().state == Waiting )
{
while( impl().state == Waiting )
{
impl().var.wait( lock );
}
impl().state= Open;
impl().var.notify_one();
}
else if( impl().state == Synchronizing )
{
impl().state= Opening;
impl().var.notify_one();
while( impl().state == Opening )
{
impl().var.wait( lock );
}
}
else{ abort(); }
}
static auto init= Utility::enroll <=[]
{
state()= std::make_shared< ThreadState >();