1 // Copyright 2021 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef GRPC_SRC_CORE_LIB_PROMISE_PROMISE_H 16 #define GRPC_SRC_CORE_LIB_PROMISE_PROMISE_H 17 18 #include <grpc/support/port_platform.h> 19 20 #include <type_traits> 21 22 #include "absl/functional/any_invocable.h" 23 #include "absl/status/status.h" 24 #include "absl/types/optional.h" 25 26 #include "src/core/lib/promise/detail/promise_like.h" 27 #include "src/core/lib/promise/poll.h" 28 29 namespace grpc_core { 30 31 // A Promise is any functor that takes no arguments and returns Poll<T>. 32 // Most of the time we just pass around the functor, but occasionally 33 // it pays to have a type erased variant, which we define here. 34 template <typename T> 35 using Promise = absl::AnyInvocable<Poll<T>()>; 36 37 // Helper to execute a promise immediately and return either the result or 38 // nothing. 39 template <typename Promise> 40 auto NowOrNever(Promise promise) 41 -> absl::optional<typename promise_detail::PromiseLike<Promise>::Result> { 42 auto r = promise_detail::PromiseLike<Promise>(std::move(promise))(); 43 if (auto* p = r.value_if_ready()) { 44 return std::move(*p); 45 } 46 return {}; 47 } 48 49 // A promise that never completes. 50 template <typename T> 51 struct Never { operatorNever52 Poll<T> operator()() { return Pending(); } 53 }; 54 55 namespace promise_detail { 56 // A promise that immediately completes. 57 template <typename T> 58 class Immediate { 59 public: Immediate(T value)60 explicit Immediate(T value) : value_(std::move(value)) {} 61 operator()62 Poll<T> operator()() { return std::move(value_); } 63 64 private: 65 T value_; 66 }; 67 } // namespace promise_detail 68 69 // Return \a value immediately 70 template <typename T> Immediate(T value)71promise_detail::Immediate<T> Immediate(T value) { 72 return promise_detail::Immediate<T>(std::move(value)); 73 } 74 75 // Return status Ok immediately 76 struct ImmediateOkStatus { operatorImmediateOkStatus77 Poll<absl::Status> operator()() { return absl::OkStatus(); } 78 }; 79 80 // Typecheck that a promise returns the expected return type. 81 // usage: auto promise = WithResult<int>([]() { return 3; }); 82 // NOTE: there are tests in promise_test.cc that are commented out because they 83 // should fail to compile. When modifying this code these should be uncommented 84 // and their miscompilation verified. 85 template <typename T, typename F> 86 auto WithResult(F f) -> 87 typename std::enable_if<std::is_same<decltype(f()), Poll<T>>::value, 88 F>::type { 89 return f; 90 } 91 92 template <typename Promise> 93 using PromiseResult = typename PollTraits< 94 typename promise_detail::PromiseLike<Promise>::Result>::Type; 95 96 } // namespace grpc_core 97 98 #endif // GRPC_SRC_CORE_LIB_PROMISE_PROMISE_H 99