promise_factory.h
Go to the documentation of this file.
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_CORE_LIB_PROMISE_DETAIL_PROMISE_FACTORY_H
16 #define GRPC_CORE_LIB_PROMISE_DETAIL_PROMISE_FACTORY_H
17 
19 
20 #include <type_traits>
21 #include <utility>
22 
23 #include "absl/meta/type_traits.h"
24 
26 
27 // PromiseFactory is an adaptor class.
28 //
29 // Where a Promise is a thing that's polled periodically, a PromiseFactory
30 // creates a Promise. Within this Promise/Activity framework, PromiseFactory's
31 // then provide the edges for computation -- invoked at state transition
32 // boundaries to provide the new steady state.
33 //
34 // A PromiseFactory formally is f(A) -> Promise<T> for some types A & T.
35 // This get a bit awkward and inapproprate to write however, and so the type
36 // contained herein can adapt various kinds of callable into the correct form.
37 // Of course a callable of a single argument returning a Promise will see an
38 // identity translation. One taking no arguments and returning a Promise
39 // similarly.
40 //
41 // A Promise passed to a PromiseFactory will yield a PromiseFactory that
42 // returns just that Promise.
43 //
44 // Generalizing slightly, a callable taking a single argument A and returning a
45 // Poll<T> will yield a PromiseFactory that captures it's argument A and
46 // returns a Poll<T>.
47 //
48 // Since various consumers of PromiseFactory run either repeatedly through an
49 // overarching Promises lifetime, or just once, and we can optimize just once
50 // by moving the contents of the PromiseFactory, two factory methods are
51 // provided: Once, that can be called just once, and Repeated, that can (wait
52 // for it) be called Repeatedly.
53 
54 namespace grpc_core {
55 namespace promise_detail {
56 
57 // Helper trait: given a T, and T x, is calling x() legal?
58 template <typename T, typename Ignored = void>
60  static constexpr bool value = false;
61 };
62 template <typename F>
63 struct IsVoidCallable<F, absl::void_t<decltype(std::declval<F>()())>> {
64  static constexpr bool value = true;
65 };
66 
67 // Given F(A,B,C,...), what's the return type?
68 template <typename T, typename Ignored = void>
69 struct ResultOfT;
70 
71 template <typename F, typename... Args>
72 struct ResultOfT<F(Args...),
73  absl::void_t<decltype(std::declval<RemoveCVRef<F>>()(
74  std::declval<Args>()...))>> {
75  using T = decltype(std::declval<RemoveCVRef<F>>()(std::declval<Args>()...));
76 };
77 
78 template <typename T>
79 using ResultOf = typename ResultOfT<T>::T;
80 
81 // Captures the promise functor and the argument passed.
82 // Provides the interface of a promise.
83 template <typename F, typename Arg>
84 class Curried {
85  public:
86  Curried(F&& f, Arg&& arg)
87  : f_(std::forward<F>(f)), arg_(std::forward<Arg>(arg)) {}
88  Curried(const F& f, Arg&& arg) : f_(f), arg_(std::forward<Arg>(arg)) {}
89  using Result = decltype(std::declval<F>()(std::declval<Arg>()));
90  Result operator()() { return f_(std::move(arg_)); }
91 
92  private:
95 };
96 
97 // Promote a callable(A) -> T | Poll<T> to a PromiseFactory(A) -> Promise<T> by
98 // capturing A.
99 template <typename A, typename F>
103  return Curried<RemoveCVRef<F>, A>(std::forward<F>(f), std::forward<A>(arg));
104 }
105 
106 // Promote a callable() -> T|Poll<T> to a PromiseFactory(A) -> Promise<T>
107 // by dropping the argument passed to the factory.
108 template <typename A, typename F>
109 absl::enable_if_t<!IsVoidCallable<ResultOf<F()>>::value,
110  PromiseLike<RemoveCVRef<F>>>
112  return PromiseLike<F>(std::move(f));
113 }
114 
115 // Promote a callable() -> T|Poll<T> to a PromiseFactory() -> Promise<T>
116 template <typename F>
117 absl::enable_if_t<!IsVoidCallable<ResultOf<F()>>::value,
118  PromiseLike<RemoveCVRef<F>>>
120  return PromiseLike<F>(std::move(f));
121 }
122 
123 // Given a callable(A) -> Promise<T>, name it a PromiseFactory and use it.
124 template <typename A, typename F>
125 absl::enable_if_t<IsVoidCallable<ResultOf<F(A)>>::value,
126  PromiseLike<decltype(std::declval<F>()(std::declval<A>()))>>
128  return f(std::forward<A>(arg));
129 }
130 
131 // Given a callable() -> Promise<T>, promote it to a
132 // PromiseFactory(A) -> Promise<T> by dropping the first argument.
133 template <typename A, typename F>
134 absl::enable_if_t<IsVoidCallable<ResultOf<F()>>::value,
135  PromiseLike<decltype(std::declval<F>()())>>
137  return f();
138 }
139 
140 // Given a callable() -> Promise<T>, name it a PromiseFactory and use it.
141 template <typename F>
142 absl::enable_if_t<IsVoidCallable<ResultOf<F()>>::value,
143  PromiseLike<decltype(std::declval<F>()())>>
145  return f();
146 };
147 
148 template <typename A, typename F>
150  private:
152 
153  public:
154  using Arg = A;
155  using Promise =
156  decltype(PromiseFactoryImpl(std::move(f_), std::declval<A>()));
157 
158  explicit PromiseFactory(F f) : f_(std::move(f)) {}
159 
160  Promise Once(Arg&& a) {
161  return PromiseFactoryImpl(std::move(f_), std::forward<Arg>(a));
162  }
163 
164  Promise Repeated(Arg&& a) const {
165  return PromiseFactoryImpl(f_, std::forward<Arg>(a));
166  }
167 };
168 
169 template <typename F>
170 class PromiseFactory<void, F> {
171  private:
173 
174  public:
175  using Arg = void;
176  using Promise = decltype(PromiseFactoryImpl(std::move(f_)));
177 
178  explicit PromiseFactory(F f) : f_(std::move(f)) {}
179 
181 
182  Promise Repeated() const { return PromiseFactoryImpl(f_); }
183 };
184 
185 } // namespace promise_detail
186 } // namespace grpc_core
187 
188 #endif // GRPC_CORE_LIB_PROMISE_DETAIL_PROMISE_FACTORY_H
grpc_core::promise_detail::Curried::arg_
GPR_NO_UNIQUE_ADDRESS Arg arg_
Definition: promise_factory.h:94
grpc_core::promise_detail::IsVoidCallable::value
static constexpr bool value
Definition: promise_factory.h:60
grpc_core::promise_detail::Curried::Curried
Curried(const F &f, Arg &&arg)
Definition: promise_factory.h:88
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::promise_detail::Curried::Result
decltype(std::declval< F >()(std::declval< Arg >())) Result
Definition: promise_factory.h:89
grpc_core::promise_detail::PromiseFactory< void, F >::PromiseFactory
PromiseFactory(F f)
Definition: promise_factory.h:178
absl::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: abseil-cpp/absl/meta/type_traits.h:631
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
grpc_core::promise_detail::PromiseFactory< void, T >::Arg
void Arg
Definition: promise_factory.h:154
Arg
Arg(64) -> Arg(128) ->Arg(256) ->Arg(512) ->Arg(1024) ->Arg(1536) ->Arg(2048) ->Arg(3072) ->Arg(4096) ->Arg(5120) ->Arg(6144) ->Arg(7168)
grpc_core::promise_detail::PromiseFactory::PromiseFactory
PromiseFactory(F f)
Definition: promise_factory.h:158
grpc_core::promise_detail::IsVoidCallable
Definition: promise_factory.h:59
grpc_core::promise_detail::PromiseFactory< void, F >::Once
Promise Once()
Definition: promise_factory.h:180
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
grpc_core::promise_detail::PromiseFactory::Once
Promise Once(Arg &&a)
Definition: promise_factory.h:160
hpack_encoder_fixtures::Args
Args({0, 16384})
grpc_core::promise_detail::PromiseFactory< void, F >::Arg
void Arg
Definition: promise_factory.h:175
grpc_core::promise_detail::Curried
Definition: promise_factory.h:84
arg
Definition: cmdline.cc:40
GPR_NO_UNIQUE_ADDRESS
#define GPR_NO_UNIQUE_ADDRESS
Definition: impl/codegen/port_platform.h:692
grpc_core::promise_detail::PromiseFactoryImpl
absl::enable_if_t<!IsVoidCallable< ResultOf< F(A)> >::value, PromiseLike< Curried< RemoveCVRef< F >, A > > > PromiseFactoryImpl(F &&f, A &&arg)
Definition: promise_factory.h:102
F
#define F(b, c, d)
Definition: md4.c:112
grpc_core::promise_detail::PromiseFactory< void, F >::Promise
decltype(PromiseFactoryImpl(std::move(f_))) Promise
Definition: promise_factory.h:176
value
const char * value
Definition: hpack_parser_table.cc:165
absl::void_t
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition: abseil-cpp/absl/meta/type_traits.h:218
grpc_core::promise_detail::ResultOf
typename ResultOfT< T >::T ResultOf
Definition: promise_factory.h:79
promise_like.h
grpc_core::promise_detail::PromiseFactory
Definition: promise_factory.h:149
grpc_core::promise_detail::PromiseFactory::Repeated
Promise Repeated(Arg &&a) const
Definition: promise_factory.h:164
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
grpc_core::promise_detail::PromiseFactory::f_
GPR_NO_UNIQUE_ADDRESS F f_
Definition: promise_factory.h:151
A
Definition: miscompile_with_no_unique_address_test.cc:23
grpc_core::promise_detail::PromiseFactory< void, F >::f_
GPR_NO_UNIQUE_ADDRESS F f_
Definition: promise_factory.h:172
grpc_core::promise_detail::RemoveCVRef
absl::remove_cv_t< absl::remove_reference_t< T > > RemoveCVRef
Definition: promise_like.h:80
grpc_core::promise_detail::PromiseFactory< void, T >::Promise
decltype(PromiseFactoryImpl(std::move(f_), std::declval< void >())) Promise
Definition: promise_factory.h:156
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::forward
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:230
grpc_core::promise_detail::PromiseFactory< void, F >::Repeated
Promise Repeated() const
Definition: promise_factory.h:182
grpc_core::promise_detail::PromiseLike
Definition: promise_like.h:67
grpc_core::promise_detail::ResultOfT< F(Args...), absl::void_t< decltype(std::declval< RemoveCVRef< F >>()(std::declval< Args >()...))> >::T
decltype(std::declval< RemoveCVRef< F > >()(std::declval< Args >()...)) T
Definition: promise_factory.h:75
grpc_core::promise_detail::ResultOfT
Definition: promise_factory.h:69
grpc_core::promise_detail::Curried::operator()
Result operator()()
Definition: promise_factory.h:90
grpc_core::promise_detail::Curried::Curried
Curried(F &&f, Arg &&arg)
Definition: promise_factory.h:86
grpc_core::promise_detail::Curried::f_
GPR_NO_UNIQUE_ADDRESS F f_
Definition: promise_factory.h:93
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:55