1
0
forked from Alepha/Alepha

Deal with last-item-in-the-queue bug.

This commit is contained in:
2024-01-06 01:46:34 -05:00
parent da34142bf1
commit 08654a9a86

View File

@ -102,12 +102,21 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Dropbox_m
drops.producer.releaseBox(); drops.producer.releaseBox();
} }
void
recycle()
{
auto &filled= drops.consumer.acquireBox();
filled.notification= nullptr;
filled.items.clear();
drops.consumer.releaseBox();
}
public: public:
explicit explicit
Dropbox( const size_t lim ) Dropbox( const size_t lim )
: boxLimit( lim ) : boxLimit( lim )
{ {
drops.consumer.releaseBox(); recycle();
} }
Item Item
@ -118,14 +127,24 @@ namespace Alepha::Hydrogen::Atomic ::detail:: Dropbox_m
{ {
[[unlikely]]; [[unlikely]];
auto notification= std::move( filled.notification ); auto notification= std::move( filled.notification );
filled.notification= nullptr; recycle();
drops.consumer.releaseBox();
std::rethrow_exception( std::move( notification ) ); std::rethrow_exception( std::move( notification ) );
} }
assert( not filled.items.empty() );
auto &rv= *filled.pos++; 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 ) 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 ); return std::move( rv );
} }