[Development] QPromise cancellation
Ivan Solovev
ivan.solovev at qt.io
Wed Jan 28 12:37:48 CET 2026
Hi Arno,
> This becomes interesting when you have nested and/or chained QFutures.
> Since Qt 6.10 we have QFuture::cancelChain() which propagates the
> "canceled" flag up a continuation chain (nice!). But we don't yet have a
> solution for propagating cancelation into nested futures.
I was trying to solve the "nested futures" problem some time ago
in scope of https://qt-project.atlassian.net/browse/QTBUG-140786,
but could not come up with a reasonable solution.
The discussion in the bugreport has some interesting details.
I think at some point I came to a conclusion that it is impossible to
integrate the nested continuations into our internal continuation chain,
because we simply cannot control when and how they are created.
> We could use QFutureCallOutInterface directly, but this still feels
> "dirty". The CallOutInterface was specifically made for QFutureWatcher;
> continuations disregard it completely. Using QFutureCallOutInterface
> for this now feels like mixing two systems that were not ever designed
> to work together.
I must admit that I did not look at the CallOutInterface when trying to
solve the problem. So, I'd be interested to have a look at a WIP patch.
Maybe we could find a way to fit it nicely into the implementation.
Even though in general I agree that QFuture internals are already
too complicated.
> Looking at how others do it: they don't ingrain cancelation into their
> promise types at all (JS, C++ stdlib). Instead, if you want something to
> support cancelation, you explicitly pass down a token of sorts
BogDan submitted a suggestion that resulted from the previous bugreport.
See https://qt-project.atlassian.net/browse/QTBUG-141174.
We cannot unconditionally use std::stop_token now, because we still
depend on C++17. But maybe exposing QPromise in the continuations
could be helpful? What do you think?
Best regards,
Ivan
Confidential
________________________________________
From: Development <development-bounces at qt-project.org> on behalf of Arno Rehn <a.rehn at menlosystems.com>
Sent: Wednesday, January 28, 2026 11:26 AM
To: development at qt-project.org
Subject: [Development] QPromise cancellation
Hey everyone,
Context: I'm currently working on making QFuture/QPromise compatible
with C++20 coroutine syntax: https://gitlab.com/pumphaus/qawaitablefuture/
This works really nicely already and when finished I'd like to upstream
this into Qt proper.
In this context, I've stumbled on propagating cancellation of a QFuture.
Cancellation is supported by means of QFuture::cancel(). Initially, this
only sets a flag in the shared state. A long-running task can check
QPromise::isCanceled() and abort at suitable moments, calling
QPromise::finish(). QFuture::onCanceled() handlers will only run when
the future is canceled *and* finished.
This becomes interesting when you have nested and/or chained QFutures.
Since Qt 6.10 we have QFuture::cancelChain() which propagates the
"canceled" flag up a continuation chain (nice!). But we don't yet have a
solution for propagating cancelation into nested futures. Think:
auto f = task().then([]{ return someOtherTask(); }).unwrap().
Calling f.cancel() while someOtherTask() is running will not have any
effect. someOtherTask() will not have the canceled flag set and will not
be notified of cancelation whatsoever. Naively, we'd need some kind of
callback for "this was canceled" that we can attach to and propagate
this to inner futures, akin to
auto unwrap() {
// ...
outerFuture.cancelCallback = [=] { innerFuture.cancelChain(); };
}
This kind of callback actually exists already in the form of
QFutureWatcher/QFutureCallOutInterface. In a proof-of-concept in my
"qawaitablefuture" this even works nicely. But the overhead of creating
a QObject for every unwrap()/coroutine seems too high. We could use
QFutureCallOutInterface directly, but this still feels "dirty". The
CallOutInterface was specifically made for QFutureWatcher; continuations
disregard it completely. Using QFutureCallOutInterface for this now
feels like mixing two systems that were not ever designed to work
together. And we'd just pile more and more things on in the internals of
QFuture, which already are quite a mess trying to fit multiple and
"weird" use cases (looking at you, "multiple result QFuture").
Looking at how others do it: they don't ingrain cancelation into their
promise types at all (JS, C++ stdlib). Instead, if you want something to
support cancelation, you explicitly pass down a token of sorts, like
https://en.cppreference.com/w/cpp/header/stop_token.html. Propagation of
the cancelation flag is now explicit and orthogonal to continuations,
making for an overall nicer design I think. OTOH, we have what we have
in Qt, so it would make sense to at least make it usable without any
footguns.
Opinions?
Cheers,
Arno
--
Arno Rehn
Principal Software Engineer
Tel +49 89 189 166 0
Fax +49 89 189 166 111
a.rehn at menlosystems.com
http://www.menlosystems.com/
Menlo Systems GmbH
Bunsenstrasse 5, D-82152 Martinsried, Germany
Amtsgericht München HRB 138145
Geschäftsführung: Dr. Michael Mei, Dr. Ronald Holzwarth
USt.-IdNr. DE217772017, St.-Nr. 14316170324
--
Development mailing list
Development at qt-project.org
https://lists.qt-project.org/listinfo/development
More information about the Development
mailing list