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