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