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#include <optional>
18
19#include "pw_allocator/capability.h"
20#include "pw_allocator/config.h"
21#include "pw_allocator/deallocator.h"
22#include "pw_allocator/fragmentation.h"
23#include "pw_allocator/layout.h"
24#include "pw_allocator/shared_ptr.h"
25#include "pw_allocator/unique_ptr.h"
26#include "pw_numeric/checked_arithmetic.h"
27#include "pw_result/result.h"
28
29namespace pw {
30
32
33// Forward declare to break a circular dependency with shared_ptr.h.
34template <typename T>
35class SharedPtr;
36
42class Allocator : public Deallocator {
43 public:
45
52 [[nodiscard]] void* Allocate(Layout layout);
53
62 template <typename T,
63 int&... kExplicitGuard,
64 std::enable_if_t<!std::is_array_v<T>, int> = 0,
65 typename... Args>
66 [[nodiscard]] T* New(Args&&... args) {
67 void* ptr = Allocate(Layout::Of<T>());
68 return ptr != nullptr ? new (ptr) T(std::forward<Args>(args)...) : nullptr;
69 }
70
79 template <typename T,
80 int&... kExplicitGuard,
81 typename ElementType = std::remove_extent_t<T>,
82 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
83 [[nodiscard]] ElementType* New() {
84 return NewArrayImpl<ElementType>(std::extent_v<T>, alignof(ElementType));
85 }
86
95 template <typename T,
96 int&... kExplicitGuard,
97 typename ElementType = std::remove_extent_t<T>,
98 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
99 [[nodiscard]] ElementType* New(size_t count) {
100 return NewArrayImpl<ElementType>(count, alignof(ElementType));
101 }
102
104 //
112 template <typename T,
113 int&... kExplicitGuard,
114 typename ElementType = std::remove_extent_t<T>,
115 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
116 [[nodiscard]] ElementType* New(size_t count, size_t alignment) {
117 return NewArrayImpl<ElementType>(count, alignment);
118 }
119
128 template <typename T,
129 int&... kExplicitGuard,
130 std::enable_if_t<!std::is_array_v<T>, int> = 0,
131 typename... Args>
132 [[nodiscard]] UniquePtr<T> MakeUnique(Args&&... args) {
133 return UniquePtr<T>(New<T>(std::forward<Args>(args)...), *this);
134 }
135
143 template <typename T, std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
144 [[nodiscard]] UniquePtr<T> MakeUnique(size_t size) {
145 return MakeUnique<T>(size, alignof(std::remove_extent_t<T>));
146 }
147
157 template <typename T, std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
158 [[nodiscard]] UniquePtr<T> MakeUnique(size_t size, size_t alignment) {
159 return UniquePtr<T>(New<T>(size, alignment), size, *this);
160 }
161
168 template <typename T, std::enable_if_t<is_bounded_array_v<T>, int> = 0>
169 [[nodiscard]] UniquePtr<T> MakeUnique() {
170 return UniquePtr<T>(New<T>(), std::extent_v<T>, this);
171 }
172
173// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
174#if PW_ALLOCATOR_HAS_ATOMICS
175
183 template <typename T,
184 int&... kExplicitGuard,
185 std::enable_if_t<!std::is_array_v<T>, int> = 0,
186 typename... Args>
187 [[nodiscard]] SharedPtr<T> MakeShared(Args&&... args) {
188 return SharedPtr<T>::template Create<Args...>(this,
189 std::forward<Args>(args)...);
190 }
191
199 template <typename T, std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
200 [[nodiscard]] SharedPtr<T> MakeShared(size_t size) {
201 return MakeShared<T>(size, alignof(std::remove_extent_t<T>));
202 }
203
213 template <typename T, std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
214 [[nodiscard]] SharedPtr<T> MakeShared(size_t size, size_t alignment) {
215 return SharedPtr<T>::Create(this, size, alignment);
216 }
217
227 template <typename T, std::enable_if_t<is_bounded_array_v<T>, int> = 0>
228 [[nodiscard]] SharedPtr<T> MakeShared() {
230 this, std::extent_v<T>, alignof(std::remove_extent_t<T>));
231 }
232
233// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
234#endif // PW_ALLOCATOR_HAS_ATOMICS
235
248 [[nodiscard]] bool Resize(void* ptr, size_t new_size);
249
273 [[nodiscard]] void* Reallocate(void* ptr, Layout new_layout);
274
277 size_t GetAllocated() const { return DoGetAllocated(); }
278
280 std::optional<Fragmentation> MeasureFragmentation() const {
281 return DoMeasureFragmentation();
282 }
283
284 protected:
286 constexpr Allocator() = default;
287
288 explicit constexpr Allocator(const Capabilities& capabilities)
289 : Deallocator(Capability::kCanAllocateArbitraryLayout | capabilities) {}
290
292 virtual void* DoAllocate(Layout layout) = 0;
293
295 virtual bool DoResize([[maybe_unused]] void* ptr,
296 [[maybe_unused]] size_t new_size) {
297 return false;
298 }
299
305 virtual void* DoReallocate(void* ptr, Layout new_layout);
306
311 virtual size_t DoGetAllocated() const { return size_t(-1); }
312
317 virtual std::optional<Fragmentation> DoMeasureFragmentation() const {
318 return std::nullopt;
319 }
320
321 private:
322 // Helper method for allocating arrays of objects.
323 template <typename ElementType>
324 ElementType* NewArrayImpl(size_t count, size_t alignment) {
325 void* ptr = Allocate(Layout::Of<ElementType[]>(count).Align(alignment));
326 return ptr != nullptr ? new (ptr) ElementType[count] : nullptr;
327 }
328};
329
330namespace allocator {
331
332// TODO(b/376730645): This deprecated alias cannot be removed yet due to a
333// downstream dependency.
334using Allocator [[deprecated("Use pw::Allocator instead")]] = ::pw::Allocator;
335
336} // namespace allocator
337
339
340} // namespace pw
Definition: allocator.h:42
ElementType * New(size_t count, size_t alignment)
Constructs an alignment-byte aligned array of count objects.
Definition: allocator.h:116
SharedPtr< T > MakeShared(Args &&... args)
Definition: allocator.h:187
SharedPtr< T > MakeShared()
Definition: allocator.h:228
UniquePtr< T > MakeUnique()
Definition: allocator.h:169
virtual size_t DoGetAllocated() const
Definition: allocator.h:311
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:214
bool Resize(void *ptr, size_t new_size)
virtual void * DoReallocate(void *ptr, Layout new_layout)
void * Reallocate(void *ptr, Layout new_layout)
T * New(Args &&... args)
Definition: allocator.h:66
UniquePtr< T > MakeUnique(Args &&... args)
Definition: allocator.h:132
UniquePtr< T > MakeUnique(size_t size, size_t alignment)
Definition: allocator.h:158
virtual std::optional< Fragmentation > DoMeasureFragmentation() const
Returns fragmentation information for the allocator's memory region.
Definition: allocator.h:317
void * Allocate(Layout layout)
UniquePtr< T > MakeUnique(size_t size)
Definition: allocator.h:144
ElementType * New(size_t count)
Definition: allocator.h:99
SharedPtr< T > MakeShared(size_t size)
Definition: allocator.h:200
ElementType * New()
Definition: allocator.h:83
size_t GetAllocated() const
Definition: allocator.h:277
virtual bool DoResize(void *ptr, size_t new_size)
Definition: allocator.h:295
std::optional< Fragmentation > MeasureFragmentation() const
Returns fragmentation information for the allocator's memory region.
Definition: allocator.h:280
Abstract interface for releasing memory.
Definition: deallocator.h:30
Definition: shared_ptr.h:64
static SharedPtr Create(Allocator *allocator, Args &&... args)
Definition: unique_ptr.h:44
Definition: capability.h:65
Definition: layout.h:64
static constexpr Layout Of()
Creates a Layout for the given type.
Definition: layout.h:77
Capability
Definition: capability.h:28
The Pigweed namespace.
Definition: alignment.h:27
Definition: fragmentation.h:47