Skip to content
This repository has been archived by the owner on Dec 12, 2023. It is now read-only.

Commit

Permalink
Combinator: Changed the parent type from Observable<QVariantList> to …
Browse files Browse the repository at this point in the history
…Observable<void> and AsyncFuture do not use any QVariant type any more
  • Loading branch information
benlau committed Mar 21, 2017
1 parent f7214c7 commit 0aab059
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 65 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ QFuture<QImage> f1 = QtConcurrent::run(readImage, QString("image.jpg"));
QFuture<void> f2 = observe(timer, &QTimer::timeout).future();
(combine() << f1 << f2).subscribe([](QVariantList result){
// Read an image
// result[0] = QImage
qDebug() << result;
});
QFuture<QImage> result = (combine() << f1 << f2).subscribe([=](){
// Read an image but do not return before timeout
return f1.result();
}).future();
```

**3. Advanced multi-threading model**
Expand Down
37 changes: 11 additions & 26 deletions asyncfuture.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <QPointer>
#include <QThread>
#include <QFutureWatcher>
#include <QVariant>
#include <functional>

namespace AsyncFuture {
Expand Down Expand Up @@ -241,23 +240,9 @@ class DeferredFuture : public QObject, public QFutureInterface<T>{

};

// Obtain the result of future in QVariant.
// It is used within Combinator only as other component do not
// require to register QMetaType
template <typename T>
inline QVariant obtainFutureResult(QFuture<T> future) {
return future.result();
}

template <>
inline QVariant obtainFutureResult<void>(QFuture<void> future) {
Q_UNUSED(future);
return QVariant();
}

class CombinedFuture: public DeferredFuture<QVariantList> {
class CombinedFuture: public DeferredFuture<void> {
public:
CombinedFuture(bool settleAllMode = false) : DeferredFuture<QVariantList>(), settleAllMode(settleAllMode) {
CombinedFuture(bool settleAllMode = false) : DeferredFuture<void>(), settleAllMode(settleAllMode) {
settledCount = 0;
count = 0;
anyCanceled = false;
Expand All @@ -269,12 +254,11 @@ class CombinedFuture: public DeferredFuture<QVariantList> {
return;
}
int index = count++;
results << QVariant();
incRefCount();

Private::watch(future, this,
[=]() {
completeFutureAt(index, future);
completeFutureAt(index);
decRefCount();
},[=]() {
cancelFutureAt(index);
Expand All @@ -286,7 +270,6 @@ class CombinedFuture: public DeferredFuture<QVariantList> {
int count;
bool anyCanceled;
bool settleAllMode;
QVariantList results;

static QSharedPointer<CombinedFuture> create(bool settleAllMode) {

Expand All @@ -306,10 +289,9 @@ class CombinedFuture: public DeferredFuture<QVariantList> {

private:

template <typename T>
void completeFutureAt(int index, QFuture<T> future) {
void completeFutureAt(int index) {
Q_UNUSED(index);
settledCount++;
results[index] = Private::obtainFutureResult(future);
checkFulfilled();
}

Expand All @@ -334,7 +316,7 @@ class CombinedFuture: public DeferredFuture<QVariantList> {
if (anyCanceled) {
cancel();
} else {
complete(results);
complete();
}
}
}
Expand Down Expand Up @@ -492,6 +474,9 @@ void>::type
voidInvoke(Functor functor, QFuture<T> future) {
Q_UNUSED(future);
functor();
/* Toubleshooting:
* 1) Are you observing a QFuture<void> but require an input argument in your callback function?
*/
}

template <typename Functor, typename T>
Expand Down Expand Up @@ -706,12 +691,12 @@ class Deferred<void> : public Observable<void> {
QSharedPointer<Private::DeferredFuture<void> > defer;
};

class Combinator : public Observable<QVariantList> {
class Combinator : public Observable<void> {
private:
QSharedPointer<Private::CombinedFuture> combinedFuture;

public:
inline Combinator(bool settleAllMode = false) : Observable<QVariantList>() {
inline Combinator(bool settleAllMode = false) : Observable<void>() {
combinedFuture = Private::CombinedFuture::create(settleAllMode);
m_future = combinedFuture->future();
}
Expand Down
41 changes: 13 additions & 28 deletions tests/asyncfutureunittests/asyncfuturetests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,66 +674,55 @@ void AsyncFutureTests::test_Combinator()
auto d1 = deferred<int>();
auto d2 = deferred<QString>();
auto d3 = deferred<void>();
auto c = Callable<void>();

auto combinator = combine();
combinator << d1.future() << d2.future() << d3.future();

QFuture<QVariantList> future = combinator.future();
QVariantList results;
QFuture<void> 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<QVariantList> future ;
QFuture<void> future ;

auto d1 = deferred<int>();
auto d2 = deferred<QString>();
auto d3 = deferred<void>();
auto c = Callable<void>();

{
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);
}

{
Expand All @@ -745,7 +734,7 @@ void AsyncFutureTests::test_Combinator()
auto combinator = combine();
combinator << d1.future() << d2.future() << d3.future();

QFuture<QVariantList> future = combinator.future();
QFuture<void> future = combinator.future();

Callable<void> canceled;

Expand All @@ -770,9 +759,9 @@ void AsyncFutureTests::test_Combinator()
auto combinator = combine(true);
combinator << d1.future() << d2.future() << d3.future();

QFuture<QVariantList> future = combinator.future();
QFuture<void> future = combinator.future();

Callable<QVariantList> completed;
Callable<void> completed;
Callable<void> canceled;

observe(future).subscribe(completed.func, canceled.func);
Expand Down Expand Up @@ -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);

}

}
11 changes: 5 additions & 6 deletions tests/asyncfutureunittests/example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,14 @@ void Example::example_combine_multiple_future()

QFuture<void> f2 = observe(timer, &QTimer::timeout).future();

(combine() << f1 << f2).subscribe([](QVariantList result){
// result[0] = QImage
qDebug() << result;
});
QFuture<QImage> 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();
}
Expand Down

0 comments on commit 0aab059

Please sign in to comment.