task: Fix cancelling gather() of tasks

This commit is contained in:
rdb 2021-05-11 11:31:27 +02:00
parent 91a6ff1d81
commit 571946739e

View File

@ -403,28 +403,30 @@ AsyncGatheringFuture(AsyncFuture::Futures futures) :
bool AsyncGatheringFuture:: bool AsyncGatheringFuture::
cancel() { cancel() {
if (!done()) { if (!done()) {
if (task_cat.is_debug()) {
task_cat.debug()
<< "Cancelling AsyncGatheringFuture (" << _futures.size() << " futures)\n";
}
// Temporarily increase the pending count so that the notify_done() // Temporarily increase the pending count so that the notify_done()
// callbacks won't end up causing it to be set to "finished". // callbacks won't end up causing it to be set to "finished".
AtomicAdjust::inc(_num_pending); AtomicAdjust::inc(_num_pending);
bool any_cancelled = false; bool any_cancelled = false;
AsyncFuture::Futures::const_iterator it; for (AsyncFuture *fut : _futures) {
for (it = _futures.begin(); it != _futures.end(); ++it) {
AsyncFuture *fut = *it;
if (fut->cancel()) { if (fut->cancel()) {
any_cancelled = true; any_cancelled = true;
} }
} }
// Now change state to "cancelled" and call the notify_done() callbacks. // If all the futures were cancelled, change state of this future to
// Don't call notify_done() if another thread has beaten us to it. // "cancelled" and call the notify_done() callbacks.
if (set_future_state(FS_cancelled)) { if (!AtomicAdjust::dec(_num_pending)) {
notify_done(false); if (set_future_state(FS_cancelled)) {
notify_done(false);
}
} }
// Decreasing the pending count is kind of pointless now, so we do it only
// in a debug build.
nassertr(!AtomicAdjust::dec(_num_pending), any_cancelled);
return any_cancelled; return any_cancelled;
} else { } else {
return false; return false;