diff options
Diffstat (limited to 'async/src/async.h')
-rw-r--r-- | async/src/async.h | 224 |
1 files changed, 130 insertions, 94 deletions
diff --git a/async/src/async.h b/async/src/async.h index c6ca9e7..73eeaa0 100644 --- a/async/src/async.h +++ b/async/src/async.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <iterator> | 25 | #include <iterator> |
26 | 26 | ||
27 | #include "future.h" | 27 | #include "future.h" |
28 | #include "debug.h" | ||
28 | #include "async_impl.h" | 29 | #include "async_impl.h" |
29 | 30 | ||
30 | #include <QVector> | 31 | #include <QVector> |
@@ -46,20 +47,22 @@ | |||
46 | * that can be stored and executed later on. Jobs can be composed, similarly to functions. | 47 | * that can be stored and executed later on. Jobs can be composed, similarly to functions. |
47 | * | 48 | * |
48 | * Relations between the components: | 49 | * Relations between the components: |
49 | * * Job: description of what should happen | 50 | * * Job: API wrapper around Executors chain. Can be destroyed while still running, |
50 | * * Executor: Running execution of a job, the process that calculates the result. | 51 | * because the actual execution happens in the background |
52 | * * Executor: Describes task to execute. Executors form a linked list matching the | ||
53 | * order in which they will be executed. The Executor chain is destroyed when | ||
54 | * the parent Job is destroyed. However if the Job is still running it is | ||
55 | * guaranteed that the Executor chain will not be destroyed until the execution | ||
56 | * is finished. | ||
57 | * * Execution: The running execution of the task stored in Executor. Each call to Job::exec() | ||
58 | * instantiates new Execution chain, which makes it possible for the Job to be | ||
59 | * executed multiple times (even in parallel). | ||
51 | * * Future: Representation of the result that is being calculated | 60 | * * Future: Representation of the result that is being calculated |
52 | * | 61 | * |
53 | * Lifetime: | ||
54 | * * Before a job is executed is treated like a normal value on the stack. | ||
55 | * * As soon as the job is executed, a heap allocated executor keeps the task running until complete. The associated future handle remains | ||
56 | * valid until the task is complete. To abort a job it has to be killed through the future handle. | ||
57 | * TODO: Can we tie the lifetime of the executor to the last available future handle? | ||
58 | * | 62 | * |
59 | * TODO: Progress reporting through future | 63 | * TODO: Composed progress reporting |
60 | * TODO: Possibility to abort a job through future (perhaps optional?) | 64 | * TODO: Possibility to abort a job through future (perhaps optional?) |
61 | * TODO: Support for timeout, specified during exec call, after which the error handler gets called with a defined errorCode. | 65 | * TODO: Support for timeout, specified during exec call, after which the error handler gets called with a defined errorCode. |
62 | * TODO: Repeated execution of a job to facilitate i.e. an async while loop of a job? | ||
63 | */ | 66 | */ |
64 | namespace Async { | 67 | namespace Async { |
65 | 68 | ||
@@ -94,38 +97,18 @@ class ExecutorBase; | |||
94 | typedef QSharedPointer<ExecutorBase> ExecutorBasePtr; | 97 | typedef QSharedPointer<ExecutorBase> ExecutorBasePtr; |
95 | 98 | ||
96 | struct Execution { | 99 | struct Execution { |
97 | Execution(const ExecutorBasePtr &executor) | 100 | Execution(const ExecutorBasePtr &executor); |
98 | : executor(executor) | 101 | ~Execution(); |
99 | , resultBase(nullptr) | 102 | void setFinished(); |
100 | , isRunning(false) | ||
101 | , isFinished(false) | ||
102 | {} | ||
103 | |||
104 | ~Execution() | ||
105 | { | ||
106 | if (resultBase) { | ||
107 | resultBase->releaseExecution(); | ||
108 | delete resultBase; | ||
109 | } | ||
110 | prevExecution.reset(); | ||
111 | } | ||
112 | |||
113 | void setFinished() | ||
114 | { | ||
115 | isFinished = true; | ||
116 | executor.clear(); | ||
117 | } | ||
118 | 103 | ||
119 | template<typename T> | 104 | template<typename T> |
120 | Async::Future<T>* result() | 105 | Async::Future<T>* result() const |
121 | { | 106 | { |
122 | return static_cast<Async::Future<T>*>(resultBase); | 107 | return static_cast<Async::Future<T>*>(resultBase); |
123 | } | 108 | } |
124 | 109 | ||
125 | void releaseFuture() | 110 | void releaseFuture(); |
126 | { | 111 | bool errorWasHandled() const; |
127 | resultBase = 0; | ||
128 | } | ||
129 | 112 | ||
130 | ExecutorBasePtr executor; | 113 | ExecutorBasePtr executor; |
131 | FutureBase *resultBase; | 114 | FutureBase *resultBase; |
@@ -133,8 +116,13 @@ struct Execution { | |||
133 | bool isFinished; | 116 | bool isFinished; |
134 | 117 | ||
135 | ExecutionPtr prevExecution; | 118 | ExecutionPtr prevExecution; |
119 | |||
120 | #ifndef QT_NO_DEBUG | ||
121 | Tracer *tracer; | ||
122 | #endif | ||
136 | }; | 123 | }; |
137 | 124 | ||
125 | |||
138 | typedef QSharedPointer<Execution> ExecutionPtr; | 126 | typedef QSharedPointer<Execution> ExecutionPtr; |
139 | 127 | ||
140 | class ExecutorBase | 128 | class ExecutorBase |
@@ -145,6 +133,9 @@ class ExecutorBase | |||
145 | template<typename Out, typename ... In> | 133 | template<typename Out, typename ... In> |
146 | friend class Async::Job; | 134 | friend class Async::Job; |
147 | 135 | ||
136 | friend class Execution; | ||
137 | friend class Async::Tracer; | ||
138 | |||
148 | public: | 139 | public: |
149 | virtual ~ExecutorBase(); | 140 | virtual ~ExecutorBase(); |
150 | virtual ExecutionPtr exec(const ExecutorBasePtr &self) = 0; | 141 | virtual ExecutionPtr exec(const ExecutorBasePtr &self) = 0; |
@@ -155,21 +146,31 @@ protected: | |||
155 | template<typename T> | 146 | template<typename T> |
156 | Async::Future<T>* createFuture(const ExecutionPtr &execution) const; | 147 | Async::Future<T>* createFuture(const ExecutionPtr &execution) const; |
157 | 148 | ||
149 | virtual bool hasErrorFunc() const = 0; | ||
150 | virtual bool handleError(const ExecutionPtr &execution) = 0; | ||
151 | |||
158 | ExecutorBasePtr mPrev; | 152 | ExecutorBasePtr mPrev; |
153 | |||
154 | #ifndef QT_NO_DEBUG | ||
155 | QString mExecutorName; | ||
156 | #endif | ||
159 | }; | 157 | }; |
160 | 158 | ||
161 | template<typename PrevOut, typename Out, typename ... In> | 159 | template<typename PrevOut, typename Out, typename ... In> |
162 | class Executor : public ExecutorBase | 160 | class Executor : public ExecutorBase |
163 | { | 161 | { |
164 | protected: | 162 | protected: |
165 | Executor(ErrorHandler errorHandler, const Private::ExecutorBasePtr &parent) | 163 | Executor(ErrorHandler errorFunc, const Private::ExecutorBasePtr &parent) |
166 | : ExecutorBase(parent) | 164 | : ExecutorBase(parent) |
167 | , mErrorFunc(errorHandler) | 165 | , mErrorFunc(errorFunc) |
168 | {} | 166 | {} |
167 | |||
169 | virtual ~Executor() {} | 168 | virtual ~Executor() {} |
170 | virtual void run(const ExecutionPtr &execution) = 0; | 169 | virtual void run(const ExecutionPtr &execution) = 0; |
171 | 170 | ||
172 | ExecutionPtr exec(const ExecutorBasePtr &self); | 171 | ExecutionPtr exec(const ExecutorBasePtr &self); |
172 | bool hasErrorFunc() const { return (bool) mErrorFunc; } | ||
173 | bool handleError(const ExecutionPtr &execution); | ||
173 | 174 | ||
174 | std::function<void(int, const QString &)> mErrorFunc; | 175 | std::function<void(int, const QString &)> mErrorFunc; |
175 | }; | 176 | }; |
@@ -178,7 +179,7 @@ template<typename Out, typename ... In> | |||
178 | class ThenExecutor: public Executor<typename detail::prevOut<In ...>::type, Out, In ...> | 179 | class ThenExecutor: public Executor<typename detail::prevOut<In ...>::type, Out, In ...> |
179 | { | 180 | { |
180 | public: | 181 | public: |
181 | ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler errorHandler, const ExecutorBasePtr &parent); | 182 | ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler errorFunc, const ExecutorBasePtr &parent); |
182 | void run(const ExecutionPtr &execution); | 183 | void run(const ExecutionPtr &execution); |
183 | private: | 184 | private: |
184 | ThenTask<Out, In ...> mFunc; | 185 | ThenTask<Out, In ...> mFunc; |
@@ -188,7 +189,7 @@ template<typename PrevOut, typename Out, typename In> | |||
188 | class EachExecutor : public Executor<PrevOut, Out, In> | 189 | class EachExecutor : public Executor<PrevOut, Out, In> |
189 | { | 190 | { |
190 | public: | 191 | public: |
191 | EachExecutor(EachTask<Out, In> each, ErrorHandler errorHandler, const ExecutorBasePtr &parent); | 192 | EachExecutor(EachTask<Out, In> each, ErrorHandler errorFunc, const ExecutorBasePtr &parent); |
192 | void run(const ExecutionPtr &execution); | 193 | void run(const ExecutionPtr &execution); |
193 | private: | 194 | private: |
194 | EachTask<Out, In> mFunc; | 195 | EachTask<Out, In> mFunc; |
@@ -199,7 +200,7 @@ template<typename Out, typename In> | |||
199 | class ReduceExecutor : public ThenExecutor<Out, In> | 200 | class ReduceExecutor : public ThenExecutor<Out, In> |
200 | { | 201 | { |
201 | public: | 202 | public: |
202 | ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorHandler, const ExecutorBasePtr &parent); | 203 | ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent); |
203 | private: | 204 | private: |
204 | ReduceTask<Out, In> mFunc; | 205 | ReduceTask<Out, In> mFunc; |
205 | }; | 206 | }; |
@@ -208,7 +209,7 @@ template<typename Out, typename ... In> | |||
208 | class SyncThenExecutor : public Executor<typename detail::prevOut<In ...>::type, Out, In ...> | 209 | class SyncThenExecutor : public Executor<typename detail::prevOut<In ...>::type, Out, In ...> |
209 | { | 210 | { |
210 | public: | 211 | public: |
211 | SyncThenExecutor(SyncThenTask<Out, In ...> then, ErrorHandler errorHandler, const ExecutorBasePtr &parent); | 212 | SyncThenExecutor(SyncThenTask<Out, In ...> then, ErrorHandler errorFunc, const ExecutorBasePtr &parent); |
212 | void run(const ExecutionPtr &execution); | 213 | void run(const ExecutionPtr &execution); |
213 | 214 | ||
214 | private: | 215 | private: |
@@ -221,7 +222,7 @@ template<typename Out, typename In> | |||
221 | class SyncReduceExecutor : public SyncThenExecutor<Out, In> | 222 | class SyncReduceExecutor : public SyncThenExecutor<Out, In> |
222 | { | 223 | { |
223 | public: | 224 | public: |
224 | SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorHandler, const ExecutorBasePtr &parent); | 225 | SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent); |
225 | private: | 226 | private: |
226 | SyncReduceTask<Out, In> mFunc; | 227 | SyncReduceTask<Out, In> mFunc; |
227 | }; | 228 | }; |
@@ -230,7 +231,7 @@ template<typename PrevOut, typename Out, typename In> | |||
230 | class SyncEachExecutor : public Executor<PrevOut, Out, In> | 231 | class SyncEachExecutor : public Executor<PrevOut, Out, In> |
231 | { | 232 | { |
232 | public: | 233 | public: |
233 | SyncEachExecutor(SyncEachTask<Out, In> each, ErrorHandler errorHandler, const ExecutorBasePtr &parent); | 234 | SyncEachExecutor(SyncEachTask<Out, In> each, ErrorHandler errorFunc, const ExecutorBasePtr &parent); |
234 | void run(const ExecutionPtr &execution); | 235 | void run(const ExecutionPtr &execution); |
235 | private: | 236 | private: |
236 | void run(Async::Future<Out> *future, const typename PrevOut::value_type &arg, std::false_type); // !std::is_void<Out> | 237 | void run(Async::Future<Out> *future, const typename PrevOut::value_type &arg, std::false_type); // !std::is_void<Out> |
@@ -251,10 +252,10 @@ private: | |||
251 | * where @p In is type of the result. | 252 | * where @p In is type of the result. |
252 | */ | 253 | */ |
253 | template<typename Out, typename ... In> | 254 | template<typename Out, typename ... In> |
254 | Job<Out, In ...> start(ThenTask<Out, In ...> func); | 255 | Job<Out, In ...> start(ThenTask<Out, In ...> func, ErrorHandler errorFunc = ErrorHandler()); |
255 | 256 | ||
256 | template<typename Out, typename ... In> | 257 | template<typename Out, typename ... In> |
257 | Job<Out, In ...> start(SyncThenTask<Out, In ...> func); | 258 | Job<Out, In ...> start(SyncThenTask<Out, In ...> func, ErrorHandler errorFunc = ErrorHandler()); |
258 | 259 | ||
259 | #ifdef WITH_KJOB | 260 | #ifdef WITH_KJOB |
260 | template<typename ReturnType, typename KJobType, ReturnType (KJobType::*KJobResultMethod)(), typename ... Args> | 261 | template<typename ReturnType, typename KJobType, ReturnType (KJobType::*KJobResultMethod)(), typename ... Args> |
@@ -356,10 +357,10 @@ class Job : public JobBase | |||
356 | friend class Job; | 357 | friend class Job; |
357 | 358 | ||
358 | template<typename OutOther, typename ... InOther> | 359 | template<typename OutOther, typename ... InOther> |
359 | friend Job<OutOther, InOther ...> start(Async::ThenTask<OutOther, InOther ...> func); | 360 | friend Job<OutOther, InOther ...> start(Async::ThenTask<OutOther, InOther ...> func, ErrorHandler errorFunc); |
360 | 361 | ||
361 | template<typename OutOther, typename ... InOther> | 362 | template<typename OutOther, typename ... InOther> |
362 | friend Job<OutOther, InOther ...> start(Async::SyncThenTask<OutOther, InOther ...> func); | 363 | friend Job<OutOther, InOther ...> start(Async::SyncThenTask<OutOther, InOther ...> func, ErrorHandler errorFunc); |
363 | 364 | ||
364 | #ifdef WITH_KJOB | 365 | #ifdef WITH_KJOB |
365 | template<typename ReturnType, typename KJobType, ReturnType (KJobType::*KJobResultMethod)(), typename ... Args> | 366 | template<typename ReturnType, typename KJobType, ReturnType (KJobType::*KJobResultMethod)(), typename ... Args> |
@@ -499,9 +500,14 @@ private: | |||
499 | auto job = otherJob; | 500 | auto job = otherJob; |
500 | FutureWatcher<OutOther> *watcher = new FutureWatcher<OutOther>(); | 501 | FutureWatcher<OutOther> *watcher = new FutureWatcher<OutOther>(); |
501 | QObject::connect(watcher, &FutureWatcherBase::futureReady, | 502 | QObject::connect(watcher, &FutureWatcherBase::futureReady, |
502 | [watcher, &future]() { | 503 | [watcher, future]() { |
503 | Async::detail::copyFutureValue(watcher->future(), future); | 504 | // FIXME: We pass future by value, because using reference causes the |
504 | future.setFinished(); | 505 | // future to get deleted before this lambda is invoked, leading to crash |
506 | // in copyFutureValue() | ||
507 | // copy by value is const | ||
508 | auto outFuture = future; | ||
509 | Async::detail::copyFutureValue(watcher->future(), outFuture); | ||
510 | outFuture.setFinished(); | ||
505 | delete watcher; | 511 | delete watcher; |
506 | }); | 512 | }); |
507 | watcher->setFuture(job.exec(in ...)); | 513 | watcher->setFuture(job.exec(in ...)); |
@@ -517,17 +523,17 @@ private: | |||
517 | namespace Async { | 523 | namespace Async { |
518 | 524 | ||
519 | template<typename Out, typename ... In> | 525 | template<typename Out, typename ... In> |
520 | Job<Out, In ...> start(ThenTask<Out, In ...> func) | 526 | Job<Out, In ...> start(ThenTask<Out, In ...> func, ErrorHandler error) |
521 | { | 527 | { |
522 | return Job<Out, In...>(Private::ExecutorBasePtr( | 528 | return Job<Out, In...>(Private::ExecutorBasePtr( |
523 | new Private::ThenExecutor<Out, In ...>(func, ErrorHandler(), Private::ExecutorBasePtr()))); | 529 | new Private::ThenExecutor<Out, In ...>(func, error, Private::ExecutorBasePtr()))); |
524 | } | 530 | } |
525 | 531 | ||
526 | template<typename Out, typename ... In> | 532 | template<typename Out, typename ... In> |
527 | Job<Out, In ...> start(SyncThenTask<Out, In ...> func) | 533 | Job<Out, In ...> start(SyncThenTask<Out, In ...> func, ErrorHandler error) |
528 | { | 534 | { |
529 | return Job<Out, In...>(Private::ExecutorBasePtr( | 535 | return Job<Out, In...>(Private::ExecutorBasePtr( |
530 | new Private::SyncThenExecutor<Out, In ...>(func, ErrorHandler(), Private::ExecutorBasePtr()))); | 536 | new Private::SyncThenExecutor<Out, In ...>(func, error, Private::ExecutorBasePtr()))); |
531 | } | 537 | } |
532 | 538 | ||
533 | #ifdef WITH_KJOB | 539 | #ifdef WITH_KJOB |
@@ -586,20 +592,18 @@ ExecutionPtr Executor<PrevOut, Out, In ...>::exec(const ExecutorBasePtr &self) | |||
586 | // Passing 'self' to execution ensures that the Executor chain remains | 592 | // Passing 'self' to execution ensures that the Executor chain remains |
587 | // valid until the entire execution is finished | 593 | // valid until the entire execution is finished |
588 | ExecutionPtr execution = ExecutionPtr::create(self); | 594 | ExecutionPtr execution = ExecutionPtr::create(self); |
595 | #ifndef QT_NO_DEBUG | ||
596 | execution->tracer = new Tracer(execution.data()); // owned by execution | ||
597 | #endif | ||
589 | 598 | ||
590 | // chainup | 599 | // chainup |
591 | execution->prevExecution = mPrev ? mPrev->exec(mPrev) : ExecutionPtr(); | 600 | execution->prevExecution = mPrev ? mPrev->exec(mPrev) : ExecutionPtr(); |
592 | /* | ||
593 | } else if (mPrev && !mPrevFuture) { | ||
594 | // If previous job is running or finished, just get it's future | ||
595 | mPrevFuture = static_cast<Async::Future<PrevOut>*>(mPrev->result()); | ||
596 | } | ||
597 | */ | ||
598 | 601 | ||
599 | execution->resultBase = this->createFuture<Out>(execution); | 602 | execution->resultBase = ExecutorBase::createFuture<Out>(execution); |
600 | auto fw = new Async::FutureWatcher<Out>(); | 603 | auto fw = new Async::FutureWatcher<Out>(); |
601 | QObject::connect(fw, &Async::FutureWatcher<Out>::futureReady, | 604 | QObject::connect(fw, &Async::FutureWatcher<Out>::futureReady, |
602 | [fw, execution, this]() { | 605 | [fw, execution, this]() { |
606 | handleError(execution); | ||
603 | execution->setFinished(); | 607 | execution->setFinished(); |
604 | delete fw; | 608 | delete fw; |
605 | }); | 609 | }); |
@@ -607,50 +611,77 @@ ExecutionPtr Executor<PrevOut, Out, In ...>::exec(const ExecutorBasePtr &self) | |||
607 | 611 | ||
608 | Async::Future<PrevOut> *prevFuture = execution->prevExecution ? execution->prevExecution->result<PrevOut>() : nullptr; | 612 | Async::Future<PrevOut> *prevFuture = execution->prevExecution ? execution->prevExecution->result<PrevOut>() : nullptr; |
609 | if (!prevFuture || prevFuture->isFinished()) { | 613 | if (!prevFuture || prevFuture->isFinished()) { |
610 | if (prevFuture && prevFuture->errorCode() != 0) { | 614 | if (prevFuture) { // prevFuture implies execution->prevExecution |
611 | if (mErrorFunc) { | 615 | if (prevFuture->errorCode()) { |
612 | mErrorFunc(prevFuture->errorCode(), prevFuture->errorMessage()); | 616 | // Propagate the errorCode and message to the outer Future |
613 | execution->resultBase->setFinished(); | 617 | execution->resultBase->setError(prevFuture->errorCode(), prevFuture->errorMessage()); |
614 | execution->setFinished(); | 618 | if (!execution->errorWasHandled()) { |
615 | return execution; | 619 | if (handleError(execution)) { |
620 | return execution; | ||
621 | } | ||
622 | } else { | ||
623 | return execution; | ||
624 | } | ||
616 | } else { | 625 | } else { |
617 | // Propagate the error to next caller | 626 | // Propagate error (if any) |
618 | } | 627 | } |
619 | } | 628 | } |
629 | |||
620 | execution->isRunning = true; | 630 | execution->isRunning = true; |
621 | run(execution); | 631 | run(execution); |
622 | } else { | 632 | } else { |
623 | auto futureWatcher = new Async::FutureWatcher<PrevOut>(); | 633 | auto prevFutureWatcher = new Async::FutureWatcher<PrevOut>(); |
624 | QObject::connect(futureWatcher, &Async::FutureWatcher<PrevOut>::futureReady, | 634 | QObject::connect(prevFutureWatcher, &Async::FutureWatcher<PrevOut>::futureReady, |
625 | [futureWatcher, execution, this]() { | 635 | [prevFutureWatcher, execution, this]() { |
626 | auto prevFuture = futureWatcher->future(); | 636 | auto prevFuture = prevFutureWatcher->future(); |
627 | assert(prevFuture.isFinished()); | 637 | assert(prevFuture.isFinished()); |
628 | delete futureWatcher; | 638 | delete prevFutureWatcher; |
629 | if (prevFuture.errorCode() != 0) { | 639 | auto prevExecutor = execution->executor->mPrev; |
630 | if (mErrorFunc) { | 640 | if (prevFuture.errorCode()) { |
631 | mErrorFunc(prevFuture.errorCode(), prevFuture.errorMessage()); | 641 | execution->resultBase->setError(prevFuture.errorCode(), prevFuture.errorMessage()); |
632 | execution->resultBase->setFinished(); | 642 | if (!execution->errorWasHandled()) { |
633 | return; | 643 | if (handleError(execution)) { |
644 | return; | ||
645 | } | ||
634 | } else { | 646 | } else { |
635 | // Propagate the error to next caller | 647 | return; |
636 | } | 648 | } |
637 | } | 649 | } |
650 | |||
651 | |||
652 | // propagate error (if any) | ||
638 | execution->isRunning = true; | 653 | execution->isRunning = true; |
639 | run(execution); | 654 | run(execution); |
640 | }); | 655 | }); |
641 | 656 | ||
642 | futureWatcher->setFuture(*static_cast<Async::Future<PrevOut>*>(prevFuture)); | 657 | prevFutureWatcher->setFuture(*static_cast<Async::Future<PrevOut>*>(prevFuture)); |
643 | } | 658 | } |
644 | 659 | ||
645 | return execution; | 660 | return execution; |
646 | } | 661 | } |
647 | 662 | ||
663 | template<typename PrevOut, typename Out, typename ... In> | ||
664 | bool Executor<PrevOut, Out, In ...>::handleError(const ExecutionPtr &execution) | ||
665 | { | ||
666 | assert(execution->resultBase->isFinished()); | ||
667 | if (execution->resultBase->errorCode()) { | ||
668 | if (mErrorFunc) { | ||
669 | mErrorFunc(execution->resultBase->errorCode(), | ||
670 | execution->resultBase->errorMessage()); | ||
671 | return true; | ||
672 | } | ||
673 | } | ||
674 | |||
675 | return false; | ||
676 | } | ||
677 | |||
648 | 678 | ||
649 | template<typename Out, typename ... In> | 679 | template<typename Out, typename ... In> |
650 | ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler error, const ExecutorBasePtr &parent) | 680 | ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler error, const ExecutorBasePtr &parent) |
651 | : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(error, parent) | 681 | : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(error, parent) |
652 | , mFunc(then) | 682 | , mFunc(then) |
653 | { | 683 | { |
684 | STORE_EXECUTOR_NAME("ThenExecutor", Out, In ...); | ||
654 | } | 685 | } |
655 | 686 | ||
656 | template<typename Out, typename ... In> | 687 | template<typename Out, typename ... In> |
@@ -662,7 +693,7 @@ void ThenExecutor<Out, In ...>::run(const ExecutionPtr &execution) | |||
662 | assert(prevFuture->isFinished()); | 693 | assert(prevFuture->isFinished()); |
663 | } | 694 | } |
664 | 695 | ||
665 | this->mFunc(prevFuture ? prevFuture->value() : In() ..., *execution->result<Out>()); | 696 | ThenExecutor<Out, In ...>::mFunc(prevFuture ? prevFuture->value() : In() ..., *execution->result<Out>()); |
666 | } | 697 | } |
667 | 698 | ||
668 | template<typename PrevOut, typename Out, typename In> | 699 | template<typename PrevOut, typename Out, typename In> |
@@ -670,6 +701,7 @@ EachExecutor<PrevOut, Out, In>::EachExecutor(EachTask<Out, In> each, ErrorHandle | |||
670 | : Executor<PrevOut, Out, In>(error, parent) | 701 | : Executor<PrevOut, Out, In>(error, parent) |
671 | , mFunc(each) | 702 | , mFunc(each) |
672 | { | 703 | { |
704 | STORE_EXECUTOR_NAME("EachExecutor", PrevOut, Out, In); | ||
673 | } | 705 | } |
674 | 706 | ||
675 | template<typename PrevOut, typename Out, typename In> | 707 | template<typename PrevOut, typename Out, typename In> |
@@ -687,7 +719,7 @@ void EachExecutor<PrevOut, Out, In>::run(const ExecutionPtr &execution) | |||
687 | 719 | ||
688 | for (auto arg : prevFuture->value()) { | 720 | for (auto arg : prevFuture->value()) { |
689 | Async::Future<Out> future; | 721 | Async::Future<Out> future; |
690 | this->mFunc(arg, future); | 722 | EachExecutor<PrevOut, Out, In>::mFunc(arg, future); |
691 | auto fw = new Async::FutureWatcher<Out>(); | 723 | auto fw = new Async::FutureWatcher<Out>(); |
692 | mFutureWatchers.append(fw); | 724 | mFutureWatchers.append(fw); |
693 | QObject::connect(fw, &Async::FutureWatcher<Out>::futureReady, | 725 | QObject::connect(fw, &Async::FutureWatcher<Out>::futureReady, |
@@ -708,16 +740,18 @@ void EachExecutor<PrevOut, Out, In>::run(const ExecutionPtr &execution) | |||
708 | } | 740 | } |
709 | 741 | ||
710 | template<typename Out, typename In> | 742 | template<typename Out, typename In> |
711 | ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler error, const ExecutorBasePtr &parent) | 743 | ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent) |
712 | : ThenExecutor<Out, In>(reduce, error, parent) | 744 | : ThenExecutor<Out, In>(reduce, errorFunc, parent) |
713 | { | 745 | { |
746 | STORE_EXECUTOR_NAME("ReduceExecutor", Out, In); | ||
714 | } | 747 | } |
715 | 748 | ||
716 | template<typename Out, typename ... In> | 749 | template<typename Out, typename ... In> |
717 | SyncThenExecutor<Out, In ...>::SyncThenExecutor(SyncThenTask<Out, In ...> then, ErrorHandler errorHandler, const ExecutorBasePtr &parent) | 750 | SyncThenExecutor<Out, In ...>::SyncThenExecutor(SyncThenTask<Out, In ...> then, ErrorHandler errorFunc, const ExecutorBasePtr &parent) |
718 | : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(errorHandler, parent) | 751 | : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(errorFunc, parent) |
719 | , mFunc(then) | 752 | , mFunc(then) |
720 | { | 753 | { |
754 | STORE_EXECUTOR_NAME("SyncThenExecutor", Out, In ...); | ||
721 | } | 755 | } |
722 | 756 | ||
723 | template<typename Out, typename ... In> | 757 | template<typename Out, typename ... In> |
@@ -740,7 +774,7 @@ void SyncThenExecutor<Out, In ...>::run(const ExecutionPtr &execution, std::fals | |||
740 | : nullptr; | 774 | : nullptr; |
741 | (void) prevFuture; // silence 'set but not used' warning | 775 | (void) prevFuture; // silence 'set but not used' warning |
742 | Async::Future<Out> *future = execution->result<Out>(); | 776 | Async::Future<Out> *future = execution->result<Out>(); |
743 | future->setValue(this->mFunc(prevFuture ? prevFuture->value() : In() ...)); | 777 | future->setValue(SyncThenExecutor<Out, In...>::mFunc(prevFuture ? prevFuture->value() : In() ...)); |
744 | } | 778 | } |
745 | 779 | ||
746 | template<typename Out, typename ... In> | 780 | template<typename Out, typename ... In> |
@@ -751,14 +785,15 @@ void SyncThenExecutor<Out, In ...>::run(const ExecutionPtr &execution, std::true | |||
751 | ? execution->prevExecution->result<typename detail::prevOut<In ...>::type>() | 785 | ? execution->prevExecution->result<typename detail::prevOut<In ...>::type>() |
752 | : nullptr; | 786 | : nullptr; |
753 | (void) prevFuture; // silence 'set but not used' warning | 787 | (void) prevFuture; // silence 'set but not used' warning |
754 | this->mFunc(prevFuture ? prevFuture->value() : In() ...); | 788 | SyncThenExecutor<Out, In ...>::mFunc(prevFuture ? prevFuture->value() : In() ...); |
755 | } | 789 | } |
756 | 790 | ||
757 | template<typename PrevOut, typename Out, typename In> | 791 | template<typename PrevOut, typename Out, typename In> |
758 | SyncEachExecutor<PrevOut, Out, In>::SyncEachExecutor(SyncEachTask<Out, In> each, ErrorHandler errorHandler, const ExecutorBasePtr &parent) | 792 | SyncEachExecutor<PrevOut, Out, In>::SyncEachExecutor(SyncEachTask<Out, In> each, ErrorHandler errorFunc, const ExecutorBasePtr &parent) |
759 | : Executor<PrevOut, Out, In>(errorHandler, parent) | 793 | : Executor<PrevOut, Out, In>(errorFunc, parent) |
760 | , mFunc(each) | 794 | , mFunc(each) |
761 | { | 795 | { |
796 | STORE_EXECUTOR_NAME("SyncEachExecutor", PrevOut, Out, In); | ||
762 | } | 797 | } |
763 | 798 | ||
764 | template<typename PrevOut, typename Out, typename In> | 799 | template<typename PrevOut, typename Out, typename In> |
@@ -783,19 +818,20 @@ void SyncEachExecutor<PrevOut, Out, In>::run(const ExecutionPtr &execution) | |||
783 | template<typename PrevOut, typename Out, typename In> | 818 | template<typename PrevOut, typename Out, typename In> |
784 | void SyncEachExecutor<PrevOut, Out, In>::run(Async::Future<Out> *out, const typename PrevOut::value_type &arg, std::false_type) | 819 | void SyncEachExecutor<PrevOut, Out, In>::run(Async::Future<Out> *out, const typename PrevOut::value_type &arg, std::false_type) |
785 | { | 820 | { |
786 | out->setValue(out->value() + this->mFunc(arg)); | 821 | out->setValue(out->value() + SyncEachExecutor<PrevOut, Out, In>::mFunc(arg)); |
787 | } | 822 | } |
788 | 823 | ||
789 | template<typename PrevOut, typename Out, typename In> | 824 | template<typename PrevOut, typename Out, typename In> |
790 | void SyncEachExecutor<PrevOut, Out, In>::run(Async::Future<Out> * /* unused */, const typename PrevOut::value_type &arg, std::true_type) | 825 | void SyncEachExecutor<PrevOut, Out, In>::run(Async::Future<Out> * /* unused */, const typename PrevOut::value_type &arg, std::true_type) |
791 | { | 826 | { |
792 | this->mFunc(arg); | 827 | SyncEachExecutor<PrevOut, Out, In>::mFunc(arg); |
793 | } | 828 | } |
794 | 829 | ||
795 | template<typename Out, typename In> | 830 | template<typename Out, typename In> |
796 | SyncReduceExecutor<Out, In>::SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorHandler, const ExecutorBasePtr &parent) | 831 | SyncReduceExecutor<Out, In>::SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent) |
797 | : SyncThenExecutor<Out, In>(reduce, errorHandler, parent) | 832 | : SyncThenExecutor<Out, In>(reduce, errorFunc, parent) |
798 | { | 833 | { |
834 | STORE_EXECUTOR_NAME("SyncReduceExecutor", Out, In); | ||
799 | } | 835 | } |
800 | 836 | ||
801 | 837 | ||