forked from Alepha/Alepha
Add notification primitive to Mailbox.
This commit is contained in:
@ -13,6 +13,7 @@ static_assert( __cplusplus > 2020'99 );
|
|||||||
#include <Alepha/Alepha.h>
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
#include <Alepha/Thread.h>
|
#include <Alepha/Thread.h>
|
||||||
#include <Alepha/Exception.h>
|
#include <Alepha/Exception.h>
|
||||||
@ -95,6 +96,8 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Mailbox_m
|
|||||||
std::vector< Item > filled;
|
std::vector< Item > filled;
|
||||||
std::vector< Item >::iterator pos= begin( filled );
|
std::vector< Item >::iterator pos= begin( filled );
|
||||||
|
|
||||||
|
std::exception_ptr notification;
|
||||||
|
|
||||||
bool finished= false;
|
bool finished= false;
|
||||||
|
|
||||||
bool mustFinish= false;
|
bool mustFinish= false;
|
||||||
@ -125,6 +128,15 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Mailbox_m
|
|||||||
interlockPoint.checkpoint( lock, [&]{ awaken( lock ); } );
|
interlockPoint.checkpoint( lock, [&]{ awaken( lock ); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void
|
||||||
|
raiseNotification()
|
||||||
|
{
|
||||||
|
auto notification_ptr= std::move( notification );
|
||||||
|
notification= nullptr;
|
||||||
|
std::rethrow_exception( std::move( notification_ptr ) );
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
[[noreturn]] void
|
[[noreturn]] void
|
||||||
raiseFinished()
|
raiseFinished()
|
||||||
{
|
{
|
||||||
@ -163,10 +175,12 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Mailbox_m
|
|||||||
if( pos == end( filled ) ) [[unlikely]]
|
if( pos == end( filled ) ) [[unlikely]]
|
||||||
{
|
{
|
||||||
if( C::debugPop ) error() << "We might have to hit the sync point." << std::endl;
|
if( C::debugPop ) error() << "We might have to hit the sync point." << std::endl;
|
||||||
|
if( notification ) raiseNotification();
|
||||||
if( mustFinish ) raiseFinished();
|
if( mustFinish ) raiseFinished();
|
||||||
Alepha::unique_lock lock( access );
|
Alepha::unique_lock lock( access );
|
||||||
if( C::debugPop ) error() << "We have to hit the sync point." << std::endl;
|
if( C::debugPop ) error() << "We have to hit the sync point." << std::endl;
|
||||||
interlock( lock );
|
interlock( lock );
|
||||||
|
if( notification and pos == end( filled ) ) raiseNotification();
|
||||||
if( finished )
|
if( finished )
|
||||||
{
|
{
|
||||||
if( pos == end( filled ) ) raiseFinished();
|
if( pos == end( filled ) ) raiseFinished();
|
||||||
@ -224,6 +238,21 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Mailbox_m
|
|||||||
finished= true;
|
finished= true;
|
||||||
checkpoint( lock );
|
checkpoint( lock );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief This function will pump the mailbox, and deliver a custom notification
|
||||||
|
* event to the other side.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
notify( auto newNotification )
|
||||||
|
{
|
||||||
|
auto notification_ptr= std::make_exception_ptr( std::move( notification ) );
|
||||||
|
Alepha::unique_lock lock( access );
|
||||||
|
assertion( not finished );
|
||||||
|
notification= std::move( notification_ptr );
|
||||||
|
interlock( lock );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user