From 65e5a6ac8848750e94e35ec65ac37d0d4a8638cd Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Mon, 19 Jan 2015 19:22:16 +0100 Subject: Async: Error continuation. --- async/autotests/asynctest.cpp | 21 +++++++++++++++++++++ async/src/async.h | 26 ++++++++++++++++++++------ async/src/future.h | 18 ++++++++++++++++++ 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/async/autotests/asynctest.cpp b/async/autotests/asynctest.cpp index 1ee3843..6c4bbeb 100644 --- a/async/autotests/asynctest.cpp +++ b/async/autotests/asynctest.cpp @@ -44,6 +44,7 @@ private Q_SLOTS: void testNestedAsync(); void testSyncEach(); void testSyncReduce(); + void testErrorHandler(); }; void AsyncTest::testSyncPromises() @@ -195,6 +196,26 @@ void AsyncTest::testSyncReduce() QCOMPARE(future.value(), 10); } +void AsyncTest::testErrorHandler() +{ + int error = 0; + auto job = Async::start( + [](Async::Future &f) { + f.setError(1, "error"); + }) + .then( + [](int v, Async::Future &f) { + f.setFinished(); + }, + [&error](int errorCode, const QString &errorMessage) { + error = errorCode; + } + ); + auto future = job.exec(); + future.waitForFinished(); + QVERIFY(error == 1); + QVERIFY(future.isFinished()); +} QTEST_MAIN(AsyncTest); diff --git a/async/src/async.h b/async/src/async.h index 8fee0bc..e4b06a9 100644 --- a/async/src/async.h +++ b/async/src/async.h @@ -47,6 +47,7 @@ template using EachTask = typename detail::identity&)>>::type; template using ReduceTask = typename detail::identity&)>>::type; +using ErrorHandler = std::function; namespace Private { @@ -93,6 +94,7 @@ protected: void exec(); std::function &)> mFunc; + std::function mErrorFunc; Async::Future *mPrevFuture; Async::FutureWatcher *mPrevFutureWatcher; }; @@ -101,7 +103,7 @@ template class ThenExecutor: public Executor::type, Out, In ...> { public: - ThenExecutor(ThenTask then, ExecutorBase *parent = nullptr); + ThenExecutor(ThenTask then, ErrorHandler errorHandler = ErrorHandler(), ExecutorBase *parent = nullptr); void previousFutureReady(); private: @@ -221,9 +223,9 @@ class Job : public JobBase public: template - Job then(ThenTask func) + Job then(ThenTask func, ErrorHandler errorFunc = ErrorHandler()) { - return Job(new Private::ThenExecutor(func, mExecutor)); + return Job(new Private::ThenExecutor(func, errorFunc, mExecutor)); } template @@ -309,10 +311,11 @@ void Executor::exec() } template -ThenExecutor::ThenExecutor(ThenTask then, ExecutorBase* parent) +ThenExecutor::ThenExecutor(ThenTask then, ErrorHandler error, ExecutorBase* parent) : Executor::type, Out, In ...>(parent) { this->mFunc = then; + this->mErrorFunc = error; } template @@ -321,8 +324,19 @@ void ThenExecutor::previousFutureReady() if (this->mPrevFuture) { assert(this->mPrevFuture->isFinished()); } - this->mFunc(this->mPrevFuture ? this->mPrevFuture->value() : In() ..., - *static_cast*>(this->mResult)); + if (this->mPrevFuture && this->mPrevFuture->errorCode()) { + if (this->mErrorFunc) { + this->mErrorFunc(this->mPrevFuture->errorCode(), this->mPrevFuture->errorMessage()); + } else { + static_cast*>(this->mResult)->setError(this->mPrevFuture->errorCode(), this->mPrevFuture->errorMessage()); + //propagate error if no error handler is available + this->mFunc(this->mPrevFuture ? this->mPrevFuture->value() : In() ..., + *static_cast*>(this->mResult)); + } + } else { + this->mFunc(this->mPrevFuture ? this->mPrevFuture->value() : In() ..., + *static_cast*>(this->mResult)); + } } template diff --git a/async/src/future.h b/async/src/future.h index 54580ad..098f6e8 100644 --- a/async/src/future.h +++ b/async/src/future.h @@ -36,6 +36,7 @@ public: virtual void setFinished() = 0; virtual bool isFinished() const = 0; + virtual void setError(int code = 1, const QString &message = QString()) = 0; protected: FutureBase(); @@ -69,6 +70,23 @@ public: return d->finished; } + void setError(int errorCode, const QString &message) + { + d->errorCode = errorCode; + d->errorMessage = message; + setFinished(); + } + + int errorCode() const + { + return d->errorCode; + } + + QString errorMessage() const + { + return d->errorMessage; + } + void waitForFinished() { if (isFinished()) { -- cgit v1.2.3