C/C++ API Reference
Loading...
Searching...
No Matches
allocator.h
1// Copyright 2023 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://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, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <cstddef>
17
18#include "pw_allocator/capability.h"
19#include "pw_allocator/config.h"
20#include "pw_allocator/deallocator.h"
21#include "pw_allocator/layout.h"
22#include "pw_allocator/shared_ptr.h"
23#include "pw_allocator/unique_ptr.h"
24#include "pw_numeric/checked_arithmetic.h"
25#include "pw_result/result.h"
26
27namespace pw {
28
30
36class Allocator : public Deallocator {
37 public:
44 void* Allocate(Layout layout) {
45 return layout.size() != 0 ? DoAllocate(layout) : nullptr;
46 }
47
56 template <typename T, int&... kExplicitGuard, typename... Args>
57 [[nodiscard]] std::enable_if_t<!std::is_array_v<T>, T*> New(Args&&... args) {
58 void* ptr = Allocate(Layout::Of<T>());
59 return ptr != nullptr ? new (ptr) T(std::forward<Args>(args)...) : nullptr;
60 }
61
70 template <typename T,
71 int&... kExplicitGuard,
72 typename ElementType = std::remove_extent_t<T>,
73 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
74 [[nodiscard]] ElementType* New() {
75 return NewArrayImpl<ElementType>(std::extent_v<T>, alignof(ElementType));
76 }
77
86 template <typename T,
87 int&... kExplicitGuard,
88 typename ElementType = std::remove_extent_t<T>,
89 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
90 [[nodiscard]] ElementType* New(size_t count) {
91 return NewArrayImpl<ElementType>(count, alignof(ElementType));
92 }
93
95 //
103 template <typename T,
104 int&... kExplicitGuard,
105 typename ElementType = std::remove_extent_t<T>,
106 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
107 [[nodiscard]] ElementType* New(size_t count, size_t alignment) {
108 return NewArrayImpl<ElementType>(count, alignment);
109 }
110
115 template <typename T>
116 T* NewArray(size_t count) {
117 return New<T[]>(count, alignof(T));
118 }
119
124 template <typename T>
125 T* NewArray(size_t count, size_t alignment) {
126 return New<T[]>(count, alignment);
127 }
128
137 template <typename T,
138 int&... kExplicitGuard,
139 std::enable_if_t<!std::is_array_v<T>, int> = 0,
140 typename... Args>
141 [[nodiscard]] UniquePtr<T> MakeUnique(Args&&... args) {
142 return UniquePtr<T>(New<T>(std::forward<Args>(args)...), *this);
143 }
144
152 template <typename T,
153 int&... kExplicitGuard,
154 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
155 [[nodiscard]] UniquePtr<T> MakeUnique(size_t size) {
156 return MakeUnique<T>(size, alignof(std::remove_extent_t<T>));
157 }
158
168 template <typename T,
169 int&... kExplicitGuard,
170 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
171 [[nodiscard]] UniquePtr<T> MakeUnique(size_t size, size_t alignment) {
172 return UniquePtr<T>(New<T>(size, alignment), size, *this);
173 }
174
181 template <typename T,
182 int&... kExplicitGuard,
183 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
184 [[nodiscard]] UniquePtr<T> MakeUnique() {
185 return UniquePtr<T>(New<T>(), std::extent_v<T>, this);
186 }
187
192 template <typename T>
193 [[nodiscard]] UniquePtr<T[]> MakeUniqueArray(size_t size) {
194 return MakeUnique<T[]>(size, alignof(std::remove_extent_t<T>));
195 }
196
201 template <typename T>
202 [[nodiscard]] UniquePtr<T[]> MakeUniqueArray(size_t size, size_t alignment) {
203 return MakeUnique<T[]>(size, alignment);
204 }
205
206// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
207#if PW_ALLOCATOR_HAS_ATOMICS
208
216 template <typename T,
217 int&... kExplicitGuard,
218 std::enable_if_t<!std::is_array_v<T>, int> = 0,
219 typename... Args>
220 [[nodiscard]] SharedPtr<T> MakeShared(Args&&... args) {
221 return SharedPtr<T>::template Create<Args...>(this,
222 std::forward<Args>(args)...);
223 }
224
232 template <typename T,
233 int&... kExplicitGuard,
234 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
235 [[nodiscard]] SharedPtr<T> MakeShared(size_t size) {
236 return MakeShared<T>(size, alignof(std::remove_extent_t<T>));
237 }
238
248 template <typename T,
249 int&... kExplicitGuard,
250 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
251 [[nodiscard]] SharedPtr<T> MakeShared(size_t size, size_t alignment) {
252 return SharedPtr<T>::Create(this, size, alignment);
253 }
254
264 template <typename T,
265 int&... kExplicitGuard,
266 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
267 [[nodiscard]] SharedPtr<T> MakeShared() {
269 this, std::extent_v<T>, alignof(std::remove_extent_t<T>));
270 }
271
272// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
273#endif // PW_ALLOCATOR_HAS_ATOMICS
274
287 bool Resize(void* ptr, size_t new_size) {
288 return ptr != nullptr && new_size != 0 && DoResize(ptr, new_size);
289 }
290
294 bool Resize(void* ptr, Layout layout, size_t new_size) {
295 return ptr != nullptr && new_size != 0 && DoResize(ptr, layout, new_size);
296 }
297
321 void* Reallocate(void* ptr, Layout new_layout) {
322 if (new_layout.size() == 0) {
323 return nullptr;
324 }
325 if (ptr == nullptr) {
326 return Allocate(new_layout);
327 }
328 return DoReallocate(ptr, new_layout);
329 }
330
334 void* Reallocate(void* ptr, Layout old_layout, size_t new_size) {
335 if (new_size == 0) {
336 return nullptr;
337 }
338 if (ptr == nullptr) {
339 return Allocate(Layout(new_size, old_layout.alignment()));
340 }
341 return DoReallocate(ptr, old_layout, new_size);
342 }
343
346 size_t GetAllocated() const { return DoGetAllocated(); }
347
348 protected:
350 constexpr Allocator() = default;
351
352 explicit constexpr Allocator(const Capabilities& capabilities)
353 : Deallocator(capabilities) {}
354
355 private:
360 virtual void* DoAllocate(Layout layout) = 0;
361
369 virtual bool DoResize([[maybe_unused]] void* ptr,
370 [[maybe_unused]] size_t new_size) {
371 return false;
372 }
373
377 virtual bool DoResize(void*, Layout, size_t) { return false; }
378
388 virtual void* DoReallocate(void* ptr, Layout new_layout);
389
393 virtual void* DoReallocate(void* ptr, Layout old_layout, size_t new_size);
394
399 virtual size_t DoGetAllocated() const { return size_t(-1); }
400
401 // Helper method for allocating arrays of objects.
402 template <typename ElementType>
403 ElementType* NewArrayImpl(size_t count, size_t alignment) {
404 void* ptr = Allocate(Layout::Of<ElementType[]>(count).Align(alignment));
405 return ptr != nullptr ? new (ptr) ElementType[count] : nullptr;
406 }
407};
408
409namespace allocator {
410
411// Alias for module consumers using the older name for the above type.
412using Allocator = ::pw::Allocator;
413
414} // namespace allocator
415
417
418} // namespace pw
Definition: allocator.h:36
SharedPtr< T > MakeShared(size_t size)
Definition: allocator.h:235
UniquePtr< T > MakeUnique(size_t size, size_t alignment)
Definition: allocator.h:171
ElementType * New(size_t count, size_t alignment)
Constructs an alignment-byte aligned array of count objects.
Definition: allocator.h:107
SharedPtr< T > MakeShared(Args &&... args)
Definition: allocator.h:220
UniquePtr< T > MakeUnique()
Definition: allocator.h:184
T * NewArray(size_t count)
Definition: allocator.h:116
virtual size_t DoGetAllocated() const
Definition: allocator.h:399
T * NewArray(size_t count, size_t alignment)
Definition: allocator.h:125
virtual void * DoAllocate(Layout layout)=0
constexpr Allocator()=default
TODO(b/326509341): Remove when downstream consumers migrate.
SharedPtr< T > MakeShared(size_t size, size_t alignment)
Definition: allocator.h:251
bool Resize(void *ptr, size_t new_size)
Definition: allocator.h:287
virtual void * DoReallocate(void *ptr, Layout new_layout)
UniquePtr< T[]> MakeUniqueArray(size_t size)
Definition: allocator.h:193
virtual void * DoReallocate(void *ptr, Layout old_layout, size_t new_size)
void * Reallocate(void *ptr, Layout new_layout)
Definition: allocator.h:321
void * Reallocate(void *ptr, Layout old_layout, size_t new_size)
Definition: allocator.h:334
UniquePtr< T > MakeUnique(Args &&... args)
Definition: allocator.h:141
virtual bool DoResize(void *, Layout, size_t)
Definition: allocator.h:377
std::enable_if_t<!std::is_array_v< T >, T * > New(Args &&... args)
Definition: allocator.h:57
bool Resize(void *ptr, Layout layout, size_t new_size)
Definition: allocator.h:294
void * Allocate(Layout layout)
Definition: allocator.h:44
SharedPtr< T > MakeShared()
Definition: allocator.h:267
ElementType * New(size_t count)
Definition: allocator.h:90
UniquePtr< T[]> MakeUniqueArray(size_t size, size_t alignment)
Definition: allocator.h:202
ElementType * New()
Definition: allocator.h:74
UniquePtr< T > MakeUnique(size_t size)
Definition: allocator.h:155
size_t GetAllocated() const
Definition: allocator.h:346
virtual bool DoResize(void *ptr, size_t new_size)
Definition: allocator.h:369
Abstract interface for releasing memory.
Definition: deallocator.h:29
Definition: shared_ptr.h:59
Definition: unique_ptr.h:43
Definition: capability.h:64
Definition: layout.h:58
static constexpr std::enable_if_t<!std::is_array_v< T >, Layout > Of()
Creates a Layout for the given type.
Definition: layout.h:68
The Pigweed namespace.
Definition: alignment.h:27