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_DETAIL_PROMISE_LIKE_H 16 #define GRPC_SRC_CORE_LIB_PROMISE_DETAIL_PROMISE_LIKE_H 17 18 #include <grpc/support/port_platform.h> 19 20 #include <utility> 21 22 #include "absl/meta/type_traits.h" 23 24 #include "src/core/lib/promise/poll.h" 25 26 // A Promise is a callable object that returns Poll<T> for some T. 27 // Often when we're writing code that uses promises, we end up wanting to also 28 // deal with code that completes instantaneously - that is, it returns some T 29 // where T is not Poll. 30 // PromiseLike wraps any callable that takes no parameters and implements the 31 // Promise interface. For things that already return Poll, this wrapping does 32 // nothing. For things that do not return Poll, we wrap the return type in Poll. 33 // This allows us to write things like: 34 // Seq( 35 // [] { return 42; }, 36 // ...) 37 // in preference to things like: 38 // Seq( 39 // [] { return Poll<int>(42); }, 40 // ...) 41 // or: 42 // Seq( 43 // [] -> Poll<int> { return 42; }, 44 // ...) 45 // leading to slightly more concise code and eliminating some rules that in 46 // practice people find hard to deal with. 47 48 namespace grpc_core { 49 namespace promise_detail { 50 51 template <typename T> 52 struct PollWrapper { WrapPollWrapper53 static Poll<T> Wrap(T&& x) { return Poll<T>(std::forward<T>(x)); } 54 }; 55 56 template <typename T> 57 struct PollWrapper<Poll<T>> { 58 static Poll<T> Wrap(Poll<T>&& x) { return std::forward<Poll<T>>(x); } 59 }; 60 61 template <typename T> 62 auto WrapInPoll(T&& x) -> decltype(PollWrapper<T>::Wrap(std::forward<T>(x))) { 63 return PollWrapper<T>::Wrap(std::forward<T>(x)); 64 } 65 66 template <typename F> 67 class PromiseLike { 68 private: 69 GPR_NO_UNIQUE_ADDRESS F f_; 70 71 public: 72 // NOLINTNEXTLINE - internal detail that drastically simplifies calling code. 73 PromiseLike(F&& f) : f_(std::forward<F>(f)) {} 74 auto operator()() -> decltype(WrapInPoll(f_())) { return WrapInPoll(f_()); } 75 using Result = typename PollTraits<decltype(WrapInPoll(f_()))>::Type; 76 }; 77 78 // T -> T, const T& -> T 79 template <typename T> 80 using RemoveCVRef = absl::remove_cv_t<absl::remove_reference_t<T>>; 81 82 } // namespace promise_detail 83 } // namespace grpc_core 84 85 #endif // GRPC_SRC_CORE_LIB_PROMISE_DETAIL_PROMISE_LIKE_H 86