arena_promise.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_ARENA_PROMISE_H
16 #define GRPC_CORE_LIB_PROMISE_ARENA_PROMISE_H
17 
19 
20 #include <stdlib.h>
21 
22 #include <type_traits>
23 #include <utility>
24 
25 #include "absl/meta/type_traits.h"
26 
30 
31 namespace grpc_core {
32 
33 namespace arena_promise_detail {
34 
35 // Type erased promise stored in the arena.
36 template <typename T>
38  public:
39  // Poll the promise, once.
40  virtual Poll<T> PollOnce() = 0;
41  // Destroy the underlying callable object if there is one.
42  // Since we don't delete (the arena owns the memory) but we may need to call a
43  // destructor, we expose this for when the ArenaPromise object is destroyed.
44  virtual void Destroy() = 0;
45 
46  protected:
47  ~ImplInterface() = default;
48 };
49 
50 // Implementation of ImplInterface for an empty object.
51 // Used when an empty ArenaPromise is created, or when the ArenaPromise is moved
52 // from. Since in either case these objects should not be polled, we simply
53 // crash if it is.
54 template <typename T>
55 class NullImpl final : public ImplInterface<T> {
56  public:
57  Poll<T> PollOnce() override {
58  abort();
59  GPR_UNREACHABLE_CODE(return Pending{});
60  }
61  void Destroy() override {}
62 
63  static ImplInterface<T>* Get() {
64  static NullImpl<T> instance;
65  return &instance;
66  }
67 
68  private:
69  ~NullImpl() = default;
70 };
71 
72 // Implementation of ImplInterface for a callable object.
73 template <typename T, typename Callable>
74 class CallableImpl final : public ImplInterface<T> {
75  public:
76  explicit CallableImpl(Callable&& callable) : callable_(std::move(callable)) {}
77  // Forward polls to the callable object.
78  Poll<T> PollOnce() override { return poll_cast<T>(callable_()); }
79  // Destroy destructs the callable object.
80  void Destroy() override { this->~CallableImpl(); }
81 
82  private:
83  // Should only be called by Destroy().
84  ~CallableImpl() = default;
85 
86  Callable callable_;
87 };
88 
89 // If a callable object is empty we can substitute any instance of that callable
90 // for the one we call (for how could we tell the difference)?
91 // Since this corresponds to a lambda with no fields, and we expect these to be
92 // reasonably common, we can elide the arena allocation entirely and simply poll
93 // a global shared instance.
94 // (this comes up often when the promise only accesses context data from the
95 // containing activity).
96 template <typename T, typename Callable>
97 class SharedImpl final : public ImplInterface<T>, private Callable {
98  public:
99  // Call the callable, or at least an exact duplicate of it - if you have no
100  // members, all your instances look the same.
101  Poll<T> PollOnce() override { return Callable::operator()(); }
102  // Nothing to destroy.
103  void Destroy() override {}
104  // Return a pointer to the shared instance - these are singletons, and are
105  // needed just to get the vtable in place.
106  static SharedImpl* Get(Callable&& callable) {
107  static_assert(sizeof(SharedImpl) == sizeof(void*),
108  "SharedImpl should be pointer sized");
109  static SharedImpl impl(std::forward<Callable>(callable));
110  return &impl;
111  }
112 
113  private:
114  explicit SharedImpl(Callable&& callable)
115  : Callable(std::forward<Callable>(callable)) {}
116  ~SharedImpl() = default;
117 };
118 
119 // Redirector type: given a callable type, expose a Make() function that creates
120 // the appropriate underlying implementation.
121 template <typename T, typename Callable, typename Ignored = void>
123 
124 template <typename T, typename Callable>
126  T, Callable, absl::enable_if_t<!std::is_empty<Callable>::value>> {
127  static ImplInterface<T>* Make(Callable&& callable) {
128  return GetContext<Arena>()->template New<CallableImpl<T, Callable>>(
129  std::forward<Callable>(callable));
130  }
131 };
132 
133 template <typename T, typename Callable>
135  T, Callable, absl::enable_if_t<std::is_empty<Callable>::value>> {
136  static ImplInterface<T>* Make(Callable&& callable) {
137  return SharedImpl<T, Callable>::Get(std::forward<Callable>(callable));
138  }
139 };
140 
141 // Wrap ChooseImplForCallable with a friend approachable syntax.
142 template <typename T, typename Callable>
143 ImplInterface<T>* MakeImplForCallable(Callable&& callable) {
145  std::forward<Callable>(callable));
146 }
147 
148 } // namespace arena_promise_detail
149 
150 // A promise for which the state memory is allocated from an arena.
151 template <typename T>
153  public:
154  // Construct an empty, uncallable, invalid ArenaPromise.
155  ArenaPromise() = default;
156 
157  // Construct an ArenaPromise that will call the given callable when polled.
158  template <typename Callable,
159  typename Ignored =
161  // NOLINTNEXTLINE(google-explicit-constructor)
162  ArenaPromise(Callable&& callable)
163  : impl_(arena_promise_detail::MakeImplForCallable<T>(
164  std::forward<Callable>(callable))) {}
165 
166  // ArenaPromise is not copyable.
167  ArenaPromise(const ArenaPromise&) = delete;
168  ArenaPromise& operator=(const ArenaPromise&) = delete;
169  // ArenaPromise is movable.
170  ArenaPromise(ArenaPromise&& other) noexcept : impl_(other.impl_) {
172  }
173  ArenaPromise& operator=(ArenaPromise&& other) noexcept {
174  impl_->Destroy();
175  impl_ = other.impl_;
177  return *this;
178  }
179 
180  // Destruction => call Destroy on the underlying impl object.
181  ~ArenaPromise() { impl_->Destroy(); }
182 
183  // Expose the promise interface: a call operator that returns Poll<T>.
184  Poll<T> operator()() { return impl_->PollOnce(); }
185 
186  bool has_value() const {
188  }
189 
190  private:
191  // Underlying impl object.
194 };
195 
196 } // namespace grpc_core
197 
198 #endif /* GRPC_CORE_LIB_PROMISE_ARENA_PROMISE_H */
grpc_core::ArenaPromise::~ArenaPromise
~ArenaPromise()
Definition: arena_promise.h:181
grpc_core::arena_promise_detail::CallableImpl::callable_
Callable callable_
Definition: arena_promise.h:86
grpc_core::arena_promise_detail::ChooseImplForCallable< T, Callable, absl::enable_if_t< std::is_empty< Callable >::value > >::Make
static ImplInterface< T > * Make(Callable &&callable)
Definition: arena_promise.h:136
grpc_core::arena_promise_detail::ImplInterface
Definition: arena_promise.h:37
grpc_core::arena_promise_detail::NullImpl
Definition: arena_promise.h:55
grpc_core::arena_promise_detail::ImplInterface::PollOnce
virtual Poll< T > PollOnce()=0
grpc_core::ArenaPromise::impl_
arena_promise_detail::ImplInterface< T > * impl_
Definition: arena_promise.h:192
grpc_core::arena_promise_detail::CallableImpl::Destroy
void Destroy() override
Definition: arena_promise.h:80
grpc_core
Definition: call_metric_recorder.h:31
re2::Ignored
int Ignored
Definition: bloaty/third_party/re2/re2/regexp.cc:534
grpc_core::arena_promise_detail::NullImpl::Get
static ImplInterface< T > * Get()
Definition: arena_promise.h:63
arena.h
grpc_core::arena_promise_detail::CallableImpl
Definition: arena_promise.h:74
instance
RefCountedPtr< grpc_tls_certificate_provider > instance
Definition: xds_server_config_fetcher.cc:224
grpc_core::ArenaPromise::operator=
ArenaPromise & operator=(ArenaPromise &&other) noexcept
Definition: arena_promise.h:173
absl::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: abseil-cpp/absl/meta/type_traits.h:631
grpc_core::arena_promise_detail::ImplInterface::~ImplInterface
~ImplInterface()=default
grpc_core::ArenaPromise::operator()
Poll< T > operator()()
Definition: arena_promise.h:184
T
#define T(upbtypeconst, upbtype, ctype, default_value)
grpc_core::Pending
Definition: poll.h:29
grpc_core::arena_promise_detail::SharedImpl::PollOnce
Poll< T > PollOnce() override
Definition: arena_promise.h:101
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
grpc_core::arena_promise_detail::NullImpl::~NullImpl
~NullImpl()=default
grpc_core::arena_promise_detail::MakeImplForCallable
ImplInterface< T > * MakeImplForCallable(Callable &&callable)
Definition: arena_promise.h:143
GPR_UNREACHABLE_CODE
#define GPR_UNREACHABLE_CODE(STATEMENT)
Definition: impl/codegen/port_platform.h:652
grpc_core::arena_promise_detail::NullImpl::PollOnce
Poll< T > PollOnce() override
Definition: arena_promise.h:57
grpc_core::arena_promise_detail::CallableImpl::CallableImpl
CallableImpl(Callable &&callable)
Definition: arena_promise.h:76
grpc_core::ArenaPromise::operator=
ArenaPromise & operator=(const ArenaPromise &)=delete
grpc_core::arena_promise_detail::CallableImpl::~CallableImpl
~CallableImpl()=default
grpc_core::ArenaPromise::ArenaPromise
ArenaPromise(Callable &&callable)
Definition: arena_promise.h:162
grpc_core::arena_promise_detail::ChooseImplForCallable
Definition: arena_promise.h:122
grpc_core::arena_promise_detail::ChooseImplForCallable< T, Callable, absl::enable_if_t<!std::is_empty< Callable >::value > >::Make
static ImplInterface< T > * Make(Callable &&callable)
Definition: arena_promise.h:127
grpc_core::ArenaPromise
Definition: arena_promise.h:152
poll.h
grpc_core::ArenaPromise::has_value
bool has_value() const
Definition: arena_promise.h:186
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
grpc_core::ArenaPromise::ArenaPromise
ArenaPromise()=default
grpc_core::arena_promise_detail::SharedImpl
Definition: arena_promise.h:97
grpc_core::arena_promise_detail::SharedImpl::~SharedImpl
~SharedImpl()=default
context.h
grpc_core::arena_promise_detail::NullImpl::Destroy
void Destroy() override
Definition: arena_promise.h:61
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
grpc_core::arena_promise_detail::ImplInterface::Destroy
virtual void Destroy()=0
absl::forward
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:230
grpc_core::arena_promise_detail::SharedImpl::SharedImpl
SharedImpl(Callable &&callable)
Definition: arena_promise.h:114
absl::variant
Definition: abseil-cpp/absl/types/internal/variant.h:46
grpc_core::ArenaPromise::ArenaPromise
ArenaPromise(ArenaPromise &&other) noexcept
Definition: arena_promise.h:170
grpc_core::arena_promise_detail::CallableImpl::PollOnce
Poll< T > PollOnce() override
Definition: arena_promise.h:78
grpc_core::arena_promise_detail::SharedImpl::Get
static SharedImpl * Get(Callable &&callable)
Definition: arena_promise.h:106
port_platform.h
grpc_core::arena_promise_detail::SharedImpl::Destroy
void Destroy() override
Definition: arena_promise.h:103


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:42