forked from Alepha/Alepha
Deal with last-item-in-the-queue bug.
This commit is contained in:
@ -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 );
|
||||
}
|
||||
|
Reference in New Issue
Block a user