From e0ba51543037a026e2a8d483dfdc0e196e9dc59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Vr=C3=A1til?= Date: Thu, 11 Dec 2014 16:09:28 +0100 Subject: Async: add Reduce task --- async/autotests/asynctest.cpp | 50 ++++++++++++++++++++++++++++++++----------- async/src/async.h | 44 ++++++++++++++++++++++++++++--------- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/async/autotests/asynctest.cpp b/async/autotests/asynctest.cpp index 403fb83..7aedfc4 100644 --- a/async/autotests/asynctest.cpp +++ b/async/autotests/asynctest.cpp @@ -41,6 +41,7 @@ private Q_SLOTS: void testSyncPromises(); void testAsyncPromises(); void testSyncEach(); + void testSyncReduce(); }; void AsyncTest::testSyncPromises() @@ -65,27 +66,29 @@ void AsyncTest::testSyncPromises() job.exec(); Async::Future future = job.result(); + QVERIFY(future.isFinished()); QCOMPARE(future.value(), QString::fromLatin1("RESULT IS 42")); } void AsyncTest::testAsyncPromises() { auto job = Async::start( - [](Async::Future &future) { - QTimer *timer = new QTimer(); - QObject::connect(timer, &QTimer::timeout, - [&]() { - future.setValue(42); - future.setFinished(); - }); - QObject::connect(timer, &QTimer::timeout, - timer, &QObject::deleteLater); - timer->setSingleShot(true); - timer->start(200); - }); + [](Async::Future &future) { + QTimer *timer = new QTimer(); + QObject::connect(timer, &QTimer::timeout, + [&]() { + future.setValue(42); + future.setFinished(); + }); + QObject::connect(timer, &QTimer::timeout, + timer, &QObject::deleteLater); + timer->setSingleShot(true); + timer->start(200); + }); job.exec(); Async::Future future = job.result(); + QVERIFY(future.isFinished()); QCOMPARE(future.value(), 42); } @@ -105,9 +108,32 @@ void AsyncTest::testSyncEach() job.exec(); Async::Future> future = job.result(); const QList expected({ 2, 3, 4, 5 }); + QVERIFY(future.isFinished()); QCOMPARE(future.value(), expected); } +void AsyncTest::testSyncReduce() +{ + auto job = Async::start>( + [](Async::Future> &future) { + future.setValue(QList{ 1, 2, 3, 4 }); + future.setFinished(); + }) + .reduce>( + [](const QList &list, Async::Future &future) { + int sum = 0; + for (int i : list) sum += i; + future.setValue(sum); + future.setFinished(); + }); + + job.exec(); + Async::Future future = job.result(); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), 10); +} + + QTEST_MAIN(AsyncTest); diff --git a/async/src/async.h b/async/src/async.h index 0f027f5..a976fa2 100644 --- a/async/src/async.h +++ b/async/src/async.h @@ -80,10 +80,6 @@ template class ThenExecutor: public Executor { - typedef Out OutType; - typedef typename std::tuple_element<0, std::tuple>::type InType; - - public: ThenExecutor(ThenTask then, Executor *parent = nullptr) : Executor(parent) @@ -93,10 +89,12 @@ public: void exec() { - Async::Future *in = 0; + typedef typename std::tuple_element<0, std::tuple>::type PrevOut; + + Async::Future *in = 0; if (mPrev) { mPrev->exec(); - in = static_cast*>(mPrev->result()); + in = static_cast*>(mPrev->result()); assert(in->isFinished()); } @@ -133,6 +131,7 @@ public: future.waitForFinished(); out->setValue(out->value() + future.value()); } + out->setFinished(); mResult = out; } @@ -141,6 +140,32 @@ private: std::function&)> mFunc; }; +template +class ReduceExecutor : public Executor +{ +public: + ReduceExecutor(ReduceTask reduce, Executor *parent = nullptr) + : Executor(parent) + , mFunc(reduce) + { + } + + void exec() + { + assert(mPrev); + mPrev->exec(); + Async::Future *in = static_cast*>(mPrev->result()); + + auto out = new Async::Future(); + mFunc(in->value(), *out); + out->waitForFinished(); + mResult = out; + } + +private: + std::function &)> mFunc; +}; + class JobBase { template @@ -187,8 +212,8 @@ public: Job reduce(ReduceTask func) { static_assert(Async::detail::isIterable::value, - "The result type of 'Reduce' task must be a list or an array."); - //return Job::create(func, new ReduceEx, this); + "The 'Result' task can only be connected to a job that returns a list or array"); + return Job(new ReduceExecutor(func, mExecutor)); } Async::Future result() const @@ -212,8 +237,7 @@ private: template Async::Job Async::start(ThenTask func) { - Executor *exec = new ThenExecutor(func); - return Job(exec); + return Job(new ThenExecutor(func)); } #endif // ASYNC_H -- cgit v1.2.3