• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/functional/any_invocable.h"
23 #include "absl/meta/type_traits.h"
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   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static Poll<T> Wrap(T&& x) {
54     return Poll<T>(std::forward<T>(x));
55   }
56 };
57 
58 template <typename T>
59 struct PollWrapper<Poll<T>> {
60   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static Poll<T> Wrap(Poll<T>&& x) {
61     return std::forward<Poll<T>>(x);
62   }
63 };
64 
65 template <typename T>
66 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline auto WrapInPoll(T&& x)
67     -> decltype(PollWrapper<T>::Wrap(std::forward<T>(x))) {
68   return PollWrapper<T>::Wrap(std::forward<T>(x));
69 }
70 
71 // T -> T, const T& -> T
72 template <typename T>
73 using RemoveCVRef = absl::remove_cv_t<absl::remove_reference_t<T>>;
74 
75 template <typename F, typename SfinaeVoid = void>
76 class PromiseLike;
77 
78 template <>
79 class PromiseLike<void>;
80 
81 template <typename F>
82 class PromiseLike<F, absl::enable_if_t<!std::is_void<
83 #if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \
84     (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
85                          std::invoke_result_t<F>
86 #else
87                          typename std::result_of<F()>::type
88 #endif
89                          >::value>> {
90  private:
91   GPR_NO_UNIQUE_ADDRESS RemoveCVRef<F> f_;
92 
93  public:
94   // NOLINTNEXTLINE - internal detail that drastically simplifies calling code.
95   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION PromiseLike(F&& f)
96       : f_(std::forward<F>(f)) {}
97   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION auto operator()()
98       -> decltype(WrapInPoll(f_())) {
99     return WrapInPoll(f_());
100   }
101   using Result = typename PollTraits<decltype(WrapInPoll(f_()))>::Type;
102 };
103 
104 template <typename F>
105 class PromiseLike<F, absl::enable_if_t<std::is_void<
106 #if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \
107     (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
108                          std::invoke_result_t<F>
109 #else
110                          typename std::result_of<F()>::type
111 #endif
112                          >::value>> {
113  private:
114   GPR_NO_UNIQUE_ADDRESS RemoveCVRef<F> f_;
115 
116  public:
117   // NOLINTNEXTLINE - internal detail that drastically simplifies calling code.
118   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION PromiseLike(F&& f)
119       : f_(std::forward<F>(f)) {}
120   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<Empty> operator()() {
121     f_();
122     return Empty{};
123   }
124   using Result = Empty;
125 };
126 
127 }  // namespace promise_detail
128 }  // namespace grpc_core
129 
130 #endif  // GRPC_SRC_CORE_LIB_PROMISE_DETAIL_PROMISE_LIKE_H
131