forked from Alepha/Alepha
Interlock for mailbox.
This commit is contained in:
86
Thread.cc
86
Thread.cc
@ -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 >();
|
||||
|
Reference in New Issue
Block a user