Fix QFuture::waitForFinished to wait until QFuture is started
Currently QFuture::waitForFinished() exits as soon as the future is not in the running state. If the user calls it before QPromise::reportStarted() is called, it will exit immediately, because nothing is running yet. Fix the behavior to wait for the finished state. [ChangeLog][Important Behavior Changes][QtCore] Fixed the behavior of QFuture::waitForFinished() to wait until the future is actually in the finished state, instead of exiting as soon as it is not in the running state. This prevents waitForFinished() from exiting immediately, if at the moment of calling it the future is not started yet. Task-number: QTBUG-84867 Change-Id: I12f5e95d8200cfffa5653b6aa566a625f8320ca8 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
7d35e31efb
commit
9efe2a8603
@ -404,7 +404,7 @@
|
||||
/*! \fn template <typename T> void QFuture<T>::waitForFinished()
|
||||
|
||||
Waits for the asynchronous computation to finish (including cancel()ed
|
||||
computations).
|
||||
computations), i.e. until isFinished() returns \c true.
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> T QFuture<T>::result() const
|
||||
|
@ -422,7 +422,7 @@ void QFutureInterfaceBase::waitForResult(int resultIndex)
|
||||
void QFutureInterfaceBase::waitForFinished()
|
||||
{
|
||||
QMutexLocker lock(&d->m_mutex);
|
||||
const bool alreadyFinished = !isRunningOrPending();
|
||||
const bool alreadyFinished = isFinished();
|
||||
lock.unlock();
|
||||
|
||||
if (!alreadyFinished) {
|
||||
@ -430,7 +430,7 @@ void QFutureInterfaceBase::waitForFinished()
|
||||
|
||||
lock.relock();
|
||||
|
||||
while (isRunningOrPending())
|
||||
while (!isFinished())
|
||||
d->waitCondition.wait(&d->m_mutex);
|
||||
}
|
||||
|
||||
|
@ -417,7 +417,7 @@ bool QFutureWatcherBase::isSuspended() const
|
||||
/*! \fn template <typename T> void QFutureWatcher<T>::waitForFinished()
|
||||
|
||||
Waits for the asynchronous computation to finish (including cancel()ed
|
||||
computations).
|
||||
computations), i.e. until isFinished() returns \c true.
|
||||
*/
|
||||
void QFutureWatcherBase::waitForFinished()
|
||||
{
|
||||
|
@ -144,6 +144,7 @@ private slots:
|
||||
void takeResultWorksForTypesWithoutDefaultCtor();
|
||||
void canceledFutureIsNotValid();
|
||||
void signalConnect();
|
||||
void waitForFinished();
|
||||
|
||||
private:
|
||||
using size_type = std::vector<int>::size_type;
|
||||
@ -3076,5 +3077,29 @@ void tst_QFuture::signalConnect()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QFuture::waitForFinished()
|
||||
{
|
||||
QFutureInterface<void> fi;
|
||||
auto future = fi.future();
|
||||
|
||||
QScopedPointer<QThread> waitingThread (QThread::create([&] {
|
||||
future.waitForFinished();
|
||||
}));
|
||||
|
||||
waitingThread->start();
|
||||
|
||||
QVERIFY(!waitingThread->wait(200));
|
||||
QVERIFY(!waitingThread->isFinished());
|
||||
|
||||
fi.reportStarted();
|
||||
QVERIFY(!waitingThread->wait(200));
|
||||
QVERIFY(!waitingThread->isFinished());
|
||||
|
||||
fi.reportFinished();
|
||||
|
||||
QVERIFY(waitingThread->wait());
|
||||
QVERIFY(waitingThread->isFinished());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QFuture)
|
||||
#include "tst_qfuture.moc"
|
||||
|
@ -75,11 +75,8 @@ void snippet_QPromise::basicExample()
|
||||
QPromise<int> promise;
|
||||
QFuture<int> future = promise.future();
|
||||
|
||||
// Note: calling reportStarted() prior to thread creation to enforce order
|
||||
// of calls: first promise.reportStarted() then future.waitForFinished()
|
||||
promise.reportStarted(); // notifies QFuture that the computation is started
|
||||
|
||||
QScopedPointer<QThread> thread(QThread::create([] (QPromise<int> promise) {
|
||||
promise.reportStarted(); // notifies QFuture that the computation is started
|
||||
promise.addResult(42);
|
||||
promise.reportFinished(); // notifies QFuture that the computation is finished
|
||||
}, std::move(promise)));
|
||||
|
Loading…
x
Reference in New Issue
Block a user