From 08654a9a86831147a496681f25187a0a0dd78b18 Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Sat, 6 Jan 2024 01:46:34 -0500 Subject: [PATCH] Deal with last-item-in-the-queue bug. --- Atomic/Dropbox.h | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Atomic/Dropbox.h b/Atomic/Dropbox.h index 312fddb..68c4ff1 100644 --- a/Atomic/Dropbox.h +++ b/Atomic/Dropbox.h @@ -102,12 +102,21 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Dropbox_m drops.producer.releaseBox(); } + void + recycle() + { + auto &filled= drops.consumer.acquireBox(); + filled.notification= nullptr; + filled.items.clear(); + drops.consumer.releaseBox(); + } + public: explicit Dropbox( const size_t lim ) : boxLimit( lim ) { - drops.consumer.releaseBox(); + recycle(); } Item @@ -118,14 +127,24 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Dropbox_m { [[unlikely]]; auto notification= std::move( filled.notification ); - filled.notification= nullptr; - drops.consumer.releaseBox(); + recycle(); std::rethrow_exception( std::move( notification ) ); } + assert( not filled.items.empty() ); auto &rv= *filled.pos++; + // If it was the last item and we're going to rotate/reccyle, + // be sure that we don't reference the now-stale value. + // This is a special case that will only come up at the end of each queue + // cycle. + // + // I need to research if NRV applies in this circumstance -- if so, then the + // `rv` variable can be an instance instead of a reference. if( filled.pos == end( filled.items ) and filled.notification == nullptr ) { - drops.consumer.releaseBox(); + [[unlikely]]; + auto rvTemp= std::move( rv ); + recycle(); + return rvTemp; } return std::move( rv ); }