cannam@147
|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
cannam@147
|
2 // Licensed under the MIT License:
|
cannam@147
|
3 //
|
cannam@147
|
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
cannam@147
|
5 // of this software and associated documentation files (the "Software"), to deal
|
cannam@147
|
6 // in the Software without restriction, including without limitation the rights
|
cannam@147
|
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
cannam@147
|
8 // copies of the Software, and to permit persons to whom the Software is
|
cannam@147
|
9 // furnished to do so, subject to the following conditions:
|
cannam@147
|
10 //
|
cannam@147
|
11 // The above copyright notice and this permission notice shall be included in
|
cannam@147
|
12 // all copies or substantial portions of the Software.
|
cannam@147
|
13 //
|
cannam@147
|
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
cannam@147
|
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
cannam@147
|
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
cannam@147
|
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
cannam@147
|
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
cannam@147
|
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
cannam@147
|
20 // THE SOFTWARE.
|
cannam@147
|
21
|
cannam@147
|
22 // This file contains a bunch of internal declarations that must appear before async.h can start.
|
cannam@147
|
23 // We don't define these directly in async.h because it makes the file hard to read.
|
cannam@147
|
24
|
cannam@147
|
25 #ifndef KJ_ASYNC_PRELUDE_H_
|
cannam@147
|
26 #define KJ_ASYNC_PRELUDE_H_
|
cannam@147
|
27
|
cannam@147
|
28 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
|
cannam@147
|
29 #pragma GCC system_header
|
cannam@147
|
30 #endif
|
cannam@147
|
31
|
cannam@147
|
32 #include "exception.h"
|
cannam@147
|
33 #include "tuple.h"
|
cannam@147
|
34
|
cannam@147
|
35 namespace kj {
|
cannam@147
|
36
|
cannam@147
|
37 class EventLoop;
|
cannam@147
|
38 template <typename T>
|
cannam@147
|
39 class Promise;
|
cannam@147
|
40 class WaitScope;
|
cannam@147
|
41
|
cannam@147
|
42 template <typename T>
|
cannam@147
|
43 Promise<Array<T>> joinPromises(Array<Promise<T>>&& promises);
|
cannam@147
|
44 Promise<void> joinPromises(Array<Promise<void>>&& promises);
|
cannam@147
|
45
|
cannam@147
|
46 namespace _ { // private
|
cannam@147
|
47
|
cannam@147
|
48 template <typename T> struct JoinPromises_ { typedef T Type; };
|
cannam@147
|
49 template <typename T> struct JoinPromises_<Promise<T>> { typedef T Type; };
|
cannam@147
|
50
|
cannam@147
|
51 template <typename T>
|
cannam@147
|
52 using JoinPromises = typename JoinPromises_<T>::Type;
|
cannam@147
|
53 // If T is Promise<U>, resolves to U, otherwise resolves to T.
|
cannam@147
|
54 //
|
cannam@147
|
55 // TODO(cleanup): Rename to avoid confusion with joinPromises() call which is completely
|
cannam@147
|
56 // unrelated.
|
cannam@147
|
57
|
cannam@147
|
58 class PropagateException {
|
cannam@147
|
59 // A functor which accepts a kj::Exception as a parameter and returns a broken promise of
|
cannam@147
|
60 // arbitrary type which simply propagates the exception.
|
cannam@147
|
61 public:
|
cannam@147
|
62 class Bottom {
|
cannam@147
|
63 public:
|
cannam@147
|
64 Bottom(Exception&& exception): exception(kj::mv(exception)) {}
|
cannam@147
|
65
|
cannam@147
|
66 Exception asException() { return kj::mv(exception); }
|
cannam@147
|
67
|
cannam@147
|
68 private:
|
cannam@147
|
69 Exception exception;
|
cannam@147
|
70 };
|
cannam@147
|
71
|
cannam@147
|
72 Bottom operator()(Exception&& e) {
|
cannam@147
|
73 return Bottom(kj::mv(e));
|
cannam@147
|
74 }
|
cannam@147
|
75 Bottom operator()(const Exception& e) {
|
cannam@147
|
76 return Bottom(kj::cp(e));
|
cannam@147
|
77 }
|
cannam@147
|
78 };
|
cannam@147
|
79
|
cannam@147
|
80 template <typename Func, typename T>
|
cannam@147
|
81 struct ReturnType_ { typedef decltype(instance<Func>()(instance<T>())) Type; };
|
cannam@147
|
82 template <typename Func>
|
cannam@147
|
83 struct ReturnType_<Func, void> { typedef decltype(instance<Func>()()) Type; };
|
cannam@147
|
84
|
cannam@147
|
85 template <typename Func, typename T>
|
cannam@147
|
86 using ReturnType = typename ReturnType_<Func, T>::Type;
|
cannam@147
|
87 // The return type of functor Func given a parameter of type T, with the special exception that if
|
cannam@147
|
88 // T is void, this is the return type of Func called with no arguments.
|
cannam@147
|
89
|
cannam@147
|
90 template <typename T> struct SplitTuplePromise_ { typedef Promise<T> Type; };
|
cannam@147
|
91 template <typename... T>
|
cannam@147
|
92 struct SplitTuplePromise_<kj::_::Tuple<T...>> {
|
cannam@147
|
93 typedef kj::Tuple<Promise<JoinPromises<T>>...> Type;
|
cannam@147
|
94 };
|
cannam@147
|
95
|
cannam@147
|
96 template <typename T>
|
cannam@147
|
97 using SplitTuplePromise = typename SplitTuplePromise_<T>::Type;
|
cannam@147
|
98 // T -> Promise<T>
|
cannam@147
|
99 // Tuple<T> -> Tuple<Promise<T>>
|
cannam@147
|
100
|
cannam@147
|
101 struct Void {};
|
cannam@147
|
102 // Application code should NOT refer to this! See `kj::READY_NOW` instead.
|
cannam@147
|
103
|
cannam@147
|
104 template <typename T> struct FixVoid_ { typedef T Type; };
|
cannam@147
|
105 template <> struct FixVoid_<void> { typedef Void Type; };
|
cannam@147
|
106 template <typename T> using FixVoid = typename FixVoid_<T>::Type;
|
cannam@147
|
107 // FixVoid<T> is just T unless T is void in which case it is _::Void (an empty struct).
|
cannam@147
|
108
|
cannam@147
|
109 template <typename T> struct UnfixVoid_ { typedef T Type; };
|
cannam@147
|
110 template <> struct UnfixVoid_<Void> { typedef void Type; };
|
cannam@147
|
111 template <typename T> using UnfixVoid = typename UnfixVoid_<T>::Type;
|
cannam@147
|
112 // UnfixVoid is the opposite of FixVoid.
|
cannam@147
|
113
|
cannam@147
|
114 template <typename In, typename Out>
|
cannam@147
|
115 struct MaybeVoidCaller {
|
cannam@147
|
116 // Calls the function converting a Void input to an empty parameter list and a void return
|
cannam@147
|
117 // value to a Void output.
|
cannam@147
|
118
|
cannam@147
|
119 template <typename Func>
|
cannam@147
|
120 static inline Out apply(Func& func, In&& in) {
|
cannam@147
|
121 return func(kj::mv(in));
|
cannam@147
|
122 }
|
cannam@147
|
123 };
|
cannam@147
|
124 template <typename In, typename Out>
|
cannam@147
|
125 struct MaybeVoidCaller<In&, Out> {
|
cannam@147
|
126 template <typename Func>
|
cannam@147
|
127 static inline Out apply(Func& func, In& in) {
|
cannam@147
|
128 return func(in);
|
cannam@147
|
129 }
|
cannam@147
|
130 };
|
cannam@147
|
131 template <typename Out>
|
cannam@147
|
132 struct MaybeVoidCaller<Void, Out> {
|
cannam@147
|
133 template <typename Func>
|
cannam@147
|
134 static inline Out apply(Func& func, Void&& in) {
|
cannam@147
|
135 return func();
|
cannam@147
|
136 }
|
cannam@147
|
137 };
|
cannam@147
|
138 template <typename In>
|
cannam@147
|
139 struct MaybeVoidCaller<In, Void> {
|
cannam@147
|
140 template <typename Func>
|
cannam@147
|
141 static inline Void apply(Func& func, In&& in) {
|
cannam@147
|
142 func(kj::mv(in));
|
cannam@147
|
143 return Void();
|
cannam@147
|
144 }
|
cannam@147
|
145 };
|
cannam@147
|
146 template <typename In>
|
cannam@147
|
147 struct MaybeVoidCaller<In&, Void> {
|
cannam@147
|
148 template <typename Func>
|
cannam@147
|
149 static inline Void apply(Func& func, In& in) {
|
cannam@147
|
150 func(in);
|
cannam@147
|
151 return Void();
|
cannam@147
|
152 }
|
cannam@147
|
153 };
|
cannam@147
|
154 template <>
|
cannam@147
|
155 struct MaybeVoidCaller<Void, Void> {
|
cannam@147
|
156 template <typename Func>
|
cannam@147
|
157 static inline Void apply(Func& func, Void&& in) {
|
cannam@147
|
158 func();
|
cannam@147
|
159 return Void();
|
cannam@147
|
160 }
|
cannam@147
|
161 };
|
cannam@147
|
162
|
cannam@147
|
163 template <typename T>
|
cannam@147
|
164 inline T&& returnMaybeVoid(T&& t) {
|
cannam@147
|
165 return kj::fwd<T>(t);
|
cannam@147
|
166 }
|
cannam@147
|
167 inline void returnMaybeVoid(Void&& v) {}
|
cannam@147
|
168
|
cannam@147
|
169 class ExceptionOrValue;
|
cannam@147
|
170 class PromiseNode;
|
cannam@147
|
171 class ChainPromiseNode;
|
cannam@147
|
172 template <typename T>
|
cannam@147
|
173 class ForkHub;
|
cannam@147
|
174
|
cannam@147
|
175 class TaskSetImpl;
|
cannam@147
|
176
|
cannam@147
|
177 class Event;
|
cannam@147
|
178
|
cannam@147
|
179 class PromiseBase {
|
cannam@147
|
180 public:
|
cannam@147
|
181 kj::String trace();
|
cannam@147
|
182 // Dump debug info about this promise.
|
cannam@147
|
183
|
cannam@147
|
184 private:
|
cannam@147
|
185 Own<PromiseNode> node;
|
cannam@147
|
186
|
cannam@147
|
187 PromiseBase() = default;
|
cannam@147
|
188 PromiseBase(Own<PromiseNode>&& node): node(kj::mv(node)) {}
|
cannam@147
|
189
|
cannam@147
|
190 friend class kj::EventLoop;
|
cannam@147
|
191 friend class ChainPromiseNode;
|
cannam@147
|
192 template <typename>
|
cannam@147
|
193 friend class kj::Promise;
|
cannam@147
|
194 friend class TaskSetImpl;
|
cannam@147
|
195 template <typename U>
|
cannam@147
|
196 friend Promise<Array<U>> kj::joinPromises(Array<Promise<U>>&& promises);
|
cannam@147
|
197 friend Promise<void> kj::joinPromises(Array<Promise<void>>&& promises);
|
cannam@147
|
198 };
|
cannam@147
|
199
|
cannam@147
|
200 void detach(kj::Promise<void>&& promise);
|
cannam@147
|
201 void waitImpl(Own<_::PromiseNode>&& node, _::ExceptionOrValue& result, WaitScope& waitScope);
|
cannam@147
|
202 Promise<void> yield();
|
cannam@147
|
203 Own<PromiseNode> neverDone();
|
cannam@147
|
204
|
cannam@147
|
205 class NeverDone {
|
cannam@147
|
206 public:
|
cannam@147
|
207 template <typename T>
|
cannam@147
|
208 operator Promise<T>() const {
|
cannam@147
|
209 return Promise<T>(false, neverDone());
|
cannam@147
|
210 }
|
cannam@147
|
211
|
cannam@147
|
212 KJ_NORETURN(void wait(WaitScope& waitScope) const);
|
cannam@147
|
213 };
|
cannam@147
|
214
|
cannam@147
|
215 } // namespace _ (private)
|
cannam@147
|
216 } // namespace kj
|
cannam@147
|
217
|
cannam@147
|
218 #endif // KJ_ASYNC_PRELUDE_H_
|