Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
deallocator.h
1// Copyright 2024 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 "pw_allocator/capability.h"
17#include "pw_allocator/hardening.h"
18#include "pw_allocator/layout.h"
19#include "pw_allocator/unique_ptr.h"
20#include "pw_result/result.h"
21#include "pw_status/status.h"
22#include "pw_status/status_with_size.h"
23
24namespace pw {
25
28 protected:
29 // Alias types and variables needed for SFINAE below.
30 template <typename T>
31 static constexpr bool is_bounded_array_v =
32 allocator::internal::is_bounded_array_v<T>;
33
34 template <typename T>
35 static constexpr bool is_unbounded_array_v =
36 allocator::internal::is_unbounded_array_v<T>;
37
38 public:
40 using Capability = allocator::Capability;
42
43 virtual ~Deallocator() = default;
44
45 constexpr const Capabilities& capabilities() const { return capabilities_; }
46
48 bool HasCapability(Capability capability) const {
49 return capabilities_.has(capability);
50 }
51
58 void Deallocate(void* ptr) {
59 if (ptr != nullptr) {
60 DoDeallocate(ptr);
61 }
62 }
63
67 void Deallocate(void* ptr, Layout layout) {
68 if (ptr != nullptr) {
69 DoDeallocate(ptr, layout);
70 }
71 }
72
94 template <typename T,
95 int&... kExplicitGuard,
96 std::enable_if_t<!std::is_array_v<T>, int> = 0>
97 void Delete(T* ptr) {
98 if constexpr (allocator::Hardening::kIncludesDebugChecks) {
99 if (auto result = GetRequestedLayout(ptr); result.ok()) {
100 PW_ASSERT(*result == Layout::Of<T>());
101 }
102 }
103 DeleteArray<T>(ptr, 1);
104 }
105
106 template <typename T,
107 int&... kExplicitGuard,
108 typename ElementType = std::remove_extent_t<T>,
109 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
110 void Delete(ElementType* ptr) {
111 size_t count = std::extent_v<T>;
112 if (count != 0) {
113 DeleteArray<ElementType>(&ptr[0], count);
114 }
115 }
116
117 template <typename T,
118 int&... kExplicitGuard,
119 typename ElementType = std::remove_extent_t<T>,
120 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
121 void Delete(ElementType* ptr, size_t count) {
122 DeleteArray<ElementType>(ptr, count);
123 }
125
138 template <typename ElementType>
139 void DeleteArray(ElementType* ptr, size_t count) {
140 if (!capabilities_.has(Capability::kSkipsDestroy)) {
141 std::destroy_n(ptr, count);
142 }
143 Deallocate(ptr);
144 }
145
154 auto result = DoGetInfo(InfoType::kCapacity, nullptr);
155 return StatusWithSize(result.status(), Layout::Unwrap(result).size());
156 }
157
168 bool IsEqual(const Deallocator& other) const { return this == &other; }
169
170 protected:
172 constexpr Deallocator() = default;
173
174 explicit constexpr Deallocator(const Capabilities& capabilities)
175 : capabilities_(capabilities) {}
176
185 template <typename T,
186 int&... kExplicitGuard,
187 typename ElementType = std::remove_extent_t<T>,
188 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
189 [[deprecated("Use `UniquePtr<T>(...)` instead.")]] UniquePtr<T> WrapUnique(
190 ElementType* ptr, size_t size) {
191 return UniquePtr<T>(ptr, size, this);
192 }
193
222 enum class InfoType {
233 kRequestedLayoutOf,
234
238
245 kUsableLayoutOf,
246
257 kAllocatedLayoutOf,
258
264 kCapacity,
265
273 kRecognizes,
274 };
275
281 Result<Layout> GetInfo(InfoType info_type, const void* ptr) const {
282 return DoGetInfo(info_type, ptr);
283 }
284
290 static Result<Layout> GetInfo(const Deallocator& deallocator,
291 InfoType info_type,
292 const void* ptr) {
293 return deallocator.DoGetInfo(info_type, ptr);
294 }
295
298 Result<Layout> GetRequestedLayout(const void* ptr) const {
299 return DoGetInfo(InfoType::kRequestedLayoutOf, ptr);
300 }
301
304 static Result<Layout> GetRequestedLayout(const Deallocator& deallocator,
305 const void* ptr) {
306 return deallocator.GetRequestedLayout(ptr);
307 }
308
311 Result<Layout> GetUsableLayout(const void* ptr) const {
312 return DoGetInfo(InfoType::kUsableLayoutOf, ptr);
313 }
314
317 static Result<Layout> GetUsableLayout(const Deallocator& deallocator,
318 const void* ptr) {
319 return deallocator.GetUsableLayout(ptr);
320 }
321
324 Result<Layout> GetAllocatedLayout(const void* ptr) const {
325 return DoGetInfo(InfoType::kAllocatedLayoutOf, ptr);
326 }
327
330 static Result<Layout> GetAllocatedLayout(const Deallocator& deallocator,
331 const void* ptr) {
332 return deallocator.GetAllocatedLayout(ptr);
333 }
334
337 bool Recognizes(const void* ptr) const {
338 return DoGetInfo(InfoType::kRecognizes, ptr).ok();
339 }
340
343 static bool Recognizes(const Deallocator& deallocator, const void* ptr) {
344 return deallocator.Recognizes(ptr);
345 }
346
347 private:
351 virtual void DoDeallocate([[maybe_unused]] void* ptr) {
352 // This method will be pure virtual once consumer migrate from the
353 // deprecated version that takes a `Layout` parameter. In the meantime, the
354 // check that this method is implemented is deferred to run-time.
355 PW_ASSERT(false);
356 }
357
360 virtual void DoDeallocate(void* ptr, Layout) { DoDeallocate(ptr); }
361
363 virtual Result<Layout> DoGetInfo(InfoType, const void*) const {
364 return Status::Unimplemented();
365 }
366
367 const Capabilities capabilities_;
368};
369
370namespace allocator {
371
372// Alias for module consumers using the older name for the above type.
373using Deallocator = ::pw::Deallocator;
374
375} // namespace allocator
376} // namespace pw
Abstract interface for releasing memory.
Definition: deallocator.h:27
void Deallocate(void *ptr, Layout layout)
Definition: deallocator.h:67
bool HasCapability(Capability capability) const
Returns whether a given capability is enabled for this object.
Definition: deallocator.h:48
void Delete(T *ptr)
Definition: deallocator.h:97
StatusWithSize GetCapacity() const
Definition: deallocator.h:153
void DeleteArray(ElementType *ptr, size_t count)
Definition: deallocator.h:139
void Deallocate(void *ptr)
Definition: deallocator.h:58
UniquePtr< T > WrapUnique(ElementType *ptr, size_t size)
Definition: deallocator.h:189
bool IsEqual(const Deallocator &other) const
Definition: deallocator.h:168
constexpr Deallocator()=default
TODO(b/326509341): Remove when downstream consumers migrate.
Definition: status_with_size.h:49
Definition: unique_ptr.h:41
Definition: capability.h:62
Definition: layout.h:56
static constexpr Layout Unwrap(const Result< Layout > &result)
Definition: layout.h:89
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27