From 1da08ebfe267313015c201fd1106f891af554e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Vr=C3=A1til?= Date: Fri, 20 Feb 2015 13:13:56 +0100 Subject: Async: allow Async::start() to have input value The initial value can be passed in as argument to Job::exec(), or by another job in case of job chaining. --- async/autotests/asynctest.cpp | 22 ++++++++++++++++ async/src/async.h | 58 ++++++++++++++++++++++++++++++++----------- 2 files changed, 66 insertions(+), 14 deletions(-) (limited to 'async') diff --git a/async/autotests/asynctest.cpp b/async/autotests/asynctest.cpp index 4ebe65e..ed550ca 100644 --- a/async/autotests/asynctest.cpp +++ b/async/autotests/asynctest.cpp @@ -25,6 +25,7 @@ #include #include #include +#include class AsyncTest : public QObject { @@ -42,6 +43,8 @@ private Q_SLOTS: void testAsyncPromises(); void testAsyncPromises2(); void testNestedAsync(); + void testStartValue(); + void testAsyncThen(); void testSyncThen(); void testAsyncEach(); @@ -52,6 +55,8 @@ private Q_SLOTS: }; + + void AsyncTest::testSyncPromises() { auto baseJob = Async::start( @@ -160,6 +165,23 @@ void AsyncTest::testNestedAsync() QTRY_VERIFY(done); } +void AsyncTest::testStartValue() +{ + auto job = Async::start( + [](int in, Async::Future &future) { + future.setValue(in); + future.setFinished(); + }); + + auto future = job.exec(42); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), 42); +} + + + + + void AsyncTest::testAsyncThen() { auto job = Async::start( diff --git a/async/src/async.h b/async/src/async.h index 1f44f10..386722a 100644 --- a/async/src/async.h +++ b/async/src/async.h @@ -31,6 +31,7 @@ #include #include +#include /* * TODO: instead of passing the future objects callbacks could be provided for result reporting (we can still use the future object internally @@ -44,6 +45,7 @@ class JobBase; template class Job; + template using ThenTask = typename detail::identity&)>>::type; template @@ -71,6 +73,9 @@ class ExecutorBase template friend class Executor; + template + friend class Async::Job; + public: virtual ~ExecutorBase(); virtual void exec() = 0; @@ -178,8 +183,11 @@ private: * void return type, and accept exactly one argument of type @p Async::Future, * where @p In is type of the result. */ -template -Job start(ThenTask func); +template +Job start(ThenTask func); + +template +Job start(SyncThenTask func); /** @@ -262,11 +270,11 @@ class Job : public JobBase template friend class Job; - template - friend Job start(Async::ThenTask func); + template + friend Job start(Async::ThenTask func); - template - friend Job start(Async::SyncThenTask func); + template + friend Job start(Async::SyncThenTask func); public: template @@ -315,6 +323,27 @@ public: new Private::SyncReduceExecutor(func, errorFunc, mExecutor))); } + template + Async::Future exec(FirstIn in) + { + // Inject a fake sync executor that will return the initial value + Private::ExecutorBasePtr first = mExecutor; + while (first->mPrev) { + first = first->mPrev; + } + auto init = new Private::SyncThenExecutor( + [in]() -> FirstIn { + return in; + }, + ErrorHandler(), Private::ExecutorBasePtr()); + first->mPrev = Private::ExecutorBasePtr(init); + + auto result = exec(); + // Remove the injected executor + first->mPrev.reset(); + return result; + } + Async::Future exec() { mExecutor->exec(); @@ -357,18 +386,18 @@ private: namespace Async { -template -Job start(ThenTask func) +template +Job start(ThenTask func) { - return Job(Private::ExecutorBasePtr( - new Private::ThenExecutor(func, ErrorHandler(), Private::ExecutorBasePtr()))); + return Job(Private::ExecutorBasePtr( + new Private::ThenExecutor(func, ErrorHandler(), Private::ExecutorBasePtr()))); } -template -Job start(SyncThenTask func) +template +Job start(SyncThenTask func) { - return Job(Private::ExecutorBasePtr( - new Private::SyncThenExecutor(func, ErrorHandler(), Private::ExecutorBasePtr()))); + return Job(Private::ExecutorBasePtr( + new Private::SyncThenExecutor(func, ErrorHandler(), Private::ExecutorBasePtr()))); } template @@ -443,6 +472,7 @@ void Executor::exec() } } + template ThenExecutor::ThenExecutor(ThenTask then, ErrorHandler error, const ExecutorBasePtr &parent) : Executor::type, Out, In ...>(error, parent) -- cgit v1.2.3