diff options
Diffstat (limited to 'async/src/async.h')
-rw-r--r-- | async/src/async.h | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/async/src/async.h b/async/src/async.h new file mode 100644 index 0000000..790dfe9 --- /dev/null +++ b/async/src/async.h | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Copyright 2014 Daniel Vrátil <dvratil@redhat.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of | ||
7 | * the License or (at your option) version 3 or any later version | ||
8 | * accepted by the membership of KDE e.V. (or its successor approved | ||
9 | * by the membership of KDE e.V.), which shall act as a proxy | ||
10 | * defined in Section 14 of version 3 of the license. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef ASYNC_H | ||
23 | #define ASYNC_H | ||
24 | |||
25 | #include <functional> | ||
26 | #include <list> | ||
27 | #include <type_traits> | ||
28 | #include <iostream> | ||
29 | #include <cassert> | ||
30 | |||
31 | #include "future.h" | ||
32 | #include "async_impl.h" | ||
33 | |||
34 | |||
35 | namespace Async { | ||
36 | |||
37 | template<typename Out, typename ... In> | ||
38 | class Job; | ||
39 | |||
40 | template<typename Out, typename ... In> | ||
41 | Job<Out, In ...> start(const std::function<Async::Future<Out>(In ...)> &func); | ||
42 | |||
43 | |||
44 | class JobBase | ||
45 | { | ||
46 | public: | ||
47 | JobBase(JobBase *prev = nullptr) | ||
48 | : mPrev(prev) | ||
49 | , mResult(0) | ||
50 | {} | ||
51 | |||
52 | virtual void exec() = 0; | ||
53 | |||
54 | public: | ||
55 | JobBase *mPrev; | ||
56 | void *mResult; | ||
57 | }; | ||
58 | |||
59 | namespace Private { | ||
60 | |||
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 | |||
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 | |||
70 | template<typename Out, typename ... In> | ||
71 | class Job : public JobBase | ||
72 | { | ||
73 | template<typename Out_, typename ... In_> | ||
74 | friend class Job; | ||
75 | |||
76 | template<typename Out_, typename ... In_, typename F_> | ||
77 | friend Job<Out_, In_ ...> start(F_ func); | ||
78 | |||
79 | public: | ||
80 | ~Job() | ||
81 | { | ||
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); | ||
85 | } | ||
86 | |||
87 | template<typename Out_, typename ... In_, typename F> | ||
88 | Job<Out_, In_ ...> then(F func) | ||
89 | { | ||
90 | Job<Out_, In_ ...> job(this); | ||
91 | job.mFunc = func; | ||
92 | return job; | ||
93 | } | ||
94 | |||
95 | Async::Future<Out> result() const | ||
96 | { | ||
97 | return *reinterpret_cast<Async::Future<Out>*>(mResult); | ||
98 | } | ||
99 | |||
100 | |||
101 | void exec() | ||
102 | { | ||
103 | Async::Private::doExec<Out, In ...>(mPrev, this); | ||
104 | } | ||
105 | |||
106 | private: | ||
107 | Job(JobBase *parent = nullptr) | ||
108 | : JobBase(parent) | ||
109 | {} | ||
110 | |||
111 | public: | ||
112 | std::function<Async::Future<Out>(In ...)> mFunc; | ||
113 | }; | ||
114 | |||
115 | template<typename Out, typename ... In, typename F> | ||
116 | Job<Out, In ...> start(F func) | ||
117 | { | ||
118 | Job<Out, In ...> job; | ||
119 | job.mFunc = std::function<Async::Future<Out>(In ...)>(func); | ||
120 | return job; | ||
121 | } | ||
122 | |||
123 | } // namespace Async | ||
124 | |||
125 | template<typename Out, typename In> | ||
126 | typename std::enable_if<!std::is_void<In>::value, void>::type | ||
127 | Async::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 | |||
139 | template<typename Out, typename ... In> | ||
140 | typename std::enable_if<sizeof...(In) == 0, void>::type | ||
141 | Async::Private::doExec(JobBase *prev, JobBase *jobBase, int * /* disambiguation */ = 0) | ||
142 | { | ||
143 | if (prev) { | ||
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 | }; | ||
154 | |||
155 | |||
156 | #endif // ASYNC_H | ||
157 | |||
158 | |||