capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

async-prelude.h (7744B)


      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 // Detect whether or not we should enable kj::Promise<T> coroutine integration.
     31 //
     32 // TODO(someday): Support coroutines with -fno-exceptions.
     33 #if !KJ_NO_EXCEPTIONS
     34 #ifdef __has_include
     35 // For now, we only support the Coroutines TS.
     36 //
     37 // TODO(someday): Also support standardized C++20 Coroutines. The latest VS2019 and GCC 10 both have
     38 //   support, though MSVC hides it behind /std:c++latest, which brings an ICE with it.
     39 #if __cpp_coroutines && __has_include(<experimental/coroutine>)
     40 // Coroutines TS detected.
     41 #include <experimental/coroutine>
     42 #define KJ_HAS_COROUTINE 1
     43 #define KJ_COROUTINE_STD_NAMESPACE std::experimental
     44 #endif
     45 #endif
     46 #endif
     47 
     48 KJ_BEGIN_HEADER
     49 
     50 namespace kj {
     51 
     52 class EventLoop;
     53 template <typename T>
     54 class Promise;
     55 class WaitScope;
     56 class TaskSet;
     57 
     58 template <typename T>
     59 Promise<Array<T>> joinPromises(Array<Promise<T>>&& promises);
     60 Promise<void> joinPromises(Array<Promise<void>>&& promises);
     61 
     62 namespace _ {  // private
     63 
     64 template <typename T>
     65 Promise<T> chainPromiseType(T*);
     66 template <typename T>
     67 Promise<T> chainPromiseType(Promise<T>*);
     68 
     69 template <typename T>
     70 using ChainPromises = decltype(chainPromiseType((T*)nullptr));
     71 // Constructs a promise for T, reducing double-promises. That is, if T is Promise<U>, resolves to
     72 // Promise<U>, otherwise resolves to Promise<T>.
     73 
     74 template <typename T>
     75 Promise<T> reducePromiseType(T*, ...);
     76 template <typename T>
     77 Promise<T> reducePromiseType(Promise<T>*, ...);
     78 template <typename T, typename Reduced = decltype(T::reducePromise(kj::instance<Promise<T>>()))>
     79 Reduced reducePromiseType(T*, bool);
     80 
     81 template <typename T>
     82 using ReducePromises = decltype(reducePromiseType((T*)nullptr, false));
     83 // Like ChainPromises, but also takes into account whether T has a method `reducePromise` that
     84 // reduces Promise<T> to something else. In particular this allows Promise<capnp::RemotePromise<U>>
     85 // to reduce to capnp::RemotePromise<U>.
     86 
     87 template <typename T> struct UnwrapPromise_;
     88 template <typename T> struct UnwrapPromise_<Promise<T>> { typedef T Type; };
     89 
     90 template <typename T>
     91 using UnwrapPromise = typename UnwrapPromise_<T>::Type;
     92 
     93 class PropagateException {
     94   // A functor which accepts a kj::Exception as a parameter and returns a broken promise of
     95   // arbitrary type which simply propagates the exception.
     96 public:
     97   class Bottom {
     98   public:
     99     Bottom(Exception&& exception): exception(kj::mv(exception)) {}
    100 
    101     Exception asException() { return kj::mv(exception); }
    102 
    103   private:
    104     Exception exception;
    105   };
    106 
    107   Bottom operator()(Exception&& e) {
    108     return Bottom(kj::mv(e));
    109   }
    110   Bottom operator()(const  Exception& e) {
    111     return Bottom(kj::cp(e));
    112   }
    113 };
    114 
    115 template <typename Func, typename T>
    116 struct ReturnType_ { typedef decltype(instance<Func>()(instance<T>())) Type; };
    117 template <typename Func>
    118 struct ReturnType_<Func, void> { typedef decltype(instance<Func>()()) Type; };
    119 
    120 template <typename Func, typename T>
    121 using ReturnType = typename ReturnType_<Func, T>::Type;
    122 // The return type of functor Func given a parameter of type T, with the special exception that if
    123 // T is void, this is the return type of Func called with no arguments.
    124 
    125 template <typename T> struct SplitTuplePromise_ { typedef Promise<T> Type; };
    126 template <typename... T>
    127 struct SplitTuplePromise_<kj::_::Tuple<T...>> {
    128   typedef kj::Tuple<ReducePromises<T>...> Type;
    129 };
    130 
    131 template <typename T>
    132 using SplitTuplePromise = typename SplitTuplePromise_<T>::Type;
    133 // T -> Promise<T>
    134 // Tuple<T> -> Tuple<Promise<T>>
    135 
    136 struct Void {};
    137 // Application code should NOT refer to this!  See `kj::READY_NOW` instead.
    138 
    139 template <typename T> struct FixVoid_ { typedef T Type; };
    140 template <> struct FixVoid_<void> { typedef Void Type; };
    141 template <typename T> using FixVoid = typename FixVoid_<T>::Type;
    142 // FixVoid<T> is just T unless T is void in which case it is _::Void (an empty struct).
    143 
    144 template <typename T> struct UnfixVoid_ { typedef T Type; };
    145 template <> struct UnfixVoid_<Void> { typedef void Type; };
    146 template <typename T> using UnfixVoid = typename UnfixVoid_<T>::Type;
    147 // UnfixVoid is the opposite of FixVoid.
    148 
    149 template <typename In, typename Out>
    150 struct MaybeVoidCaller {
    151   // Calls the function converting a Void input to an empty parameter list and a void return
    152   // value to a Void output.
    153 
    154   template <typename Func>
    155   static inline Out apply(Func& func, In&& in) {
    156     return func(kj::mv(in));
    157   }
    158 };
    159 template <typename In, typename Out>
    160 struct MaybeVoidCaller<In&, Out> {
    161   template <typename Func>
    162   static inline Out apply(Func& func, In& in) {
    163     return func(in);
    164   }
    165 };
    166 template <typename Out>
    167 struct MaybeVoidCaller<Void, Out> {
    168   template <typename Func>
    169   static inline Out apply(Func& func, Void&& in) {
    170     return func();
    171   }
    172 };
    173 template <typename In>
    174 struct MaybeVoidCaller<In, Void> {
    175   template <typename Func>
    176   static inline Void apply(Func& func, In&& in) {
    177     func(kj::mv(in));
    178     return Void();
    179   }
    180 };
    181 template <typename In>
    182 struct MaybeVoidCaller<In&, Void> {
    183   template <typename Func>
    184   static inline Void apply(Func& func, In& in) {
    185     func(in);
    186     return Void();
    187   }
    188 };
    189 template <>
    190 struct MaybeVoidCaller<Void, Void> {
    191   template <typename Func>
    192   static inline Void apply(Func& func, Void&& in) {
    193     func();
    194     return Void();
    195   }
    196 };
    197 
    198 template <typename T>
    199 inline T&& returnMaybeVoid(T&& t) {
    200   return kj::fwd<T>(t);
    201 }
    202 inline void returnMaybeVoid(Void&& v) {}
    203 
    204 class ExceptionOrValue;
    205 class PromiseNode;
    206 class ChainPromiseNode;
    207 template <typename T>
    208 class ForkHub;
    209 class FiberStack;
    210 class FiberBase;
    211 
    212 class Event;
    213 class XThreadEvent;
    214 class XThreadPaf;
    215 
    216 class PromiseBase {
    217 public:
    218   kj::String trace();
    219   // Dump debug info about this promise.
    220 
    221 private:
    222   Own<PromiseNode> node;
    223 
    224   PromiseBase() = default;
    225   PromiseBase(Own<PromiseNode>&& node): node(kj::mv(node)) {}
    226 
    227   template <typename>
    228   friend class kj::Promise;
    229   friend class PromiseNode;
    230 };
    231 
    232 void detach(kj::Promise<void>&& promise);
    233 void waitImpl(Own<_::PromiseNode>&& node, _::ExceptionOrValue& result, WaitScope& waitScope);
    234 bool pollImpl(_::PromiseNode& node, WaitScope& waitScope);
    235 Promise<void> yield();
    236 Promise<void> yieldHarder();
    237 Own<PromiseNode> neverDone();
    238 
    239 class NeverDone {
    240 public:
    241   template <typename T>
    242   operator Promise<T>() const;
    243 
    244   KJ_NORETURN(void wait(WaitScope& waitScope) const);
    245 };
    246 
    247 }  // namespace _ (private)
    248 }  // namespace kj
    249 
    250 KJ_END_HEADER