QtConcurrent: Provide a test for runWithPromise with handlers
Test runWithPromise with "then" and "onCanceled" handlers. Test the case when QFuture::cancel() is being called when the task's thread already started, so that a call to QPromise::isCanceled() from inside the running thread returns different values in the same task's run. This nicely proves that communication between QFuture and QPromise works between different threads. Task-number: QTBUG-84868 Change-Id: Icb2e0b1f99e2dcd919d881515f1ccd08e2f25b8c Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
cde42e2f76
commit
cc0be95ac7
@ -26,8 +26,11 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
#include <qtconcurrentrun.h>
|
||||
#include <qfuture.h>
|
||||
#include <QFuture>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QString>
|
||||
#include <QWaitCondition>
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
using namespace QtConcurrent;
|
||||
@ -55,6 +58,7 @@ private slots:
|
||||
void callableObjectWithState();
|
||||
void withPromise();
|
||||
void withPromiseInThreadPool();
|
||||
void withPromiseAndThen();
|
||||
void moveOnlyType();
|
||||
void crefFunction();
|
||||
void customPromise();
|
||||
@ -1346,6 +1350,111 @@ void tst_QtConcurrentRun::withPromiseInThreadPool()
|
||||
QList<QString>({QString(QLatin1String("rvalue"))}));
|
||||
}
|
||||
|
||||
void tst_QtConcurrentRun::withPromiseAndThen()
|
||||
{
|
||||
bool runExecuted = false;
|
||||
bool cancelReceivedBeforeSync = false;
|
||||
bool cancelReceivedAfterSync = false;
|
||||
|
||||
bool syncBegin = false;
|
||||
bool syncEnd = false;
|
||||
|
||||
QMutex mutex;
|
||||
QWaitCondition condition;
|
||||
|
||||
auto reset = [&]() {
|
||||
runExecuted = false;
|
||||
cancelReceivedBeforeSync = false;
|
||||
cancelReceivedAfterSync = false;
|
||||
syncBegin = false;
|
||||
syncEnd = false;
|
||||
};
|
||||
|
||||
auto setFlag = [&mutex, &condition] (bool &flag) {
|
||||
QMutexLocker locker(&mutex);
|
||||
flag = true;
|
||||
condition.wakeOne();
|
||||
};
|
||||
|
||||
auto waitForFlag = [&mutex, &condition] (const bool &flag) {
|
||||
QMutexLocker locker(&mutex);
|
||||
while (!flag)
|
||||
condition.wait(&mutex);
|
||||
};
|
||||
|
||||
auto report1WithCancel = [&](QPromise<int> &promise) {
|
||||
runExecuted = true;
|
||||
cancelReceivedBeforeSync = promise.isCanceled();
|
||||
|
||||
setFlag(syncBegin);
|
||||
waitForFlag(syncEnd);
|
||||
|
||||
cancelReceivedAfterSync = promise.isCanceled();
|
||||
if (cancelReceivedAfterSync)
|
||||
return;
|
||||
promise.addResult(1);
|
||||
};
|
||||
|
||||
{
|
||||
auto future = run(report1WithCancel);
|
||||
|
||||
waitForFlag(syncBegin);
|
||||
future.cancel();
|
||||
setFlag(syncEnd);
|
||||
|
||||
future.waitForFinished();
|
||||
QCOMPARE(future.results().count(), 0);
|
||||
QVERIFY(runExecuted);
|
||||
QVERIFY(!cancelReceivedBeforeSync);
|
||||
QVERIFY(cancelReceivedAfterSync);
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
{
|
||||
bool thenExecuted = false;
|
||||
bool cancelExecuted = false;
|
||||
auto future = run(report1WithCancel);
|
||||
auto resultFuture = future.then(QtFuture::Launch::Async, [&](int) { thenExecuted = true; })
|
||||
.onCanceled([&]() { cancelExecuted = true; });
|
||||
|
||||
waitForFlag(syncBegin);
|
||||
// no cancel this time
|
||||
setFlag(syncEnd);
|
||||
|
||||
resultFuture.waitForFinished();
|
||||
QCOMPARE(future.results().count(), 1);
|
||||
QCOMPARE(future.result(), 1);
|
||||
QVERIFY(runExecuted);
|
||||
QVERIFY(thenExecuted);
|
||||
QVERIFY(!cancelExecuted);
|
||||
QVERIFY(!cancelReceivedBeforeSync);
|
||||
QVERIFY(!cancelReceivedAfterSync);
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
{
|
||||
bool thenExecuted = false;
|
||||
bool cancelExecuted = false;
|
||||
auto future = run(report1WithCancel);
|
||||
auto resultFuture = future.then(QtFuture::Launch::Async, [&](int) { thenExecuted = true; })
|
||||
.onCanceled([&]() { cancelExecuted = true; });
|
||||
|
||||
waitForFlag(syncBegin);
|
||||
future.cancel();
|
||||
setFlag(syncEnd);
|
||||
|
||||
resultFuture.waitForFinished();
|
||||
QCOMPARE(future.results().count(), 0);
|
||||
QVERIFY(runExecuted);
|
||||
QVERIFY(!thenExecuted);
|
||||
QVERIFY(cancelExecuted);
|
||||
QVERIFY(!cancelReceivedBeforeSync);
|
||||
QVERIFY(cancelReceivedAfterSync);
|
||||
}
|
||||
}
|
||||
|
||||
class MoveOnlyType
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user