diff options
Diffstat (limited to 'async/src/async.h')
-rw-r--r-- | async/src/async.h | 58 |
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 &)>; | |||
57 | namespace Private | 59 | namespace Private |
58 | { | 60 | { |
59 | 61 | ||
62 | class ExecutorBase; | ||
63 | typedef QSharedPointer<ExecutorBase> ExecutorBasePtr; | ||
64 | |||
65 | |||
60 | template<typename ... T> | 66 | template<typename ... T> |
61 | struct PreviousOut { | 67 | struct 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 | ||
79 | protected: | 85 | protected: |
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> | |||
87 | class Executor : public ExecutorBase | 93 | class Executor : public ExecutorBase |
88 | { | 94 | { |
89 | protected: | 95 | protected: |
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> | |||
106 | class ThenExecutor: public Executor<typename PreviousOut<In ...>::type, Out, In ...> | 112 | class ThenExecutor: public Executor<typename PreviousOut<In ...>::type, Out, In ...> |
107 | { | 113 | { |
108 | public: | 114 | public: |
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> | |||
114 | class EachExecutor : public Executor<PrevOut, Out, In> | 120 | class EachExecutor : public Executor<PrevOut, Out, In> |
115 | { | 121 | { |
116 | public: | 122 | public: |
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 | ||
120 | private: | 126 | private: |
@@ -122,11 +128,10 @@ private: | |||
122 | }; | 128 | }; |
123 | 129 | ||
124 | template<typename Out, typename In> | 130 | template<typename Out, typename In> |
125 | class ReduceExecutor : public Executor<In, Out, In> | 131 | class ReduceExecutor : public ThenExecutor<Out, In> |
126 | { | 132 | { |
127 | public: | 133 | public: |
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 | ||
177 | public: | 182 | public: |
178 | JobBase(Private::ExecutorBase *executor); | 183 | JobBase(const Private::ExecutorBasePtr &executor); |
179 | ~JobBase(); | 184 | ~JobBase(); |
180 | 185 | ||
181 | protected: | 186 | protected: |
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 | ||
276 | private: | 282 | private: |
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 { | |||
289 | template<typename Out> | 295 | template<typename Out> |
290 | Job<Out> start(ThenTask<Out> func) | 296 | Job<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 | ||
296 | namespace Private { | 301 | namespace Private { |
@@ -326,7 +331,7 @@ void Executor<PrevOut, Out, In ...>::exec() | |||
326 | } | 331 | } |
327 | 332 | ||
328 | template<typename Out, typename ... In> | 333 | template<typename Out, typename ... In> |
329 | ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler error, ExecutorBase* parent) | 334 | ThenExecutor<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 | ||
358 | template<typename PrevOut, typename Out, typename In> | 363 | template<typename PrevOut, typename Out, typename In> |
359 | EachExecutor<PrevOut, Out, In>::EachExecutor(EachTask<Out, In> each, ExecutorBase* parent) | 364 | EachExecutor<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 | ||
395 | template<typename Out, typename In> | 400 | template<typename Out, typename In> |
396 | ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, ExecutorBase* parent) | 401 | ReduceExecutor<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 | ||
402 | template<typename Out, typename In> | ||
403 | void 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 | ||