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 <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 );
}
}; };
} }