summaryrefslogtreecommitdiffstats
path: root/async/src
diff options
context:
space:
mode:
Diffstat (limited to 'async/src')
-rw-r--r--async/src/async.h111
1 files changed, 60 insertions, 51 deletions
diff --git a/async/src/async.h b/async/src/async.h
index 790dfe9..3fee450 100644
--- a/async/src/async.h
+++ b/async/src/async.h
@@ -34,38 +34,51 @@
34 34
35namespace Async { 35namespace Async {
36 36
37class JobBase;
38
37template<typename Out, typename ... In> 39template<typename Out, typename ... In>
38class Job; 40class Job;
39 41
40template<typename Out, typename ... In> 42template<typename Out, typename ... In>
41Job<Out, In ...> start(const std::function<Async::Future<Out>(In ...)> &func); 43Job<Out, In ...> start(const std::function<Async::Future<Out>(In ...)> &func);
42 44
45namespace Private
46{
47 template<typename Out, typename ... In>
48 Async::Future<Out>* doExec(Job<Out, In ...> *job, const In & ... args);
49}
43 50
44class JobBase 51class JobBase
45{ 52{
53 template<typename Out, typename ... In>
54 friend Async::Future<Out>* Private::doExec(Job<Out, In ...> *job, const In & ... args);
55
56 template<typename Out, typename ... In>
57 friend class Job;
58
59protected:
60 enum JobType {
61 Then,
62 Each
63 };
64
46public: 65public:
47 JobBase(JobBase *prev = nullptr) 66 JobBase(JobType jobType, JobBase *prev = nullptr)
48 : mPrev(prev) 67 : mPrev(prev)
49 , mResult(0) 68 , mResult(0)
69 , mJobType(jobType)
50 {} 70 {}
51 71
52 virtual void exec() = 0; 72 virtual void exec() = 0;
53 73
54public: 74protected:
55 JobBase *mPrev; 75 JobBase *mPrev;
56 void *mResult; 76 void *mResult;
57};
58 77
59namespace Private { 78 JobType mJobType;
79};
60 80
61 template<typename Out, typename In>
62 typename std::enable_if<!std::is_void<In>::value, void>::type
63 doExec(JobBase *prev, JobBase *jobBase);
64 81
65 template<typename Out, typename ... In>
66 typename std::enable_if<sizeof...(In) == 0, void>::type
67 doExec(JobBase *prev, JobBase *jobBase, int * /* disambiguate */ = 0);
68}
69 82
70template<typename Out, typename ... In> 83template<typename Out, typename ... In>
71class Job : public JobBase 84class Job : public JobBase
@@ -76,20 +89,25 @@ class Job : public JobBase
76 template<typename Out_, typename ... In_, typename F_> 89 template<typename Out_, typename ... In_, typename F_>
77 friend Job<Out_, In_ ...> start(F_ func); 90 friend Job<Out_, In_ ...> start(F_ func);
78 91
92 typedef Out OutType;
93 typedef typename std::tuple_element<0, std::tuple<In ..., void>>::type InType;
94
79public: 95public:
80 ~Job() 96 ~Job()
81 { 97 {
82 // Can't delete in JobBase, since we don't know the type
83 // and deleting void* is undefined
84 delete reinterpret_cast<Async::Future<Out>*>(mResult); 98 delete reinterpret_cast<Async::Future<Out>*>(mResult);
85 } 99 }
86 100
87 template<typename Out_, typename ... In_, typename F> 101 template<typename Out_, typename ... In_, typename F>
88 Job<Out_, In_ ...> then(F func) 102 Job<Out_, In_ ...> then(F func)
89 { 103 {
90 Job<Out_, In_ ...> job(this); 104 return Job<Out_, In_ ...>::create(func, JobBase::Then, this);
91 job.mFunc = func; 105 }
92 return job; 106
107 template<typename Out_, typename ... In_, typename F>
108 Job<Out_, In_ ...> each(F func)
109 {
110 return Job<Out_, In_ ...>::create(func, JobBase::Each, this);
93 } 111 }
94 112
95 Async::Future<Out> result() const 113 Async::Future<Out> result() const
@@ -97,16 +115,34 @@ public:
97 return *reinterpret_cast<Async::Future<Out>*>(mResult); 115 return *reinterpret_cast<Async::Future<Out>*>(mResult);
98 } 116 }
99 117
100
101 void exec() 118 void exec()
102 { 119 {
103 Async::Private::doExec<Out, In ...>(mPrev, this); 120 Async::Future<InType> *in = nullptr;
121 if (mPrev) {
122 mPrev->exec();
123 in = reinterpret_cast<Async::Future<InType>*>(mPrev->mResult);
124 assert(in->isFinished());
125 }
126
127 Job<Out, In ...> *job = dynamic_cast<Job<Out, In ...>*>(this);
128 Async::Future<Out> *out = Private::doExec<Out, In ...>(this, in ? in->value() : In() ...);
129 out->waitForFinished();
130 job->mResult = reinterpret_cast<void*>(out);
104 } 131 }
105 132
106private: 133private:
107 Job(JobBase *parent = nullptr) 134 Job(JobBase::JobType jobType, JobBase *parent = nullptr)
108 : JobBase(parent) 135 : JobBase(jobType, parent)
109 {} 136 {
137 }
138
139 template<typename F>
140 static Job<Out, In ... > create(F func, JobBase::JobType jobType, JobBase *parent = nullptr)
141 {
142 Job<Out, In ...> job(jobType, parent);
143 job.mFunc = func;
144 return job;
145 }
110 146
111public: 147public:
112 std::function<Async::Future<Out>(In ...)> mFunc; 148 std::function<Async::Future<Out>(In ...)> mFunc;
@@ -115,44 +151,17 @@ public:
115template<typename Out, typename ... In, typename F> 151template<typename Out, typename ... In, typename F>
116Job<Out, In ...> start(F func) 152Job<Out, In ...> start(F func)
117{ 153{
118 Job<Out, In ...> job; 154 return Job<Out, In ...>::create(func, JobBase::Then);
119 job.mFunc = std::function<Async::Future<Out>(In ...)>(func);
120 return job;
121} 155}
122 156
123} // namespace Async 157} // namespace Async
124 158
125template<typename Out, typename In>
126typename std::enable_if<!std::is_void<In>::value, void>::type
127Async::Private::doExec(JobBase *prev, JobBase *jobBase)
128{
129 prev->exec();
130 Async::Future<In> *in = reinterpret_cast<Async::Future<In>*>(prev->mResult);
131 assert(in->isFinished());
132
133 Job<Out, In> *job = dynamic_cast<Job<Out, In>*>(jobBase);
134 Async::Future<Out> *out = new Async::Future<Out>(job->mFunc(in->value()));
135 out->waitForFinished();
136 job->mResult = reinterpret_cast<void*>(out);
137};
138
139template<typename Out, typename ... In> 159template<typename Out, typename ... In>
140typename std::enable_if<sizeof...(In) == 0, void>::type 160Async::Future<Out>* Async::Private::doExec(Job<Out, In ...> *job, const In & ... args)
141Async::Private::doExec(JobBase *prev, JobBase *jobBase, int * /* disambiguation */ = 0)
142{ 161{
143 if (prev) { 162 return new Async::Future<Out>(job->mFunc(args ...));
144 prev->exec();
145 Async::Future<void> *in = reinterpret_cast<Async::Future<void>*>(prev->mResult);
146 assert(in->isFinished());
147 }
148
149 Job<Out> *job = dynamic_cast<Job<Out>*>(jobBase);
150 Async::Future<Out> *out = new Async::Future<Out>(job->mFunc());
151 out->waitForFinished();
152 job->mResult = reinterpret_cast<void*>(out);
153}; 163};
154 164
155
156#endif // ASYNC_H 165#endif // ASYNC_H
157 166
158 167