Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
34class Allocator : public Deallocator {
35 public:
42 void* Allocate(Layout layout) {
43 return layout.size() != 0 ? DoAllocate(layout) : nullptr;
44 }
45
54 template <typename T, int&... kExplicitGuard, typename... Args>
55 [[nodiscard]] std::enable_if_t<!std::is_array_v<T>, T*> New(Args&&... args) {
56 void* ptr = Allocate(Layout::Of<T>());
57 return ptr != nullptr ? new (ptr) T(std::forward<Args>(args)...) : nullptr;
58 }
59
68 template <typename T,
69 int&... kExplicitGuard,
70 typename ElementType = std::remove_extent_t<T>,
71 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
72 [[nodiscard]] ElementType* New() {
73 return NewArrayImpl<ElementType>(std::extent_v<T>, alignof(ElementType));
74 }
75
84 template <typename T,
85 int&... kExplicitGuard,
86 typename ElementType = std::remove_extent_t<T>,
87 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
88 [[nodiscard]] ElementType* New(size_t count) {
89 return NewArrayImpl<ElementType>(count, alignof(ElementType));
90 }
91
93 //
101 template <typename T,
102 int&... kExplicitGuard,
103 typename ElementType = std::remove_extent_t<T>,
104 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
105 [[nodiscard]] ElementType* New(size_t count, size_t alignment) {
106 return NewArrayImpl<ElementType>(count, alignment);
107 }
108
113 template <typename T>
114 T* NewArray(size_t count) {
115 return New<T[]>(count, alignof(T));
116 }
117
122 template <typename T>
123 T* NewArray(size_t count, size_t alignment) {
124 return New<T[]>(count, alignment);
125 }
126
135 template <typename T,
136 int&... kExplicitGuard,
137 std::enable_if_t<!std::is_array_v<T>, int> = 0,
138 typename... Args>
139 [[nodiscard]] UniquePtr<T> MakeUnique(Args&&... args) {
140 return UniquePtr<T>(New<T>(std::forward<Args>(args)...), *this);
141 }
142
150 template <typename T,
151 int&... kExplicitGuard,
152 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
153 [[nodiscard]] UniquePtr<T> MakeUnique(size_t size) {
154 return MakeUnique<T>(size, alignof(std::remove_extent_t<T>));
155 }
156
166 template <typename T,
167 int&... kExplicitGuard,
168 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
169 [[nodiscard]] UniquePtr<T> MakeUnique(size_t size, size_t alignment) {
170 return UniquePtr<T>(New<T>(size, alignment), size, *this);
171 }
172
179 template <typename T,
180 int&... kExplicitGuard,
181 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
182 [[nodiscard]] UniquePtr<T> MakeUnique() {
183 return UniquePtr<T>(New<T>(), std::extent_v<T>, this);
184 }
185
190 template <typename T>
191 [[nodiscard]] UniquePtr<T[]> MakeUniqueArray(size_t size) {
192 return MakeUnique<T[]>(size, alignof(std::remove_extent_t<T>));
193 }
194
199 template <typename T>
200 [[nodiscard]] UniquePtr<T[]> MakeUniqueArray(size_t size, size_t alignment) {
201 return MakeUnique<T[]>(size, alignment);
202 }
203
204// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
205#if PW_ALLOCATOR_HAS_ATOMICS
206
214 template <typename T,
215 int&... kExplicitGuard,
216 std::enable_if_t<!std::is_array_v<T>, int> = 0,
217 typename... Args>
218 [[nodiscard]] SharedPtr<T> MakeShared(Args&&... args) {
219 return SharedPtr<T>::template Create<Args...>(this,
220 std::forward<Args>(args)...);
221 }
222
230 template <typename T,
231 int&... kExplicitGuard,
232 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
233 [[nodiscard]] SharedPtr<T> MakeShared(size_t size) {
234 return MakeShared<T>(size, alignof(std::remove_extent_t<T>));
235 }
236
246 template <typename T,
247 int&... kExplicitGuard,
248 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
249 [[nodiscard]] SharedPtr<T> MakeShared(size_t size, size_t alignment) {
250 return SharedPtr<T>::Create(this, size, alignment);
251 }
252
262 template <typename T,
263 int&... kExplicitGuard,
264 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
265 [[nodiscard]] SharedPtr<T> MakeShared() {
267 this, std::extent_v<T>, alignof(std::remove_extent_t<T>));
268 }
269
270// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
271#endif // PW_ALLOCATOR_HAS_ATOMICS
272
285 bool Resize(void* ptr, size_t new_size) {
286 return ptr != nullptr && new_size != 0 && DoResize(ptr, new_size);
287 }
288
292 bool Resize(void* ptr, Layout layout, size_t new_size) {
293 return ptr != nullptr && new_size != 0 && DoResize(ptr, layout, new_size);
294 }
295
319 void* Reallocate(void* ptr, Layout new_layout) {
320 if (new_layout.size() == 0) {
321 return nullptr;
322 }
323 if (ptr == nullptr) {
324 return Allocate(new_layout);
325 }
326 return DoReallocate(ptr, new_layout);
327 }
328
332 void* Reallocate(void* ptr, Layout old_layout, size_t new_size) {
333 if (new_size == 0) {
334 return nullptr;
335 }
336 if (ptr == nullptr) {
337 return Allocate(Layout(new_size, old_layout.alignment()));
338 }
339 return DoReallocate(ptr, old_layout, new_size);
340 }
341
344 size_t GetAllocated() const { return DoGetAllocated(); }
345
346 protected:
348 constexpr Allocator() = default;
349
350 explicit constexpr Allocator(const Capabilities& capabilities)
351 : Deallocator(capabilities) {}
352
353 private:
358 virtual void* DoAllocate(Layout layout) = 0;
359
367 virtual bool DoResize([[maybe_unused]] void* ptr,
368 [[maybe_unused]] size_t new_size) {
369 return false;
370 }
371
375 virtual bool DoResize(void*, Layout, size_t) { return false; }
376
386 virtual void* DoReallocate(void* ptr, Layout new_layout);
387
391 virtual void* DoReallocate(void* ptr, Layout old_layout, size_t new_size);
392
397 virtual size_t DoGetAllocated() const { return size_t(-1); }
398
399 // Helper method for allocating arrays of objects.
400 template <typename ElementType>
401 ElementType* NewArrayImpl(size_t count, size_t alignment) {
402 void* ptr = Allocate(Layout::Of<ElementType[]>(count).Align(alignment));
403 return ptr != nullptr ? new (ptr) ElementType[count] : nullptr;
404 }
405};
406
407namespace allocator {
408
409// Alias for module consumers using the older name for the above type.
410using Allocator = ::pw::Allocator;
411
412} // namespace allocator
413} // namespace pw
Definition: allocator.h:34
SharedPtr< T > MakeShared(size_t size)
Definition: allocator.h:233
UniquePtr< T > MakeUnique(size_t size, size_t alignment)
Definition: allocator.h:169
ElementType * New(size_t count, size_t alignment)
Constructs an alignment-byte aligned array of count objects.
Definition: allocator.h:105
SharedPtr< T > MakeShared(Args &&... args)
Definition: allocator.h:218
UniquePtr< T > MakeUnique()
Definition: allocator.h:182
T * NewArray(size_t count)
Definition: allocator.h:114
virtual size_t DoGetAllocated() const
Definition: allocator.h:397
T * NewArray(size_t count, size_t alignment)
Definition: allocator.h:123
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:249
bool Resize(void *ptr, size_t new_size)
Definition: allocator.h:285
virtual void * DoReallocate(void *ptr, Layout new_layout)
UniquePtr< T[]> MakeUniqueArray(size_t size)
Definition: allocator.h:191
virtual void * DoReallocate(void *ptr, Layout old_layout, size_t new_size)
void * Reallocate(void *ptr, Layout new_layout)
Definition: allocator.h:319
void * Reallocate(void *ptr, Layout old_layout, size_t new_size)
Definition: allocator.h:332
UniquePtr< T > MakeUnique(Args &&... args)
Definition: allocator.h:139
virtual bool DoResize(void *, Layout, size_t)
Definition: allocator.h:375
std::enable_if_t<!std::is_array_v< T >, T * > New(Args &&... args)
Definition: allocator.h:55
bool Resize(void *ptr, Layout layout, size_t new_size)
Definition: allocator.h:292
void * Allocate(Layout layout)
Definition: allocator.h:42
SharedPtr< T > MakeShared()
Definition: allocator.h:265
ElementType * New(size_t count)
Definition: allocator.h:88
UniquePtr< T[]> MakeUniqueArray(size_t size, size_t alignment)
Definition: allocator.h:200
ElementType * New()
Definition: allocator.h:72
UniquePtr< T > MakeUnique(size_t size)
Definition: allocator.h:153
size_t GetAllocated() const
Definition: allocator.h:344
virtual bool DoResize(void *ptr, size_t new_size)
Definition: allocator.h:367
Abstract interface for releasing memory.
Definition: deallocator.h:27
Definition: shared_ptr.h:57
Definition: unique_ptr.h:41
Definition: capability.h:62
Definition: layout.h:56
static constexpr std::enable_if_t<!std::is_array_v< T >, Layout > Of()
Creates a Layout for the given type.
Definition: layout.h:66
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27