From 571946739ecb3c9140afa1e5a64da26b3b849a65 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 11 May 2021 11:31:27 +0200 Subject: [PATCH] task: Fix cancelling gather() of tasks --- panda/src/event/asyncFuture.cxx | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/panda/src/event/asyncFuture.cxx b/panda/src/event/asyncFuture.cxx index b1c8ce0fc3..696680bb1a 100644 --- a/panda/src/event/asyncFuture.cxx +++ b/panda/src/event/asyncFuture.cxx @@ -403,28 +403,30 @@ AsyncGatheringFuture(AsyncFuture::Futures futures) : bool AsyncGatheringFuture:: cancel() { 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() // callbacks won't end up causing it to be set to "finished". AtomicAdjust::inc(_num_pending); bool any_cancelled = false; - AsyncFuture::Futures::const_iterator it; - for (it = _futures.begin(); it != _futures.end(); ++it) { - AsyncFuture *fut = *it; + for (AsyncFuture *fut : _futures) { if (fut->cancel()) { any_cancelled = true; } } - // Now change state to "cancelled" and call the notify_done() callbacks. - // Don't call notify_done() if another thread has beaten us to it. - if (set_future_state(FS_cancelled)) { - notify_done(false); + // If all the futures were cancelled, change state of this future to + // "cancelled" and call the notify_done() callbacks. + if (!AtomicAdjust::dec(_num_pending)) { + 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; } else { return false;