forked from Alepha/Alepha
Add a new mailbox alternative
This commit is contained in:
91
Atomic/DeadDrop.h
Normal file
91
Atomic/DeadDrop.h
Normal file
@ -0,0 +1,91 @@
|
||||
static_assert( __cplusplus > 2020'99 );
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Alepha/Alepha.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include <Alepha/Thread.h>
|
||||
|
||||
namespace Alepha::Hydrogen::Atomic ::detail:: DeadDrop_m
|
||||
{
|
||||
inline namespace exports
|
||||
{
|
||||
template< typename Item >
|
||||
class DeadDrop;
|
||||
}
|
||||
|
||||
template< typename Item >
|
||||
class exports::DeadDrop
|
||||
{
|
||||
private:
|
||||
Alepha::mutex access;
|
||||
|
||||
struct Box
|
||||
{
|
||||
private:
|
||||
Alepha::mutex *access= nullptr;
|
||||
Alepha::condition_variable ready;
|
||||
|
||||
Item original;
|
||||
|
||||
Item *active= &original;
|
||||
std::queue< Item * > next;
|
||||
|
||||
Box *companion= nullptr;
|
||||
|
||||
friend DeadDrop;
|
||||
|
||||
void
|
||||
setup( Alepha::mutex *const access, Box *const companion )
|
||||
{
|
||||
this->access= access;
|
||||
this->companion= companion;
|
||||
}
|
||||
|
||||
public:
|
||||
Item &
|
||||
acquireBox()
|
||||
{
|
||||
if( not active )
|
||||
{
|
||||
[[unlikely]];
|
||||
std::unique_lock lock{ *access };
|
||||
ready.wait( lock, [&]{ return not next.empty(); } );
|
||||
active= next.front();
|
||||
next.pop();
|
||||
}
|
||||
assert( active );
|
||||
return *active;
|
||||
}
|
||||
|
||||
void
|
||||
releaseBox()
|
||||
{
|
||||
std::unique_lock lock{ *access };
|
||||
companion->next.push( active );
|
||||
active= nullptr;
|
||||
companion->ready.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
Box producer;
|
||||
Box consumer;
|
||||
|
||||
explicit
|
||||
DeadDrop()
|
||||
{
|
||||
producer.setup( &this->access, &consumer );
|
||||
consumer.setup( &this->access, &producer );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace Alepha::Hydrogen::Atomic::inline exports::inline DeadDrop_m
|
||||
{
|
||||
using namespace detail::DeadDrop_m::exports;
|
||||
}
|
||||
Reference in New Issue
Block a user