From cc0be95ac782c9cf0bf994d0af6e2966cf29f8fa Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 29 Sep 2020 16:50:01 +0200 Subject: QtConcurrent: Provide a test for runWithPromise with handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Sona Kurazyan Reviewed-by: MÃ¥rten Nordheim --- .../qtconcurrentrun/tst_qtconcurrentrun.cpp | 111 ++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp index 1132954a82..01b7c1b895 100644 --- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp +++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp @@ -26,8 +26,11 @@ ** ****************************************************************************/ #include -#include +#include +#include +#include #include +#include #include 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(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 &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: -- cgit v1.2.3