summaryrefslogtreecommitdiffstats
path: root/async/src/async.h
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2015-04-12 16:02:56 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2015-04-12 16:02:56 +0200
commit7357673a7ee5a0976447d0285e3aa272e8626282 (patch)
tree667c7f7c8a780c88419f878ed5c381d54a7ed803 /async/src/async.h
parente85967518b9041e9943ec5f1765c6694bb153840 (diff)
parent73b8fe58c6fb985898d2bbf431926f0628e2b0a9 (diff)
downloadsink-7357673a7ee5a0976447d0285e3aa272e8626282.tar.gz
sink-7357673a7ee5a0976447d0285e3aa272e8626282.zip
Merge remote-tracking branch 'origin/develop' into develop
Diffstat (limited to 'async/src/async.h')
-rw-r--r--async/src/async.h224
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 */
64namespace Async { 67namespace Async {
65 68
@@ -94,38 +97,18 @@ class ExecutorBase;
94typedef QSharedPointer<ExecutorBase> ExecutorBasePtr; 97typedef QSharedPointer<ExecutorBase> ExecutorBasePtr;
95 98
96struct Execution { 99struct 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
138typedef QSharedPointer<Execution> ExecutionPtr; 126typedef QSharedPointer<Execution> ExecutionPtr;
139 127
140class ExecutorBase 128class 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
148public: 139public:
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
161template<typename PrevOut, typename Out, typename ... In> 159template<typename PrevOut, typename Out, typename ... In>
162class Executor : public ExecutorBase 160class Executor : public ExecutorBase
163{ 161{
164protected: 162protected:
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>
178class ThenExecutor: public Executor<typename detail::prevOut<In ...>::type, Out, In ...> 179class ThenExecutor: public Executor<typename detail::prevOut<In ...>::type, Out, In ...>
179{ 180{
180public: 181public:
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);
183private: 184private:
184 ThenTask<Out, In ...> mFunc; 185 ThenTask<Out, In ...> mFunc;
@@ -188,7 +189,7 @@ template<typename PrevOut, typename Out, typename In>
188class EachExecutor : public Executor<PrevOut, Out, In> 189class EachExecutor : public Executor<PrevOut, Out, In>
189{ 190{
190public: 191public:
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);
193private: 194private:
194 EachTask<Out, In> mFunc; 195 EachTask<Out, In> mFunc;
@@ -199,7 +200,7 @@ template<typename Out, typename In>
199class ReduceExecutor : public ThenExecutor<Out, In> 200class ReduceExecutor : public ThenExecutor<Out, In>
200{ 201{
201public: 202public:
202 ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorHandler, const ExecutorBasePtr &parent); 203 ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent);
203private: 204private:
204 ReduceTask<Out, In> mFunc; 205 ReduceTask<Out, In> mFunc;
205}; 206};
@@ -208,7 +209,7 @@ template<typename Out, typename ... In>
208class SyncThenExecutor : public Executor<typename detail::prevOut<In ...>::type, Out, In ...> 209class SyncThenExecutor : public Executor<typename detail::prevOut<In ...>::type, Out, In ...>
209{ 210{
210public: 211public:
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
214private: 215private:
@@ -221,7 +222,7 @@ template<typename Out, typename In>
221class SyncReduceExecutor : public SyncThenExecutor<Out, In> 222class SyncReduceExecutor : public SyncThenExecutor<Out, In>
222{ 223{
223public: 224public:
224 SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorHandler, const ExecutorBasePtr &parent); 225 SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent);
225private: 226private:
226 SyncReduceTask<Out, In> mFunc; 227 SyncReduceTask<Out, In> mFunc;
227}; 228};
@@ -230,7 +231,7 @@ template<typename PrevOut, typename Out, typename In>
230class SyncEachExecutor : public Executor<PrevOut, Out, In> 231class SyncEachExecutor : public Executor<PrevOut, Out, In>
231{ 232{
232public: 233public:
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);
235private: 236private:
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 */
253template<typename Out, typename ... In> 254template<typename Out, typename ... In>
254Job<Out, In ...> start(ThenTask<Out, In ...> func); 255Job<Out, In ...> start(ThenTask<Out, In ...> func, ErrorHandler errorFunc = ErrorHandler());
255 256
256template<typename Out, typename ... In> 257template<typename Out, typename ... In>
257Job<Out, In ...> start(SyncThenTask<Out, In ...> func); 258Job<Out, In ...> start(SyncThenTask<Out, In ...> func, ErrorHandler errorFunc = ErrorHandler());
258 259
259#ifdef WITH_KJOB 260#ifdef WITH_KJOB
260template<typename ReturnType, typename KJobType, ReturnType (KJobType::*KJobResultMethod)(), typename ... Args> 261template<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:
517namespace Async { 523namespace Async {
518 524
519template<typename Out, typename ... In> 525template<typename Out, typename ... In>
520Job<Out, In ...> start(ThenTask<Out, In ...> func) 526Job<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
526template<typename Out, typename ... In> 532template<typename Out, typename ... In>
527Job<Out, In ...> start(SyncThenTask<Out, In ...> func) 533Job<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
663template<typename PrevOut, typename Out, typename ... In>
664bool 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
649template<typename Out, typename ... In> 679template<typename Out, typename ... In>
650ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler error, const ExecutorBasePtr &parent) 680ThenExecutor<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
656template<typename Out, typename ... In> 687template<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
668template<typename PrevOut, typename Out, typename In> 699template<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
675template<typename PrevOut, typename Out, typename In> 707template<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
710template<typename Out, typename In> 742template<typename Out, typename In>
711ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler error, const ExecutorBasePtr &parent) 743ReduceExecutor<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
716template<typename Out, typename ... In> 749template<typename Out, typename ... In>
717SyncThenExecutor<Out, In ...>::SyncThenExecutor(SyncThenTask<Out, In ...> then, ErrorHandler errorHandler, const ExecutorBasePtr &parent) 750SyncThenExecutor<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
723template<typename Out, typename ... In> 757template<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
746template<typename Out, typename ... In> 780template<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
757template<typename PrevOut, typename Out, typename In> 791template<typename PrevOut, typename Out, typename In>
758SyncEachExecutor<PrevOut, Out, In>::SyncEachExecutor(SyncEachTask<Out, In> each, ErrorHandler errorHandler, const ExecutorBasePtr &parent) 792SyncEachExecutor<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
764template<typename PrevOut, typename Out, typename In> 799template<typename PrevOut, typename Out, typename In>
@@ -783,19 +818,20 @@ void SyncEachExecutor<PrevOut, Out, In>::run(const ExecutionPtr &execution)
783template<typename PrevOut, typename Out, typename In> 818template<typename PrevOut, typename Out, typename In>
784void SyncEachExecutor<PrevOut, Out, In>::run(Async::Future<Out> *out, const typename PrevOut::value_type &arg, std::false_type) 819void 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
789template<typename PrevOut, typename Out, typename In> 824template<typename PrevOut, typename Out, typename In>
790void SyncEachExecutor<PrevOut, Out, In>::run(Async::Future<Out> * /* unused */, const typename PrevOut::value_type &arg, std::true_type) 825void 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
795template<typename Out, typename In> 830template<typename Out, typename In>
796SyncReduceExecutor<Out, In>::SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorHandler, const ExecutorBasePtr &parent) 831SyncReduceExecutor<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