1
0
forked from Alepha/Alepha
Files
Alepha/Atomic/DeadDrop.h

94 lines
1.6 KiB
C++

static_assert( __cplusplus > 2020'99 );
#pragma once
#include <Alepha/Alepha.h>
#include <cassert>
#include <queue>
#include <boost/circular_buffer.hpp>
#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;
boost::circular_buffer< Item * > next{ 2 };
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_front();
}
assert( active );
return *active;
}
void
releaseBox()
{
std::unique_lock lock{ *access };
companion->next.push_back( 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;
}