summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--async/autotests/asynctest.cpp21
-rw-r--r--async/src/async.h26
-rw-r--r--async/src/future.h18
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:
44 void testNestedAsync(); 44 void testNestedAsync();
45 void testSyncEach(); 45 void testSyncEach();
46 void testSyncReduce(); 46 void testSyncReduce();
47 void testErrorHandler();
47}; 48};
48 49
49void AsyncTest::testSyncPromises() 50void AsyncTest::testSyncPromises()
@@ -195,6 +196,26 @@ void AsyncTest::testSyncReduce()
195 QCOMPARE(future.value(), 10); 196 QCOMPARE(future.value(), 10);
196} 197}
197 198
199void AsyncTest::testErrorHandler()
200{
201 int error = 0;
202 auto job = Async::start<int>(
203 [](Async::Future<int> &f) {
204 f.setError(1, "error");
205 })
206 .then<int, int>(
207 [](int v, Async::Future<int> &f) {
208 f.setFinished();
209 },
210 [&error](int errorCode, const QString &errorMessage) {
211 error = errorCode;
212 }
213 );
214 auto future = job.exec();
215 future.waitForFinished();
216 QVERIFY(error == 1);
217 QVERIFY(future.isFinished());
218}
198 219
199 220
200QTEST_MAIN(AsyncTest); 221QTEST_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<typename Out, typename In>
47using EachTask = typename detail::identity<std::function<void(In, Async::Future<Out>&)>>::type; 47using EachTask = typename detail::identity<std::function<void(In, Async::Future<Out>&)>>::type;
48template<typename Out, typename In> 48template<typename Out, typename In>
49using ReduceTask = typename detail::identity<std::function<void(In, Async::Future<Out>&)>>::type; 49using ReduceTask = typename detail::identity<std::function<void(In, Async::Future<Out>&)>>::type;
50using ErrorHandler = std::function<void(int, const QString &)>;
50 51
51namespace Private 52namespace Private
52{ 53{
@@ -93,6 +94,7 @@ protected:
93 void exec(); 94 void exec();
94 95
95 std::function<void(const In& ..., Async::Future<Out> &)> mFunc; 96 std::function<void(const In& ..., Async::Future<Out> &)> mFunc;
97 std::function<void(int, const QString &)> mErrorFunc;
96 Async::Future<PrevOut> *mPrevFuture; 98 Async::Future<PrevOut> *mPrevFuture;
97 Async::FutureWatcher<PrevOut> *mPrevFutureWatcher; 99 Async::FutureWatcher<PrevOut> *mPrevFutureWatcher;
98}; 100};
@@ -101,7 +103,7 @@ template<typename Out, typename ... In>
101class ThenExecutor: public Executor<typename PreviousOut<In ...>::type, Out, In ...> 103class ThenExecutor: public Executor<typename PreviousOut<In ...>::type, Out, In ...>
102{ 104{
103public: 105public:
104 ThenExecutor(ThenTask<Out, In ...> then, ExecutorBase *parent = nullptr); 106 ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler errorHandler = ErrorHandler(), ExecutorBase *parent = nullptr);
105 void previousFutureReady(); 107 void previousFutureReady();
106 108
107private: 109private:
@@ -221,9 +223,9 @@ class Job : public JobBase
221 223
222public: 224public:
223 template<typename OutOther, typename ... InOther> 225 template<typename OutOther, typename ... InOther>
224 Job<OutOther, InOther ...> then(ThenTask<OutOther, InOther ...> func) 226 Job<OutOther, InOther ...> then(ThenTask<OutOther, InOther ...> func, ErrorHandler errorFunc = ErrorHandler())
225 { 227 {
226 return Job<OutOther, InOther ...>(new Private::ThenExecutor<OutOther, InOther ...>(func, mExecutor)); 228 return Job<OutOther, InOther ...>(new Private::ThenExecutor<OutOther, InOther ...>(func, errorFunc, mExecutor));
227 } 229 }
228 230
229 template<typename OutOther, typename InOther> 231 template<typename OutOther, typename InOther>
@@ -309,10 +311,11 @@ void Executor<PrevOut, Out, In ...>::exec()
309} 311}
310 312
311template<typename Out, typename ... In> 313template<typename Out, typename ... In>
312ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ExecutorBase* parent) 314ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler error, ExecutorBase* parent)
313 : Executor<typename PreviousOut<In ...>::type, Out, In ...>(parent) 315 : Executor<typename PreviousOut<In ...>::type, Out, In ...>(parent)
314{ 316{
315 this->mFunc = then; 317 this->mFunc = then;
318 this->mErrorFunc = error;
316} 319}
317 320
318template<typename Out, typename ... In> 321template<typename Out, typename ... In>
@@ -321,8 +324,19 @@ void ThenExecutor<Out, In ...>::previousFutureReady()
321 if (this->mPrevFuture) { 324 if (this->mPrevFuture) {
322 assert(this->mPrevFuture->isFinished()); 325 assert(this->mPrevFuture->isFinished());
323 } 326 }
324 this->mFunc(this->mPrevFuture ? this->mPrevFuture->value() : In() ..., 327 if (this->mPrevFuture && this->mPrevFuture->errorCode()) {
325 *static_cast<Async::Future<Out>*>(this->mResult)); 328 if (this->mErrorFunc) {
329 this->mErrorFunc(this->mPrevFuture->errorCode(), this->mPrevFuture->errorMessage());
330 } else {
331 static_cast<Async::Future<Out>*>(this->mResult)->setError(this->mPrevFuture->errorCode(), this->mPrevFuture->errorMessage());
332 //propagate error if no error handler is available
333 this->mFunc(this->mPrevFuture ? this->mPrevFuture->value() : In() ...,
334 *static_cast<Async::Future<Out>*>(this->mResult));
335 }
336 } else {
337 this->mFunc(this->mPrevFuture ? this->mPrevFuture->value() : In() ...,
338 *static_cast<Async::Future<Out>*>(this->mResult));
339 }
326} 340}
327 341
328template<typename PrevOut, typename Out, typename In> 342template<typename PrevOut, typename Out, typename In>
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:
36 36
37 virtual void setFinished() = 0; 37 virtual void setFinished() = 0;
38 virtual bool isFinished() const = 0; 38 virtual bool isFinished() const = 0;
39 virtual void setError(int code = 1, const QString &message = QString()) = 0;
39 40
40protected: 41protected:
41 FutureBase(); 42 FutureBase();
@@ -69,6 +70,23 @@ public:
69 return d->finished; 70 return d->finished;
70 } 71 }
71 72
73 void setError(int errorCode, const QString &message)
74 {
75 d->errorCode = errorCode;
76 d->errorMessage = message;
77 setFinished();
78 }
79
80 int errorCode() const
81 {
82 return d->errorCode;
83 }
84
85 QString errorMessage() const
86 {
87 return d->errorMessage;
88 }
89
72 void waitForFinished() 90 void waitForFinished()
73 { 91 {
74 if (isFinished()) { 92 if (isFinished()) {