1
0
forked from Alepha/Alepha

Add notification primitive to Mailbox.

This commit is contained in:
2024-01-02 04:59:54 -05:00
parent c1c217146c
commit 8ce3bd8bdf

View File

@ -13,6 +13,7 @@ static_assert( __cplusplus > 2020'99 );
#include <Alepha/Alepha.h>
#include <vector>
#include <exception>
#include <Alepha/Thread.h>
#include <Alepha/Exception.h>
@ -95,6 +96,8 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Mailbox_m
std::vector< Item > filled;
std::vector< Item >::iterator pos= begin( filled );
std::exception_ptr notification;
bool finished= false;
bool mustFinish= false;
@ -125,6 +128,15 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Mailbox_m
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
raiseFinished()
{
@ -163,10 +175,12 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Mailbox_m
if( pos == end( filled ) ) [[unlikely]]
{
if( C::debugPop ) error() << "We might have to hit the sync point." << std::endl;
if( notification ) raiseNotification();
if( mustFinish ) raiseFinished();
Alepha::unique_lock lock( access );
if( C::debugPop ) error() << "We have to hit the sync point." << std::endl;
interlock( lock );
if( notification and pos == end( filled ) ) raiseNotification();
if( finished )
{
if( pos == end( filled ) ) raiseFinished();
@ -224,6 +238,21 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Mailbox_m
finished= true;
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 );
}
};
}