diff --git a/Atomic/Mailbox.h b/Atomic/Mailbox.h index c21ae04..8cd0684 100644 --- a/Atomic/Mailbox.h +++ b/Atomic/Mailbox.h @@ -13,6 +13,7 @@ static_assert( __cplusplus > 2020'99 ); #include #include +#include #include #include @@ -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 ); + } }; }