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 <memory>
17
18#include "pw_allocator/capability.h"
19#include "pw_allocator/hardening.h"
20#include "pw_allocator/layout.h"
21#include "pw_result/result.h"
22#include "pw_status/status.h"
23#include "pw_status/status_with_size.h"
24
25namespace pw {
26
28
31 public:
35
36 virtual ~Deallocator() = default;
37
38 constexpr const Capabilities& capabilities() const { return capabilities_; }
39
41 constexpr bool HasCapability(Capability capability) const {
42 return capabilities_.has(capability);
43 }
44
51 inline void Deallocate(void* ptr);
52
74 template <typename T,
75 int&... kExplicitGuard,
76 std::enable_if_t<!std::is_array_v<T>, int> = 0>
77 void Delete(T* ptr);
78
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 void Delete(ElementType* ptr);
84
85 template <typename T,
86 int&... kExplicitGuard,
87 typename ElementType = std::remove_extent_t<T>,
88 std::enable_if_t<is_unbounded_array_v<T>, int> = 0>
89 void Delete(ElementType* ptr, size_t count);
91
104 template <typename ElementType>
105 void DeleteArray(ElementType* ptr, size_t count);
106
114 inline StatusWithSize GetCapacity() const;
115
126 bool IsEqual(const Deallocator& other) const { return this == &other; }
127
128 protected:
129 // There are downstream consumers that have implemented Allocators outside the
130 // `pw` namespace, and that use unqualified names for `is_[un]bounded_array`.
131 template <typename T>
132 static constexpr bool is_bounded_array_v = ::pw::is_bounded_array_v<T>;
133
134 template <typename T>
135 static constexpr bool is_unbounded_array_v = ::pw::is_unbounded_array_v<T>;
136
138 constexpr Deallocator() = default;
139
140 explicit constexpr Deallocator(const Capabilities& capabilities)
141 : capabilities_(capabilities) {}
142
171 enum class InfoType {
182 kRequestedLayoutOf,
183
187
194 kUsableLayoutOf,
195
206 kAllocatedLayoutOf,
207
213 kCapacity,
214
222 kRecognizes,
223 };
224
230 Result<Layout> GetInfo(InfoType info_type, const void* ptr) const {
231 return DoGetInfo(info_type, ptr);
232 }
233
239 static Result<Layout> GetInfo(const Deallocator& deallocator,
240 InfoType info_type,
241 const void* ptr) {
242 return deallocator.DoGetInfo(info_type, ptr);
243 }
244
247 Result<Layout> GetRequestedLayout(const void* ptr) const {
248 return DoGetInfo(InfoType::kRequestedLayoutOf, ptr);
249 }
250
253 static Result<Layout> GetRequestedLayout(const Deallocator& deallocator,
254 const void* ptr) {
255 return deallocator.GetRequestedLayout(ptr);
256 }
257
260 Result<Layout> GetUsableLayout(const void* ptr) const {
261 return DoGetInfo(InfoType::kUsableLayoutOf, ptr);
262 }
263
266 static Result<Layout> GetUsableLayout(const Deallocator& deallocator,
267 const void* ptr) {
268 return deallocator.GetUsableLayout(ptr);
269 }
270
273 Result<Layout> GetAllocatedLayout(const void* ptr) const {
274 return DoGetInfo(InfoType::kAllocatedLayoutOf, ptr);
275 }
276
279 static Result<Layout> GetAllocatedLayout(const Deallocator& deallocator,
280 const void* ptr) {
281 return deallocator.GetAllocatedLayout(ptr);
282 }
283
286 bool Recognizes(const void* ptr) const {
287 return DoGetInfo(InfoType::kRecognizes, ptr).ok();
288 }
289
292 static bool Recognizes(const Deallocator& deallocator, const void* ptr) {
293 return deallocator.Recognizes(ptr);
294 }
295
297 virtual void DoDeallocate([[maybe_unused]] void* ptr) = 0;
298
302 virtual Result<Layout> DoGetInfo(InfoType, const void*) const {
303 return Status::Unimplemented();
304 }
305
306 private:
307 const Capabilities capabilities_;
308};
309
311
312// Template and inline method implementations.
313
314void Deallocator::Deallocate(void* ptr) {
315 if (ptr != nullptr) {
316 DoDeallocate(ptr);
317 }
318}
319
320template <typename T,
321 int&... kExplicitGuard,
322 std::enable_if_t<!std::is_array_v<T>, int>>
323void Deallocator::Delete(T* ptr) {
324 if constexpr (allocator::Hardening::kIncludesDebugChecks) {
325 if (auto result = GetRequestedLayout(ptr); result.ok()) {
326 if constexpr (std::has_virtual_destructor_v<T>) {
327 PW_ASSERT(result->size() >= sizeof(T) &&
328 result->alignment() >= alignof(T));
329 } else {
330 PW_ASSERT(*result == Layout::Of<T>());
331 }
332 }
333 }
334 DeleteArray<T>(ptr, 1);
335}
336
337template <typename T,
338 int&... kExplicitGuard,
339 typename ElementType,
340 std::enable_if_t<is_bounded_array_v<T>, int>>
341void Deallocator::Delete(ElementType* ptr) {
342 size_t count = std::extent_v<T>;
343 if (count != 0) {
344 DeleteArray<ElementType>(&ptr[0], count);
345 }
346}
347
348template <typename T,
349 int&... kExplicitGuard,
350 typename ElementType,
351 std::enable_if_t<is_unbounded_array_v<T>, int>>
352void Deallocator::Delete(ElementType* ptr, size_t count) {
353 DeleteArray<ElementType>(ptr, count);
354}
355
356template <typename ElementType>
357void Deallocator::DeleteArray(ElementType* ptr, size_t count) {
358 if (!capabilities_.has(Capability::kSkipsDestroy)) {
359 std::destroy_n(ptr, count);
360 }
361 Deallocate(ptr);
362}
363
365 auto result = DoGetInfo(InfoType::kCapacity, nullptr);
366 return StatusWithSize(result.status(), Layout::Unwrap(result).size());
367}
368
369} // namespace pw
Abstract interface for releasing memory.
Definition: deallocator.h:30
static constexpr Status Unimplemented()
Definition: status.h:280
Definition: status_with_size.h:51
Definition: capability.h:65
Definition: layout.h:64
static constexpr Layout Unwrap(const Result< Layout > &result)
Definition: layout.h:93
void Deallocate(void *ptr)
Definition: deallocator.h:314
StatusWithSize GetCapacity() const
Definition: deallocator.h:364
void Delete(T *ptr)
void DeleteArray(ElementType *ptr, size_t count)
constexpr bool HasCapability(Capability capability) const
Returns whether a given capability is enabled for this object.
Definition: deallocator.h:41
Capability
Definition: capability.h:28
bool IsEqual(const Deallocator &other) const
Definition: deallocator.h:126
constexpr Deallocator()=default
TODO(b/326509341): Remove when downstream consumers migrate.
The Pigweed namespace.
Definition: alignment.h:27