QPromise: run continuation(s) on destruction

If the QFuture is canceled because the associated QPromise has been
destroyed, we still need to run its continuations (i.e. onCanceled
handler, if it's attached), so replaced the cleanContinuation() call
inside ~QPromise() with runContinuation(), which will also take care of
cleaning the continuation.

[ChangeLog][QtCore][Important Behavior Changes] QFuture now runs its
continuations when its associated QPromise has been destroyed.
Previously, if a QFuture was canceled because the associated QPromise
has been destroyed, its continuations were skipped.

Fixes: QTBUG-103992
Pick-to: 6.4 6.3 6.2
Change-Id: Ie05bc760c96c349aade8adb8d2fe5263aff8efac
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Sona Kurazyan 2022-06-20 15:46:00 +02:00
parent 5d041a15bf
commit bf3fc5c95c
2 changed files with 21 additions and 1 deletions

View File

@ -39,7 +39,7 @@ public:
// potential waits
if (d.d && !(d.loadState() & QFutureInterfaceBase::State::Finished)) {
d.cancelAndFinish(); // cancel and finalize the state
d.cleanContinuation();
d.runContinuation();
}
}

View File

@ -40,6 +40,7 @@ private slots:
#endif
void cancelWhenReassigned();
void cancelWhenDestroyedWithoutStarting();
void cancelWhenDestroyedRunsContinuations();
void finishWhenSwapped();
void cancelWhenMoved();
void waitUntilResumed();
@ -494,6 +495,25 @@ void tst_QPromise::cancelWhenDestroyedWithoutStarting()
QVERIFY(future.isFinished());
}
void tst_QPromise::cancelWhenDestroyedRunsContinuations()
{
QFuture<void> future;
bool onCanceledCalled = false;
bool thenCalled = false;
{
QPromise<void> promise;
future = promise.future();
future.then([&] {
thenCalled = true;
}).onCanceled([&] {
onCanceledCalled = true;
});
}
QVERIFY(future.isFinished());
QVERIFY(!thenCalled);
QVERIFY(onCanceledCalled);
}
void tst_QPromise::finishWhenSwapped()
{
#if !QT_CONFIG(cxx11_future)