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 FiberBase; 192 193 class Event; 194 class XThreadEvent; 195 196 class PromiseBase { 197 public: 198 kj::String trace(); 199 // Dump debug info about this promise. 200 201 private: 202 Own<PromiseNode> node; 203 204 PromiseBase() = default; 205 PromiseBase(Own<PromiseNode>&& node): node(kj::mv(node)) {} 206 207 template <typename> 208 friend class kj::Promise; 209 friend class PromiseNode; 210 }; 211 212 void detach(kj::Promise<void>&& promise); 213 void waitImpl(Own<_::PromiseNode>&& node, _::ExceptionOrValue& result, WaitScope& waitScope); 214 bool pollImpl(_::PromiseNode& node, WaitScope& waitScope); 215 Promise<void> yield(); 216 Promise<void> yieldHarder(); 217 Own<PromiseNode> neverDone(); 218 219 class NeverDone { 220 public: 221 template <typename T> 222 operator Promise<T>() const; 223 224 KJ_NORETURN(void wait(WaitScope& waitScope) const); 225 }; 226 227 } // namespace _ (private) 228 } // namespace kj 229 230 KJ_END_HEADER 231