C/C++ API Reference
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
27
30 protected:
31 // Alias types and variables needed for SFINAE below.
32 template <typename T>
33 static constexpr bool is_bounded_array_v =
34 allocator::internal::is_bounded_array_v<T>;
35
36 template <typename T>
37 static constexpr bool is_unbounded_array_v =
38 allocator::internal::is_unbounded_array_v<T>;
39
40 public:
44
45 virtual ~Deallocator() = default;
46
47 constexpr const Capabilities& capabilities() const { return capabilities_; }
48
50 constexpr bool HasCapability(Capability capability) const {
51 return capabilities_.has(capability);
52 }
53
60 void Deallocate(void* ptr) {
61 if (ptr != nullptr) {
62 DoDeallocate(ptr);
63 }
64 }
65
69 void Deallocate(void* ptr, Layout layout) {
70 if (ptr != nullptr) {
71 DoDeallocate(ptr, layout);
72 }
73 }
74
96 template <typename T,
97 int&... kExplicitGuard,
98 std::enable_if_t<!std::is_array_v<T>, int> = 0>
99 void Delete(T* ptr) {
100 if constexpr (allocator::Hardening::kIncludesDebugChecks) {
101 if (auto result = GetRequestedLayout(ptr); result.ok()) {
102 if constexpr (std::has_virtual_destructor_v<T>) {
103 PW_ASSERT(result->size() >= sizeof(T) &&
104 result->alignment() >= alignof(T));
105 } else {
106 PW_ASSERT(*result == Layout::Of<T>());
107 }
108 }
109 }
110 DeleteArray<T>(ptr, 1);
111 }
112
113 template <typename T,
114 int&... kExplicitGuard,
115 typename ElementType = std::remove_extent_t<T>,
116 std::enable_if_t<is_bounded_array_v<T>, int> = 0>
117 void Delete(ElementType* ptr) {
118 size_t count = std::extent_v<T>;
119 if (count != 0) {
120 DeleteArray<ElementType>(&ptr[0], count);
121 }
122 }
123
124 template <typename T,
125 int&... kExplicitGuard,
126 typename ElementType = std::remove_extent_t<T>,
127 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
128 void Delete(ElementType* ptr, size_t count) {
129 DeleteArray<ElementType>(ptr, count);
130 }
132
145 template <typename ElementType>
146 void DeleteArray(ElementType* ptr, size_t count) {
147 if (!capabilities_.has(Capability::kSkipsDestroy)) {
148 std::destroy_n(ptr, count);
149 }
150 Deallocate(ptr);
151 }
152
161 auto result = DoGetInfo(InfoType::kCapacity, nullptr);
162 return StatusWithSize(result.status(), Layout::Unwrap(result).size());
163 }
164
175 bool IsEqual(const Deallocator& other) const { return this == &other; }
176
177 protected:
179 constexpr Deallocator() = default;
180
181 explicit constexpr Deallocator(const Capabilities& capabilities)
182 : capabilities_(capabilities) {}
183
192 template <typename T,
193 int&... kExplicitGuard,
194 typename ElementType = std::remove_extent_t<T>,
195 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
196 [[deprecated("Use `UniquePtr<T>(...)` instead.")]] UniquePtr<T> WrapUnique(
197 ElementType* ptr, size_t size) {
198 return UniquePtr<T>(ptr, size, this);
199 }
200
229 enum class InfoType {
240 kRequestedLayoutOf,
241
252 kUsableLayoutOf,
253
264 kAllocatedLayoutOf,
265
271 kCapacity,
272
280 kRecognizes,
281 };
282
288 Result<Layout> GetInfo(InfoType info_type, const void* ptr) const {
289 return DoGetInfo(info_type, ptr);
290 }
291
297 static Result<Layout> GetInfo(const Deallocator& deallocator,
298 InfoType info_type,
299 const void* ptr) {
300 return deallocator.DoGetInfo(info_type, ptr);
301 }
302
305 Result<Layout> GetRequestedLayout(const void* ptr) const {
306 return DoGetInfo(InfoType::kRequestedLayoutOf, ptr);
307 }
308
311 static Result<Layout> GetRequestedLayout(const Deallocator& deallocator,
312 const void* ptr) {
313 return deallocator.GetRequestedLayout(ptr);
314 }
315
318 Result<Layout> GetUsableLayout(const void* ptr) const {
319 return DoGetInfo(InfoType::kUsableLayoutOf, ptr);
320 }
321
324 static Result<Layout> GetUsableLayout(const Deallocator& deallocator,
325 const void* ptr) {
326 return deallocator.GetUsableLayout(ptr);
327 }
328
331 Result<Layout> GetAllocatedLayout(const void* ptr) const {
332 return DoGetInfo(InfoType::kAllocatedLayoutOf, ptr);
333 }
334
337 static Result<Layout> GetAllocatedLayout(const Deallocator& deallocator,
338 const void* ptr) {
339 return deallocator.GetAllocatedLayout(ptr);
340 }
341
344 bool Recognizes(const void* ptr) const {
345 return DoGetInfo(InfoType::kRecognizes, ptr).ok();
346 }
347
350 static bool Recognizes(const Deallocator& deallocator, const void* ptr) {
351 return deallocator.Recognizes(ptr);
352 }
353
354 private:
358 virtual void DoDeallocate([[maybe_unused]] void* ptr) {
359 // This method will be pure virtual once consumer migrate from the
360 // deprecated version that takes a `Layout` parameter. In the meantime, the
361 // check that this method is implemented is deferred to run-time.
362 PW_ASSERT(false);
363 }
364
367 virtual void DoDeallocate(void* ptr, Layout) { DoDeallocate(ptr); }
368
370 virtual Result<Layout> DoGetInfo(InfoType, const void*) const {
371 return Status::Unimplemented();
372 }
373
374 const Capabilities capabilities_;
375};
376
377namespace allocator {
378
379// Alias for module consumers using the older name for the above type.
380using Deallocator = ::pw::Deallocator;
382} // namespace allocator
383
385
386} // namespace pw
Abstract interface for releasing memory.
Definition: deallocator.h:29
static constexpr Status Unimplemented()
Definition: status.h:280
Definition: status_with_size.h:51
Definition: unique_ptr.h:43
Definition: capability.h:65
Definition: layout.h:58
static constexpr Layout Unwrap(const Result< Layout > &result)
Definition: layout.h:91
void Deallocate(void *ptr, Layout layout)
Definition: deallocator.h:69
void Delete(T *ptr)
Definition: deallocator.h:99
StatusWithSize GetCapacity() const
Definition: deallocator.h:160
void DeleteArray(ElementType *ptr, size_t count)
Definition: deallocator.h:146
void Deallocate(void *ptr)
Definition: deallocator.h:60
constexpr bool HasCapability(Capability capability) const
Returns whether a given capability is enabled for this object.
Definition: deallocator.h:50
Capability
Definition: capability.h:28
UniquePtr< T > WrapUnique(ElementType *ptr, size_t size)
Definition: deallocator.h:196
bool IsEqual(const Deallocator &other) const
Definition: deallocator.h:175
constexpr Deallocator()=default
TODO(b/326509341): Remove when downstream consumers migrate.
The Pigweed namespace.
Definition: alignment.h:27