QFutureInterface: add a warning when an existing continuation is overwritten
... and also extend the documentation to explain this case explicitly. Fixes: QTBUG-107545 Change-Id: I9414cc677b037989de60e97871485018e5c8a569 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> (cherry picked from commit 502a7706b94380d4957a7e594fc7c4c4db8ae81b) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
122c825022
commit
2e1025dd4a
@ -385,3 +385,17 @@ QFuture<QFuture<QFuture<int>>>> outerFuture;
|
||||
QFuture<int> unwrappedFuture = outerFuture.unwrap();
|
||||
|
||||
//! [30]
|
||||
|
||||
//! [31]
|
||||
QPromise<int> p;
|
||||
|
||||
QFuture<int> f1 = p.future();
|
||||
f1.then([](int) { qDebug("first"); });
|
||||
|
||||
QFuture<int> f2 = p.future();
|
||||
f2.then([](int) { qDebug("second"); });
|
||||
|
||||
p.start();
|
||||
p.addResult(42);
|
||||
p.finish();
|
||||
//! [31]
|
||||
|
@ -75,6 +75,15 @@
|
||||
If \c testFuture gets canceled, its state is propagated to the next then(),
|
||||
which will be also canceled. So in this case \c {Block 6} will be called.
|
||||
|
||||
The future can have only one continuation. Consider the following example:
|
||||
|
||||
\snippet code/src_corelib_thread_qfuture.cpp 31
|
||||
|
||||
In this case \c f1 and \c f2 are effectively the same QFuture object, as
|
||||
they share the same internal state. As a result, calling
|
||||
\l {QFuture::}{then} on \c f2 will overwrite the continuation specified for
|
||||
\c {f1}. So, only \c {"second"} will be printed when this code is executed.
|
||||
|
||||
QFuture also offers ways to interact with a running computation. For
|
||||
instance, the computation can be canceled with the cancel() function. To
|
||||
suspend or resume the computation, use the setSuspended() function or one of
|
||||
|
@ -834,6 +834,10 @@ void QFutureInterfaceBase::setContinuation(std::function<void(const QFutureInter
|
||||
// store the move-only continuation, to guarantee that the associated
|
||||
// future's data stays alive.
|
||||
if (d->continuationState != QFutureInterfaceBasePrivate::Cleaned) {
|
||||
if (d->continuation) {
|
||||
qWarning() << "Adding a continuation to a future which already has a continuation. "
|
||||
"The existing continuation is overwritten.";
|
||||
}
|
||||
d->continuation = std::move(func);
|
||||
d->continuationData = continuationFutureData;
|
||||
}
|
||||
|
@ -220,6 +220,7 @@ private slots:
|
||||
void whenAnyDifferentTypesWithCanceled();
|
||||
void whenAnyDifferentTypesWithFailed();
|
||||
|
||||
void continuationOverride();
|
||||
void continuationsDontLeak();
|
||||
void cancelAfterFinishWithContinuations();
|
||||
|
||||
@ -4662,6 +4663,35 @@ void tst_QFuture::whenAnyDifferentTypesWithFailed()
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QFuture::continuationOverride()
|
||||
{
|
||||
QPromise<int> p;
|
||||
bool firstExecuted = false;
|
||||
bool secondExecuted = false;
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Adding a continuation to a future which already has a continuation. "
|
||||
"The existing continuation is overwritten.");
|
||||
|
||||
QFuture<int> f1 = p.future();
|
||||
f1.then([&firstExecuted](int) {
|
||||
firstExecuted = true;
|
||||
});
|
||||
|
||||
QFuture<int> f2 = p.future();
|
||||
f2.then([&secondExecuted](int) {
|
||||
secondExecuted = true;
|
||||
});
|
||||
|
||||
p.start();
|
||||
p.addResult(42);
|
||||
p.finish();
|
||||
|
||||
QVERIFY(p.future().isFinished());
|
||||
QVERIFY(!firstExecuted);
|
||||
QVERIFY(secondExecuted);
|
||||
}
|
||||
|
||||
struct InstanceCounter
|
||||
{
|
||||
InstanceCounter() { ++count; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user