From 1a5cc8d13d0d348a571cab0d24dc814b896c8db7 Mon Sep 17 00:00:00 2001 From: Sona Kurazyan Date: Tue, 5 May 2020 17:44:47 +0200 Subject: Add support of cancellation handler callbacks to QFuture Added QFuture::onCanceled() method, for attaching handlers to be called when the QFuture gets canceled. Change-Id: I1f01647d6173ba0c1db6641e14140108b33ac7c4 Reviewed-by: Leena Miettinen Reviewed-by: Fabian Kosmale --- tests/auto/corelib/thread/qfuture/tst_qfuture.cpp | 120 +++++++++++++++++++--- 1 file changed, 104 insertions(+), 16 deletions(-) (limited to 'tests') diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index f61aa1361e..a7f308de59 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -131,6 +131,7 @@ private slots: void onFailedTestCallables(); void onFailedForMoveOnlyTypes(); #endif + void onCanceled(); void takeResults(); void takeResult(); void runAndTake(); @@ -1933,18 +1934,24 @@ void tst_QFuture::thenForMoveOnlyTypes() QVERIFY(runThenForMoveOnly([] { return std::make_unique(42); })); } +template +QFuture createCanceledFuture() +{ + QFutureInterface promise; + promise.reportStarted(); + promise.reportCanceled(); + promise.reportFinished(); + return promise.future(); +} + void tst_QFuture::thenOnCanceledFuture() { // Continuations on a canceled future { - QFutureInterface promise; - promise.reportStarted(); - promise.reportCanceled(); - promise.reportFinished(); - int thenResult = 0; - QFuture then = - promise.future().then([&]() { ++thenResult; }).then([&]() { ++thenResult; }); + QFuture then = createCanceledFuture().then([&]() { ++thenResult; }).then([&]() { + ++thenResult; + }); QVERIFY(then.isCanceled()); QCOMPARE(thenResult, 0); @@ -1970,16 +1977,10 @@ void tst_QFuture::thenOnCanceledFuture() // Continuations on a canceled future { - QFutureInterface promise; - promise.reportStarted(); - promise.reportCanceled(); - promise.reportFinished(); - int thenResult = 0; - QFuture then = - promise.future().then(QtFuture::Launch::Async, [&]() { ++thenResult; }).then([&]() { - ++thenResult; - }); + QFuture then = createCanceledFuture() + .then(QtFuture::Launch::Async, [&]() { ++thenResult; }) + .then([&]() { ++thenResult; }); QVERIFY(then.isCanceled()); QCOMPARE(thenResult, 0); @@ -2486,6 +2487,15 @@ void tst_QFuture::onFailed() QCOMPARE(checkpoint, 3); QCOMPARE(res, 0); } + + // onFailed on a canceled future + { + auto future = createCanceledFuture() + .then([](int) { return 42; }) + .onCanceled([] { return -1; }) + .onFailed([] { return -2; }); + QCOMPARE(future.result(), -1); + } } template @@ -2565,6 +2575,84 @@ void tst_QFuture::onFailedForMoveOnlyTypes() #endif // QT_NO_EXCEPTIONS +void tst_QFuture::onCanceled() +{ + // Canceled int future + { + auto future = createCanceledFuture().then([](int) { return 42; }).onCanceled([] { + return -1; + }); + QCOMPARE(future.result(), -1); + } + + // Canceled void future + { + int checkpoint = 0; + auto future = createCanceledFuture().then([&] { checkpoint = 42; }).onCanceled([&] { + checkpoint = -1; + }); + QCOMPARE(checkpoint, -1); + } + + // onCanceled propagates result + { + QFutureInterface promise; + auto future = + promise.future().then([](int res) { return res; }).onCanceled([] { return -1; }); + + promise.reportStarted(); + promise.reportResult(42); + promise.reportFinished(); + QCOMPARE(future.result(), 42); + } + + // onCanceled propagates move-only result + { + QFutureInterface promise; + auto future = promise.future().then([](UniquePtr res) { return res; }).onCanceled([] { + return std::make_unique(-1); + }); + + promise.reportStarted(); + promise.reportAndMoveResult(std::make_unique(42)); + promise.reportFinished(); + QCOMPARE(*future.takeResult(), 42); + } + +#ifndef QT_NO_EXCEPTIONS + // onCanceled propagates exceptions + { + QFutureInterface promise; + auto future = promise.future() + .then([](int res) { + throw std::runtime_error("error"); + return res; + }) + .onCanceled([] { return 2; }) + .onFailed([] { return 3; }); + + promise.reportStarted(); + promise.reportResult(1); + promise.reportFinished(); + QCOMPARE(future.result(), 3); + } + + // onCanceled throws + { + auto future = createCanceledFuture() + .then([](int) { return 42; }) + .onCanceled([] { + throw std::runtime_error("error"); + return -1; + }) + .onFailed([] { return -2; }); + + QCOMPARE(future.result(), -2); + } + +#endif // QT_NO_EXCEPTIONS +} + void tst_QFuture::testSingleResult(const UniquePtr &p) { QVERIFY(p.get() != nullptr); -- cgit v1.2.3