diff --git a/README.md b/README.md index d6f0043..dfc37f9 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,11 @@ QFuture f1 = QtConcurrent::run(readImage, QString("image.jpg")); QFuture f2 = observe(timer, &QTimer::timeout).future(); -(combine() << f1 << f2).subscribe([](QVariantList result){ - // Read an image - // result[0] = QImage - qDebug() << result; -}); +QFuture result = (combine() << f1 << f2).subscribe([=](){ + // Read an image but do not return before timeout + return f1.result(); +}).future(); + ``` **3. Advanced multi-threading model** diff --git a/asyncfuture.h b/asyncfuture.h index 41d5899..923bee9 100644 --- a/asyncfuture.h +++ b/asyncfuture.h @@ -4,7 +4,6 @@ #include #include #include -#include #include namespace AsyncFuture { @@ -241,23 +240,9 @@ class DeferredFuture : public QObject, public QFutureInterface{ }; -// Obtain the result of future in QVariant. -// It is used within Combinator only as other component do not -// require to register QMetaType -template -inline QVariant obtainFutureResult(QFuture future) { - return future.result(); -} - -template <> -inline QVariant obtainFutureResult(QFuture future) { - Q_UNUSED(future); - return QVariant(); -} - -class CombinedFuture: public DeferredFuture { +class CombinedFuture: public DeferredFuture { public: - CombinedFuture(bool settleAllMode = false) : DeferredFuture(), settleAllMode(settleAllMode) { + CombinedFuture(bool settleAllMode = false) : DeferredFuture(), settleAllMode(settleAllMode) { settledCount = 0; count = 0; anyCanceled = false; @@ -269,12 +254,11 @@ class CombinedFuture: public DeferredFuture { return; } int index = count++; - results << QVariant(); incRefCount(); Private::watch(future, this, [=]() { - completeFutureAt(index, future); + completeFutureAt(index); decRefCount(); },[=]() { cancelFutureAt(index); @@ -286,7 +270,6 @@ class CombinedFuture: public DeferredFuture { int count; bool anyCanceled; bool settleAllMode; - QVariantList results; static QSharedPointer create(bool settleAllMode) { @@ -306,10 +289,9 @@ class CombinedFuture: public DeferredFuture { private: - template - void completeFutureAt(int index, QFuture future) { + void completeFutureAt(int index) { + Q_UNUSED(index); settledCount++; - results[index] = Private::obtainFutureResult(future); checkFulfilled(); } @@ -334,7 +316,7 @@ class CombinedFuture: public DeferredFuture { if (anyCanceled) { cancel(); } else { - complete(results); + complete(); } } } @@ -492,6 +474,9 @@ void>::type voidInvoke(Functor functor, QFuture future) { Q_UNUSED(future); functor(); + /* Toubleshooting: + * 1) Are you observing a QFuture but require an input argument in your callback function? + */ } template @@ -706,12 +691,12 @@ class Deferred : public Observable { QSharedPointer > defer; }; -class Combinator : public Observable { +class Combinator : public Observable { private: QSharedPointer combinedFuture; public: - inline Combinator(bool settleAllMode = false) : Observable() { + inline Combinator(bool settleAllMode = false) : Observable() { combinedFuture = Private::CombinedFuture::create(settleAllMode); m_future = combinedFuture->future(); } diff --git a/tests/asyncfutureunittests/asyncfuturetests.cpp b/tests/asyncfutureunittests/asyncfuturetests.cpp index dbe27a0..ec63f1b 100644 --- a/tests/asyncfutureunittests/asyncfuturetests.cpp +++ b/tests/asyncfutureunittests/asyncfuturetests.cpp @@ -674,66 +674,55 @@ void AsyncFutureTests::test_Combinator() auto d1 = deferred(); auto d2 = deferred(); auto d3 = deferred(); + auto c = Callable(); auto combinator = combine(); combinator << d1.future() << d2.future() << d3.future(); - QFuture future = combinator.future(); - QVariantList results; + QFuture future = combinator.future(); - observe(future).subscribe([&](QVariantList value) { - results = value; - }); + observe(future).subscribe(c.func); d1.complete(1); d2.complete("second"); d3.complete(); - QCOMPARE(results.isEmpty(), true); + QCOMPARE(c.called, false); QCOMPARE(future.isFinished(), false); QVERIFY(waitUntil(future,1000)); + QCOMPARE(c.called, true); QCOMPARE(future.isFinished(), true); - - QCOMPARE(results.size(), 3); - QVERIFY(results[0] == 1); - QVERIFY(results[1] == "second"); } { // case: all completed (but Combinator was destroyed ) - QFuture future ; + QFuture future ; auto d1 = deferred(); auto d2 = deferred(); auto d3 = deferred(); + auto c = Callable(); { future = (combine() << d1.future() << d2.future() << d3.future()).future(); } - QVariantList results; - - observe(future).subscribe([&](QVariantList value) { - results = value; - }); + observe(future).subscribe(c.func); d1.complete(1); d2.complete("second"); d3.complete(); - QCOMPARE(results.isEmpty(), true); + QCOMPARE(c.called, false); QCOMPARE(future.isFinished(), false); QVERIFY(waitUntil(future,1000)); QCOMPARE(future.isFinished(), true); - - QCOMPARE(results.size(), 3); - QVERIFY(results[0] == 1); - QVERIFY(results[1] == "second"); + QCOMPARE(c.called, true); } { @@ -745,7 +734,7 @@ void AsyncFutureTests::test_Combinator() auto combinator = combine(); combinator << d1.future() << d2.future() << d3.future(); - QFuture future = combinator.future(); + QFuture future = combinator.future(); Callable canceled; @@ -770,9 +759,9 @@ void AsyncFutureTests::test_Combinator() auto combinator = combine(true); combinator << d1.future() << d2.future() << d3.future(); - QFuture future = combinator.future(); + QFuture future = combinator.future(); - Callable completed; + Callable completed; Callable canceled; observe(future).subscribe(completed.func, canceled.func); @@ -824,10 +813,6 @@ void AsyncFutureTests::test_Combinator_add_to_already_finished() d4.complete(true); QVERIFY(waitUntil(copy.future(), 1000)); // It is already resolved - QVERIFY(copy.future().isResultReadyAt(0)); - QVariantList result = copy.future().result(); - QCOMPARE(result.size(), 3); - } } diff --git a/tests/asyncfutureunittests/example.cpp b/tests/asyncfutureunittests/example.cpp index 31cd1f0..469c361 100644 --- a/tests/asyncfutureunittests/example.cpp +++ b/tests/asyncfutureunittests/example.cpp @@ -63,15 +63,14 @@ void Example::example_combine_multiple_future() QFuture f2 = observe(timer, &QTimer::timeout).future(); - (combine() << f1 << f2).subscribe([](QVariantList result){ - // result[0] = QImage - qDebug() << result; - }); + QFuture result = (combine() << f1 << f2).subscribe([=](){ + // Read an image but do not return before timeout + return f1.result(); + }).future(); timer->start(); - waitUntil(f1); - waitUntil(f2); + QVERIFY(waitUntil(result, 1000)); timer->deleteLater(); }