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, 39 insertions, 19 deletions
diff --git a/async/src/async.h b/async/src/async.h
index 239927d..182e57c 100644
--- a/async/src/async.h
+++ b/async/src/async.h
@@ -39,13 +39,20 @@ class JobBase;
39template<typename Out, typename ... In> 39template<typename Out, typename ... In>
40class Job; 40class Job;
41 41
42template<typename Out, typename ... In, typename F> 42template<typename Out, typename ... In>
43Job<Out, In ...> start(F func); 43using ThenTask = typename detail::identity<std::function<void(In ..., Async::Future<Out>&)>>::type;
44template<typename Out, typename In>
45using EachTask = typename detail::identity<std::function<void(In, Async::Future<Out>&)>>::type;
46template<typename Out, typename In>
47using ReduceTask = typename detail::identity<std::function<void(In, Async::Future<Out>&)>>::type;
48
49template<typename Out, typename ... In>
50Job<Out, In ...> start(ThenTask<Out, In ...> func);
44 51
45namespace Private 52namespace Private
46{ 53{
47 template<typename Out, typename ... In> 54 template<typename Out, typename ... In>
48 Async::Future<Out>* doExec(Job<Out, In ...> *job, const In & ... args); 55 void doExec(Job<Out, In ...> *job, Async::Future<Out> &out, const In & ... args);
49} 56}
50 57
51class JobBase 58class JobBase
@@ -56,7 +63,8 @@ class JobBase
56protected: 63protected:
57 enum JobType { 64 enum JobType {
58 Then, 65 Then,
59 Each 66 Each,
67 Reduce
60 }; 68 };
61 69
62public: 70public:
@@ -75,8 +83,8 @@ class Job : public JobBase
75 template<typename Out_, typename ... In_> 83 template<typename Out_, typename ... In_>
76 friend class Job; 84 friend class Job;
77 85
78 template<typename Out_, typename ... In_, typename F_> 86 template<typename Out_, typename ... In_>
79 friend Job<Out_, In_ ...> start(F_ func); 87 friend Job<Out_, In_ ...> start(Async::ThenTask<Out_, In_ ...> func);
80 88
81 typedef Out OutType; 89 typedef Out OutType;
82 typedef typename std::tuple_element<0, std::tuple<In ..., void>>::type InType; 90 typedef typename std::tuple_element<0, std::tuple<In ..., void>>::type InType;
@@ -87,16 +95,28 @@ public:
87 delete reinterpret_cast<Async::Future<Out>*>(mResult); 95 delete reinterpret_cast<Async::Future<Out>*>(mResult);
88 } 96 }
89 97
90 template<typename Out_, typename ... In_, typename F> 98 template<typename Out_, typename ... In_>
91 Job<Out_, In_ ...> then(F func) 99 Job<Out_, In_ ...> then(ThenTask<Out_, In_ ...> func)
92 { 100 {
93 return Job<Out_, In_ ...>::create(func, JobBase::Then, this); 101 return Job<Out_, In_ ...>::create(func, JobBase::Then, this);
94 } 102 }
95 103
96 template<typename Out_, typename ... In_, typename F> 104 template<typename Out_, typename In_>
97 Job<Out_, In_ ...> each(F func) 105 Job<Out_, In_> each(EachTask<Out_, In_> func)
98 { 106 {
99 return Job<Out_, In_ ...>::create(func, JobBase::Each, this); 107 static_assert(detail::isIterable<OutType>::value,
108 "The 'Each' task can only be connected to a job that returns a list or array.");
109 static_assert(detail::isIterable<Out_>::value,
110 "The result type of 'Each' task must be a list or an array.");
111 return Job<Out_, In_>::create(func, JobBase::Each, this);
112 }
113
114 template<typename Out_, typename In_>
115 Job<Out_, In_> reduce(ReduceTask<Out_, In_> func)
116 {
117 static_assert(Async::detail::isIterable<OutType>::value,
118 "The result type of 'Reduce' task must be a list or an array.");
119 return Job<Out_, In_>::create(func, JobBase::Reduce, this);
100 } 120 }
101 121
102 Async::Future<Out> result() const 122 Async::Future<Out> result() const
@@ -116,7 +136,7 @@ private:
116 static Job<Out, In ... > create(F func, JobBase::JobType jobType, JobBase *parent = nullptr); 136 static Job<Out, In ... > create(F func, JobBase::JobType jobType, JobBase *parent = nullptr);
117 137
118public: 138public:
119 std::function<Async::Future<Out>(In ...)> mFunc; 139 std::function<void(In ..., Async::Future<Out>&)> mFunc;
120}; 140};
121 141
122 142
@@ -126,16 +146,16 @@ public:
126 146
127// ********** Out of line definitions **************** 147// ********** Out of line definitions ****************
128 148
129template<typename Out, typename ... In, typename F> 149template<typename Out, typename ... In>
130Async::Job<Out, In ...> Async::start(F func) 150Async::Job<Out, In ...> Async::start(ThenTask<Out, In ...> func)
131{ 151{
132 return Job<Out, In ...>::create(func, JobBase::Then); 152 return Job<Out, In ...>::create(func, JobBase::Then);
133} 153}
134 154
135template<typename Out, typename ... In> 155template<typename Out, typename ... In>
136Async::Future<Out>* Async::Private::doExec(Job<Out, In ...> *job, const In & ... args) 156void Async::Private::doExec(Job<Out, In ...> *job, Async::Future<Out> &out, const In & ... args)
137{ 157{
138 return new Async::Future<Out>(job->mFunc(args ...)); 158 job->mFunc(args ..., out);
139}; 159};
140 160
141template<typename Out, typename ... In> 161template<typename Out, typename ... In>
@@ -148,10 +168,10 @@ void Async::Job<Out, In ...>::exec()
148 assert(in->isFinished()); 168 assert(in->isFinished());
149 } 169 }
150 170
151 Job<Out, In ...> *job = dynamic_cast<Job<Out, In ...>*>(this); 171 auto out = new Async::Future<Out>();
152 Async::Future<Out> *out = Private::doExec<Out, In ...>(this, in ? in->value() : In() ...); 172 Private::doExec<Out, In ...>(this, *out, in ? in->value() : In() ...);
153 out->waitForFinished(); 173 out->waitForFinished();
154 job->mResult = reinterpret_cast<void*>(out); 174 mResult = reinterpret_cast<void*>(out);
155} 175}
156 176
157template<typename Out, typename ... In> 177template<typename Out, typename ... In>