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();
|
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 );
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user