GRPC Core  58.0.0
memory_allocator.h
Go to the documentation of this file.
1 // Copyright 2021 The 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 #ifndef GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
15 #define GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
16 
18 #include <grpc/slice.h>
20 #include <stdlib.h> // for abort()
21 
22 #include <algorithm>
23 #include <memory>
24 #include <type_traits>
25 #include <utility>
26 #include <vector>
27 
28 namespace grpc_event_engine {
29 namespace experimental {
30 
31 // Tracks memory allocated by one system.
32 // Is effectively a thin wrapper/smart pointer for a MemoryAllocatorImpl,
33 // providing a convenient and stable API.
35  public:
39  explicit MemoryAllocator(
40  std::shared_ptr<internal::MemoryAllocatorImpl> allocator)
41  : allocator_(std::move(allocator)) {}
42  // Construct an invalid MemoryAllocator.
43  MemoryAllocator() : allocator_(nullptr) {}
45  if (allocator_ != nullptr) allocator_->Shutdown();
46  }
47 
48  MemoryAllocator(const MemoryAllocator&) = delete;
49  MemoryAllocator& operator=(const MemoryAllocator&) = delete;
50 
51  MemoryAllocator(MemoryAllocator&&) = default;
53 
54  bool IsValid() const { return allocator_ != nullptr; }
55 
59  void Reset() {
60  auto a = std::move(allocator_);
61  if (a != nullptr) a->Shutdown();
62  }
63 
67  size_t Reserve(MemoryRequest request) { return allocator_->Reserve(request); }
68 
70  void Release(size_t n) { return allocator_->Release(n); }
71 
72  //
73  // The remainder of this type are helper functions implemented in terms of
74  // Reserve/Release.
75  //
76 
78  class Reservation {
79  public:
80  Reservation() = default;
81  Reservation(const Reservation&) = delete;
82  Reservation& operator=(const Reservation&) = delete;
83  Reservation(Reservation&&) = default;
84  Reservation& operator=(Reservation&&) = default;
86  if (allocator_ != nullptr) allocator_->Release(size_);
87  }
88 
89  private:
90  friend class MemoryAllocator;
91  Reservation(std::shared_ptr<internal::MemoryAllocatorImpl> allocator,
92  size_t size)
93  : allocator_(std::move(allocator)), size_(size) {}
94 
95  std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
96  size_t size_ = 0;
97  };
98 
102  return Reservation(allocator_, Reserve(request));
103  }
104 
109  template <typename T, typename... Args>
110  typename std::enable_if<std::has_virtual_destructor<T>::value, T*>::type New(
111  Args&&... args) {
112  // Wrap T such that when it's destroyed, we can release memory back to the
113  // allocator.
114  class Wrapper final : public T {
115  public:
116  explicit Wrapper(std::shared_ptr<internal::MemoryAllocatorImpl> allocator,
117  Args&&... args)
118  : T(std::forward<Args>(args)...), allocator_(std::move(allocator)) {}
119  ~Wrapper() override { allocator_->Release(sizeof(*this)); }
120 
121  private:
122  const std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
123  };
124  Reserve(sizeof(Wrapper));
125  return new Wrapper(allocator_, std::forward<Args>(args)...);
126  }
127 
129  template <typename T, typename... Args>
130  std::unique_ptr<T> MakeUnique(Args&&... args) {
131  return std::unique_ptr<T>(New<T>(std::forward<Args>(args)...));
132  }
133 
139  return allocator_->MakeSlice(request);
140  }
141 
143  template <typename T>
144  class Container {
145  public:
146  using value_type = T;
147 
151  : underlying_allocator_(underlying_allocator) {}
152  template <typename U>
153  explicit Container(const Container<U>& other)
154  : underlying_allocator_(other.underlying_allocator()) {}
155 
157  return underlying_allocator_;
158  }
159 
160  T* allocate(size_t n) {
161  underlying_allocator_->Reserve(n * sizeof(T));
162  return static_cast<T*>(::operator new(n * sizeof(T)));
163  }
164  void deallocate(T* p, size_t n) {
165  ::operator delete(p);
166  underlying_allocator_->Release(n * sizeof(T));
167  }
168 
169  private:
170  MemoryAllocator* underlying_allocator_;
171  };
172 
173  protected:
178  return allocator_.get();
179  }
180 
182  return allocator_.get();
183  }
184 
185  private:
186  std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
187 };
188 
189 // Wrapper type around std::vector to make initialization against a
190 // MemoryAllocator based container allocator easy.
191 template <typename T>
192 class Vector : public std::vector<T, MemoryAllocator::Container<T>> {
193  public:
194  explicit Vector(MemoryAllocator* allocator)
195  : std::vector<T, MemoryAllocator::Container<T>>(
196  MemoryAllocator::Container<T>(allocator)) {}
197 };
198 
200  public:
201  virtual ~MemoryAllocatorFactory() = default;
208  virtual MemoryAllocator CreateMemoryAllocator(absl::string_view name) = 0;
209 };
210 
211 } // namespace experimental
212 } // namespace grpc_event_engine
213 
214 #endif // GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
grpc_event_engine::experimental::MemoryAllocator::MakeSlice
grpc_slice MakeSlice(MemoryRequest request)
Allocate a slice, using MemoryRequest to size the number of returned bytes.
Definition: memory_allocator.h:138
grpc_event_engine::experimental::MemoryAllocator::get_internal_impl_ptr
const internal::MemoryAllocatorImpl * get_internal_impl_ptr() const
Definition: memory_allocator.h:181
grpc_event_engine::experimental::MemoryAllocator::Reservation::operator=
Reservation & operator=(const Reservation &)=delete
grpc_event_engine::experimental::MemoryAllocator::MemoryAllocator
MemoryAllocator(std::shared_ptr< internal::MemoryAllocatorImpl > allocator)
Construct a MemoryAllocator given an internal::MemoryAllocatorImpl implementation.
Definition: memory_allocator.h:39
grpc_event_engine::experimental::MemoryAllocator::get_internal_impl_ptr
internal::MemoryAllocatorImpl * get_internal_impl_ptr()
Return a pointer to the underlying implementation.
Definition: memory_allocator.h:177
grpc_event_engine::experimental::MemoryAllocator::Container
A C++ allocator for containers of T.
Definition: memory_allocator.h:144
grpc_event_engine::experimental::Vector::Vector
Vector(MemoryAllocator *allocator)
Definition: memory_allocator.h:194
grpc_event_engine::experimental::MemoryAllocator::Reservation::~Reservation
~Reservation()
Definition: memory_allocator.h:85
grpc_event_engine::experimental::MemoryAllocator::Container::Container
Container(MemoryAllocator *underlying_allocator)
Construct the allocator: underlying_allocator is borrowed, and must outlive this object.
Definition: memory_allocator.h:150
grpc_event_engine::experimental::MemoryAllocator::Release
void Release(size_t n)
Release some bytes that were previously reserved.
Definition: memory_allocator.h:70
grpc_event_engine::experimental::MemoryAllocator::Reserve
size_t Reserve(MemoryRequest request)
Reserve bytes from the quota.
Definition: memory_allocator.h:67
grpc_event_engine::experimental::MemoryAllocatorFactory::CreateMemoryAllocator
virtual MemoryAllocator CreateMemoryAllocator(absl::string_view name)=0
On Endpoint creation, call CreateMemoryAllocator to create a new allocator for the endpoint.
grpc_event_engine::experimental::Vector
Definition: memory_allocator.h:192
grpc_event_engine::experimental::MemoryAllocator::Reset
void Reset()
Drop the underlying allocator and make this an empty object.
Definition: memory_allocator.h:59
grpc_event_engine::experimental::MemoryAllocator::Reservation::Reservation
Reservation()=default
grpc_event_engine::experimental::MemoryAllocator::New
std::enable_if< std::has_virtual_destructor< T >::value, T * >::type New(Args &&... args)
Allocate a new object of type T, with constructor arguments.
Definition: memory_allocator.h:110
grpc_event_engine::experimental::internal::MemoryAllocatorImpl
Underlying memory allocation interface.
Definition: memory_allocator_impl.h:34
grpc_event_engine::experimental::MemoryAllocator::MakeUnique
std::unique_ptr< T > MakeUnique(Args &&... args)
Construct a unique_ptr immediately.
Definition: memory_allocator.h:130
grpc_event_engine::experimental::MemoryRequest
Reservation request - how much memory do we want to allocate?
Definition: memory_request.h:28
memory_allocator_impl.h
grpc_event_engine::experimental::MemoryAllocator::Container::value_type
T value_type
Definition: memory_allocator.h:146
grpc_event_engine::experimental::MemoryAllocator::Container::deallocate
void deallocate(T *p, size_t n)
Definition: memory_allocator.h:164
grpc_event_engine::experimental::MemoryAllocator::IsValid
bool IsValid() const
Definition: memory_allocator.h:54
grpc_event_engine::experimental::MemoryAllocator::Container::Container
Container(const Container< U > &other)
Definition: memory_allocator.h:153
grpc_slice
A grpc_slice s, if initialized, represents the byte range s.bytes[0..s.length-1].
Definition: slice_type.h:62
grpc_event_engine::experimental::MemoryAllocatorFactory
Definition: memory_allocator.h:199
grpc_event_engine::experimental::MemoryAllocator::Container::underlying_allocator
MemoryAllocator * underlying_allocator() const
Definition: memory_allocator.h:156
grpc_event_engine
Definition: endpoint_config.h:24
grpc_event_engine::experimental::MemoryAllocator
Definition: memory_allocator.h:34
grpc_event_engine::experimental::MemoryAllocatorFactory::~MemoryAllocatorFactory
virtual ~MemoryAllocatorFactory()=default
grpc_event_engine::experimental::MemoryAllocator::Reservation
An automatic releasing reservation of memory.
Definition: memory_allocator.h:78
grpc_event_engine::experimental::MemoryAllocator::operator=
MemoryAllocator & operator=(const MemoryAllocator &)=delete
grpc_event_engine::experimental::MemoryAllocator::MemoryAllocator
MemoryAllocator()
Definition: memory_allocator.h:43
slice.h
grpc_event_engine::experimental::MemoryAllocator::Container::allocate
T * allocate(size_t n)
Definition: memory_allocator.h:160
grpc_event_engine::experimental::MemoryAllocator::MakeReservation
Reservation MakeReservation(MemoryRequest request)
Reserve bytes from the quota and automatically release them when Reservation is destroyed.
Definition: memory_allocator.h:101
grpc_event_engine::experimental::MemoryAllocator::~MemoryAllocator
~MemoryAllocator()
Definition: memory_allocator.h:44
port_platform.h