summaryrefslogtreecommitdiffstats
path: root/async/src/async.h
diff options
context:
space:
mode:
Diffstat (limited to 'async/src/async.h')
-rw-r--r--async/src/async.h58
1 files changed, 28 insertions, 30 deletions
diff --git a/async/src/async.h b/async/src/async.h
index 753a44f..d15373b 100644
--- a/async/src/async.h
+++ b/async/src/async.h
@@ -29,10 +29,12 @@
29 29
30#include <QVector> 30#include <QVector>
31#include <QObject> 31#include <QObject>
32#include <QSharedPointer>
32 33
33 34
34/* 35/*
35 * TODO: on .then and potentially others: support for ThenTask without future argument and return value which makes it implicitly a sync continuation. Useful for typical value consumer continuations. 36 * TODO: on .then and potentially others: support for ThenTask without future argument and return value which makes it implicitly a sync continuation.
37 * Useful for typical value consumer continuations.
36 * TODO: error continuation on .then and others. 38 * TODO: error continuation on .then and others.
37 * TODO: instead of passing the future objects callbacks could be provided for result reporting (we can still use the future object internally 39 * TODO: instead of passing the future objects callbacks could be provided for result reporting (we can still use the future object internally
38 */ 40 */
@@ -57,6 +59,10 @@ using ErrorHandler = std::function<void(int, const QString &)>;
57namespace Private 59namespace Private
58{ 60{
59 61
62class ExecutorBase;
63typedef QSharedPointer<ExecutorBase> ExecutorBasePtr;
64
65
60template<typename ... T> 66template<typename ... T>
61struct PreviousOut { 67struct PreviousOut {
62 using type = typename std::tuple_element<0, std::tuple<T ..., void>>::type; 68 using type = typename std::tuple_element<0, std::tuple<T ..., void>>::type;
@@ -77,9 +83,9 @@ public:
77 } 83 }
78 84
79protected: 85protected:
80 ExecutorBase(ExecutorBase *parent); 86 ExecutorBase(const ExecutorBasePtr &parent);
81 87
82 ExecutorBase *mPrev; 88 ExecutorBasePtr mPrev;
83 FutureBase *mResult; 89 FutureBase *mResult;
84}; 90};
85 91
@@ -87,7 +93,7 @@ template<typename PrevOut, typename Out, typename ... In>
87class Executor : public ExecutorBase 93class Executor : public ExecutorBase
88{ 94{
89protected: 95protected:
90 Executor(ExecutorBase *parent) 96 Executor(const Private::ExecutorBasePtr &parent)
91 : ExecutorBase(parent) 97 : ExecutorBase(parent)
92 , mPrevFuture(0) 98 , mPrevFuture(0)
93 {} 99 {}
@@ -106,7 +112,7 @@ template<typename Out, typename ... In>
106class ThenExecutor: public Executor<typename PreviousOut<In ...>::type, Out, In ...> 112class ThenExecutor: public Executor<typename PreviousOut<In ...>::type, Out, In ...>
107{ 113{
108public: 114public:
109 ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler errorHandler = ErrorHandler(), ExecutorBase *parent = nullptr); 115 ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler errorHandler = ErrorHandler(), const ExecutorBasePtr &parent = ExecutorBasePtr());
110 void previousFutureReady(); 116 void previousFutureReady();
111}; 117};
112 118
@@ -114,7 +120,7 @@ template<typename PrevOut, typename Out, typename In>
114class EachExecutor : public Executor<PrevOut, Out, In> 120class EachExecutor : public Executor<PrevOut, Out, In>
115{ 121{
116public: 122public:
117 EachExecutor(EachTask<Out, In> each, ExecutorBase *parent); 123 EachExecutor(EachTask<Out, In> each, const ExecutorBasePtr &parent);
118 void previousFutureReady(); 124 void previousFutureReady();
119 125
120private: 126private:
@@ -122,11 +128,10 @@ private:
122}; 128};
123 129
124template<typename Out, typename In> 130template<typename Out, typename In>
125class ReduceExecutor : public Executor<In, Out, In> 131class ReduceExecutor : public ThenExecutor<Out, In>
126{ 132{
127public: 133public:
128 ReduceExecutor(ReduceTask<Out, In> reduce, ExecutorBase *parent); 134 ReduceExecutor(ReduceTask<Out, In> reduce, const ExecutorBasePtr &parent);
129 void previousFutureReady();
130}; 135};
131 136
132} // namespace Private 137} // namespace Private
@@ -175,11 +180,11 @@ class JobBase
175 friend class Job; 180 friend class Job;
176 181
177public: 182public:
178 JobBase(Private::ExecutorBase *executor); 183 JobBase(const Private::ExecutorBasePtr &executor);
179 ~JobBase(); 184 ~JobBase();
180 185
181protected: 186protected:
182 Private::ExecutorBase *mExecutor; 187 Private::ExecutorBasePtr mExecutor;
183}; 188};
184 189
185/** 190/**
@@ -237,9 +242,8 @@ public:
237 template<typename OutOther, typename ... InOther> 242 template<typename OutOther, typename ... InOther>
238 Job<OutOther, InOther ...> then(ThenTask<OutOther, InOther ...> func, ErrorHandler errorFunc = ErrorHandler()) 243 Job<OutOther, InOther ...> then(ThenTask<OutOther, InOther ...> func, ErrorHandler errorFunc = ErrorHandler())
239 { 244 {
240 //FIXME are we leaking the executor? 245 return Job<OutOther, InOther ...>(Private::ExecutorBasePtr(
241 //The executor is copied with ever job instance, so use a sharedpointer? 246 new Private::ThenExecutor<OutOther, InOther ...>(func, errorFunc, mExecutor)));
242 return Job<OutOther, InOther ...>(new Private::ThenExecutor<OutOther, InOther ...>(func, errorFunc, mExecutor));
243 } 247 }
244 248
245 template<typename OutOther, typename InOther> 249 template<typename OutOther, typename InOther>
@@ -249,7 +253,8 @@ public:
249 "The 'Each' task can only be connected to a job that returns a list or an array."); 253 "The 'Each' task can only be connected to a job that returns a list or an array.");
250 static_assert(detail::isIterable<OutOther>::value, 254 static_assert(detail::isIterable<OutOther>::value,
251 "The result type of 'Each' task must be a list or an array."); 255 "The result type of 'Each' task must be a list or an array.");
252 return Job<OutOther, InOther>(new Private::EachExecutor<Out, OutOther, InOther>(func, mExecutor)); 256 return Job<OutOther, InOther>(Private::ExecutorBasePtr(
257 new Private::EachExecutor<Out, OutOther, InOther>(func, mExecutor)));
253 } 258 }
254 259
255 template<typename OutOther, typename InOther> 260 template<typename OutOther, typename InOther>
@@ -259,7 +264,8 @@ public:
259 "The 'Result' task can only be connected to a job that returns a list or an array"); 264 "The 'Result' task can only be connected to a job that returns a list or an array");
260 static_assert(std::is_same<typename Out::value_type, typename InOther::value_type>::value, 265 static_assert(std::is_same<typename Out::value_type, typename InOther::value_type>::value,
261 "The return type of previous task must be compatible with input type of this task"); 266 "The return type of previous task must be compatible with input type of this task");
262 return Job<OutOther, InOther>(new Private::ReduceExecutor<OutOther, InOther>(func, mExecutor)); 267 return Job<OutOther, InOther>(Private::ExecutorBasePtr(
268 new Private::ReduceExecutor<OutOther, InOther>(func, mExecutor)));
263 } 269 }
264 270
265 Async::Future<Out> exec() 271 Async::Future<Out> exec()
@@ -274,7 +280,7 @@ public:
274 } 280 }
275 281
276private: 282private:
277 Job(Private::ExecutorBase *executor) 283 Job(Private::ExecutorBasePtr executor)
278 : JobBase(executor) 284 : JobBase(executor)
279 {} 285 {}
280}; 286};
@@ -289,8 +295,7 @@ namespace Async {
289template<typename Out> 295template<typename Out>
290Job<Out> start(ThenTask<Out> func) 296Job<Out> start(ThenTask<Out> func)
291{ 297{
292 //FIXME we're leaking the exucutor, use a shared pointer 298 return Job<Out>(Private::ExecutorBasePtr(new Private::ThenExecutor<Out>(func)));
293 return Job<Out>(new Private::ThenExecutor<Out>(func));
294} 299}
295 300
296namespace Private { 301namespace Private {
@@ -326,7 +331,7 @@ void Executor<PrevOut, Out, In ...>::exec()
326} 331}
327 332
328template<typename Out, typename ... In> 333template<typename Out, typename ... In>
329ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler error, ExecutorBase* parent) 334ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler error, const ExecutorBasePtr &parent)
330 : Executor<typename PreviousOut<In ...>::type, Out, In ...>(parent) 335 : Executor<typename PreviousOut<In ...>::type, Out, In ...>(parent)
331{ 336{
332 this->mFunc = then; 337 this->mFunc = then;
@@ -356,7 +361,7 @@ void ThenExecutor<Out, In ...>::previousFutureReady()
356} 361}
357 362
358template<typename PrevOut, typename Out, typename In> 363template<typename PrevOut, typename Out, typename In>
359EachExecutor<PrevOut, Out, In>::EachExecutor(EachTask<Out, In> each, ExecutorBase* parent) 364EachExecutor<PrevOut, Out, In>::EachExecutor(EachTask<Out, In> each, const ExecutorBasePtr &parent)
360 : Executor<PrevOut, Out, In>(parent) 365 : Executor<PrevOut, Out, In>(parent)
361{ 366{
362 this->mFunc = each; 367 this->mFunc = each;
@@ -393,18 +398,11 @@ void EachExecutor<PrevOut, Out, In>::previousFutureReady()
393} 398}
394 399
395template<typename Out, typename In> 400template<typename Out, typename In>
396ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, ExecutorBase* parent) 401ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, const ExecutorBasePtr &parent)
397 : Executor<In, Out, In>(parent) 402 : ThenExecutor<Out, In>(reduce, ErrorHandler(), parent)
398{ 403{
399 this->mFunc = reduce;
400} 404}
401 405
402template<typename Out, typename In>
403void ReduceExecutor<Out, In>::previousFutureReady()
404{
405 assert(this->mPrevFuture->isFinished());
406 this->mFunc(this->mPrevFuture->value(), *static_cast<Async::Future<Out>*>(this->mResult));
407}
408 406
409} // namespace Private 407} // namespace Private
410 408