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
78 template <typename T,
79 int&... kExplicitGuard,
80 typename ElementType = std::remove_extent_t<T>,
81 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
82 [[nodiscard]] ElementType* New() {
83 return NewArrayImpl<ElementType>(std::extent_v<T>, alignof(ElementType));
84 }
85
94 template <typename T,
95 int&... kExplicitGuard,
96 typename ElementType = std::remove_extent_t<T>,
97 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
98 [[nodiscard]] ElementType* New(size_t count) {
99 return NewArrayImpl<ElementType>(count, alignof(ElementType));
100 }
101
103 //
111 template <typename T,
112 int&... kExplicitGuard,
113 typename ElementType = std::remove_extent_t<T>,
114 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
115 [[nodiscard]] ElementType* New(size_t count, size_t alignment) {
116 return NewArrayImpl<ElementType>(count, alignment);
117 }
118
127 template <typename T,
128 int&... kExplicitGuard,
129 std::enable_if_t<!std::is_array_v<T>, int> = 0,
130 typename... Args>
131 [[nodiscard]] UniquePtr<T> MakeUnique(Args&&... args) {
132 return UniquePtr<T>(New<T>(std::forward<Args>(args)...), *this);
133 }
134
142 template <typename T, std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
143 [[nodiscard]] UniquePtr<T> MakeUnique(size_t size) {
144 return MakeUnique<T>(size, alignof(std::remove_extent_t<T>));
145 }
146
156 template <typename T, std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
157 [[nodiscard]] UniquePtr<T> MakeUnique(size_t size, size_t alignment) {
158 return UniquePtr<T>(New<T>(size, alignment), size, *this);
159 }
160
167 template <typename T, std::enable_if_t<is_bounded_array_v<T>, int> = 0>
168 [[nodiscard]] UniquePtr<T> MakeUnique() {
169 return UniquePtr<T>(New<T>(), std::extent_v<T>, this);
170 }
171
172// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
173#if PW_ALLOCATOR_HAS_ATOMICS
174
182 template <typename T,
183 int&... kExplicitGuard,
184 std::enable_if_t<!std::is_array_v<T>, int> = 0,
185 typename... Args>
186 [[nodiscard]] SharedPtr<T> MakeShared(Args&&... args) {
187 return SharedPtr<T>::template Create<Args...>(this,
188 std::forward<Args>(args)...);
189 }
190
198 template <typename T, std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
199 [[nodiscard]] SharedPtr<T> MakeShared(size_t size) {
200 return MakeShared<T>(size, alignof(std::remove_extent_t<T>));
201 }
202
212 template <typename T, std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
213 [[nodiscard]] SharedPtr<T> MakeShared(size_t size, size_t alignment) {
214 return SharedPtr<T>::Create(this, size, alignment);
215 }
216
223 template <typename T, std::enable_if_t<is_bounded_array_v<T>, int> = 0>
224 [[nodiscard]] SharedPtr<T> MakeShared() {
226 this, std::extent_v<T>, alignof(std::remove_extent_t<T>));
227 }
228
229// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
230#endif // PW_ALLOCATOR_HAS_ATOMICS
231
244 [[nodiscard]] bool Resize(void* ptr, size_t new_size);
245
269 [[nodiscard]] void* Reallocate(void* ptr, Layout new_layout);
270
273 size_t GetAllocated() const { return DoGetAllocated(); }
274
276 std::optional<Fragmentation> MeasureFragmentation() const {
277 return DoMeasureFragmentation();
278 }
279
280 protected:
282 constexpr Allocator() = default;
283
284 explicit constexpr Allocator(const Capabilities& capabilities)
285 : Deallocator(Capability::kCanAllocateArbitraryLayout | capabilities) {}
286
288 virtual void* DoAllocate(Layout layout) = 0;
289
291 virtual bool DoResize([[maybe_unused]] void* ptr,
292 [[maybe_unused]] size_t new_size) {
293 return false;
294 }
295
301 virtual void* DoReallocate(void* ptr, Layout new_layout);
302
307 virtual size_t DoGetAllocated() const { return size_t(-1); }
308
313 virtual std::optional<Fragmentation> DoMeasureFragmentation() const {
314 return std::nullopt;
315 }
316
317 private:
318 // Helper method for allocating arrays of objects.
319 template <typename ElementType>
320 ElementType* NewArrayImpl(size_t count, size_t alignment) {
321 void* ptr = Allocate(Layout::Of<ElementType[]>(count).Align(alignment));
322 return ptr != nullptr ? new (ptr) ElementType[count] : nullptr;
323 }
324};
325
326namespace allocator {
327
328// TODO(b/376730645): This deprecated alias cannot be removed yet due to a
329// downstream dependency.
330using Allocator [[deprecated("Use pw::Allocator instead")]] = ::pw::Allocator;
331
332} // namespace allocator
333
335
336} // 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:115
SharedPtr< T > MakeShared(Args &&... args)
Definition: allocator.h:186
SharedPtr< T > MakeShared()
Definition: allocator.h:224
UniquePtr< T > MakeUnique()
Definition: allocator.h:168
virtual size_t DoGetAllocated() const
Definition: allocator.h:307
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:213
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:131
UniquePtr< T > MakeUnique(size_t size, size_t alignment)
Definition: allocator.h:157
virtual std::optional< Fragmentation > DoMeasureFragmentation() const
Returns fragmentation information for the allocator's memory region.
Definition: allocator.h:313
void * Allocate(Layout layout)
UniquePtr< T > MakeUnique(size_t size)
Definition: allocator.h:143
ElementType * New(size_t count)
Definition: allocator.h:98
SharedPtr< T > MakeShared(size_t size)
Definition: allocator.h:199
ElementType * New()
Definition: allocator.h:82
size_t GetAllocated() const
Definition: allocator.h:273
virtual bool DoResize(void *ptr, size_t new_size)
Definition: allocator.h:291
std::optional< Fragmentation > MeasureFragmentation() const
Returns fragmentation information for the allocator's memory region.
Definition: allocator.h:276
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