WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
deleter.hpp
Go to the documentation of this file.
1// Copyright (C) 2015-2023 Jonathan Müller and foonathan/memory contributors
2// SPDX-License-Identifier: Zlib
3
4#ifndef WPI_MEMORY_DELETER_HPP_INCLUDED
5#define WPI_MEMORY_DELETER_HPP_INCLUDED
6
7/// \file
8/// \c Deleter classes using a RawAllocator.
9
10#include <type_traits>
11
12#include "allocator_storage.hpp"
13#include "config.hpp"
14#include "threading.hpp"
15
16namespace wpi
17{
18 namespace memory
19 {
20 /// A deleter class that deallocates the memory through a specified RawAllocator.
21 ///
22 /// It deallocates memory for a specified type but does not call its destructors.
23 /// \ingroup memory_adapter
24 template <typename Type, class RawAllocator>
25 class allocator_deallocator : WPI_EBO(allocator_reference<RawAllocator>)
26 {
27 static_assert(!std::is_abstract<Type>::value,
28 "use allocator_polymorphic_deallocator for storing base classes");
29
30 public:
32 using value_type = Type;
33
34 /// \effects Creates it without any associated allocator.
35 /// The deallocator must not be used if that is the case.
36 /// \notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.
37 allocator_deallocator() noexcept = default;
38
39 /// \effects Creates it by passing it an \ref allocator_reference.
40 /// It will store the reference to it and uses the referenced allocator object for the deallocation.
41 allocator_deallocator(allocator_reference<RawAllocator> alloc) noexcept
42 : allocator_reference<RawAllocator>(alloc)
43 {
44 }
45
46 /// \effects Deallocates the memory given to it.
47 /// Calls \c deallocate_node(pointer, sizeof(value_type), alignof(value_type)) on the referenced allocator object.
48 /// \requires The deallocator must not have been created by the default constructor.
50 {
51 this->deallocate_node(pointer, sizeof(value_type), alignof(value_type));
52 }
53
54 /// \returns The reference to the allocator.
55 /// It has the same type as the call to \ref allocator_reference::get_allocator().
56 /// \requires The deallocator must not be created by the default constructor.
57 auto get_allocator() const noexcept
58 -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
59 {
61 }
62 };
63
64 /// Specialization of \ref allocator_deallocator for array types.
65 /// Otherwise the same behavior.
66 /// \ingroup memory_adapter
67 template <typename Type, class RawAllocator>
68 class allocator_deallocator<Type[], RawAllocator>
69 : WPI_EBO(allocator_reference<RawAllocator>)
70 {
71 static_assert(!std::is_abstract<Type>::value, "must not create polymorphic arrays");
72
73 public:
75 using value_type = Type;
76
77 /// \effects Creates it without any associated allocator.
78 /// The deallocator must not be used if that is the case.
79 /// \notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.
80 allocator_deallocator() noexcept : size_(0u) {}
81
82 /// \effects Creates it by passing it an \ref allocator_reference and the size of the array that will be deallocated.
83 /// It will store the reference to the allocator and uses the referenced allocator object for the deallocation.
85 std::size_t size) noexcept
86 : allocator_reference<RawAllocator>(alloc), size_(size)
87 {
88 }
89
90 /// \effects Deallocates the memory given to it.
91 /// Calls \c deallocate_array(pointer, size, sizeof(value_type), alignof(value_type))
92 /// on the referenced allocator object with the size given in the constructor.
93 /// \requires The deallocator must not have been created by the default constructor.
95 {
96 this->deallocate_array(pointer, size_, sizeof(value_type), alignof(value_type));
97 }
98
99 /// \returns The reference to the allocator.
100 /// It has the same type as the call to \ref allocator_reference::get_allocator().
101 /// \requires The deallocator must not have been created by the default constructor.
102 auto get_allocator() const noexcept
103 -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
104 {
106 }
107
108 /// \returns The size of the array that will be deallocated.
109 /// This is the same value as passed in the constructor, or `0` if it was created by the default constructor.
110 std::size_t array_size() const noexcept
111 {
112 return size_;
113 }
114
115 private:
116 std::size_t size_;
117 };
118
119 /// A deleter class that deallocates the memory of a derived type through a specified RawAllocator.
120 ///
121 /// It can only be created from a \ref allocator_deallocator and thus must only be used for smart pointers initialized by derived-to-base conversion of the pointer.
122 /// \ingroup memory_adapter
123 template <typename BaseType, class RawAllocator>
124 class allocator_polymorphic_deallocator : WPI_EBO(allocator_reference<RawAllocator>)
125 {
126 public:
128 using value_type = BaseType;
129
130 /// \effects Creates it from a deallocator for a derived type.
131 /// It will deallocate the memory as if done by the derived type.
132 template <typename T, WPI_REQUIRES((std::is_base_of<BaseType, T>::value))>
134 : allocator_reference<RawAllocator>(dealloc.get_allocator()),
135 derived_size_(sizeof(T)),
136 derived_alignment_(alignof(T))
137 {
138 }
139
140 /// \effects Deallocates the memory given to it.
141 /// Calls \c deallocate_node(pointer, size, alignment) on the referenced allocator object,
142 /// where \c size and \c alignment are the values of the type it was created with.
144 {
145 this->deallocate_node(pointer, derived_size_, derived_alignment_);
146 }
147
148 /// \returns The reference to the allocator.
149 /// It has the same type as the call to \ref allocator_reference::get_allocator().
150 auto get_allocator() const noexcept
151 -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
152 {
154 }
155
156 private:
157 std::size_t derived_size_, derived_alignment_;
158 };
159
160 /// Similar to \ref allocator_deallocator but calls the destructors of the object.
161 /// Otherwise behaves the same.
162 /// \ingroup memory_adapter
163 template <typename Type, class RawAllocator>
164 class allocator_deleter : WPI_EBO(allocator_reference<RawAllocator>)
165 {
166 static_assert(!std::is_abstract<Type>::value,
167 "use allocator_polymorphic_deleter for storing base classes");
168
169 public:
171 using value_type = Type;
172
173 /// \effects Creates it without any associated allocator.
174 /// The deleter must not be used if that is the case.
175 /// \notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.
176 allocator_deleter() noexcept = default;
177
178 /// \effects Creates it by passing it an \ref allocator_reference.
179 /// It will store the reference to it and uses the referenced allocator object for the deallocation.
180 allocator_deleter(allocator_reference<RawAllocator> alloc) noexcept
181 : allocator_reference<RawAllocator>(alloc)
182 {
183 }
184
185 /// \effects Calls the destructor and deallocates the memory given to it.
186 /// Calls \c deallocate_node(pointer, sizeof(value_type), alignof(value_type))
187 /// on the referenced allocator object for the deallocation.
188 /// \requires The deleter must not have been created by the default constructor.
190 {
191 pointer->~value_type();
192 this->deallocate_node(pointer, sizeof(value_type), alignof(value_type));
193 }
194
195 /// \returns The reference to the allocator.
196 /// It has the same type as the call to \ref allocator_reference::get_allocator().
197 auto get_allocator() const noexcept
198 -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
199 {
201 }
202 };
203
204 /// Specialization of \ref allocator_deleter for array types.
205 /// Otherwise the same behavior.
206 /// \ingroup memory_adapter
207 template <typename Type, class RawAllocator>
208 class allocator_deleter<Type[], RawAllocator>
209 : WPI_EBO(allocator_reference<RawAllocator>)
210 {
211 static_assert(!std::is_abstract<Type>::value, "must not create polymorphic arrays");
212
213 public:
215 using value_type = Type;
216
217 /// \effects Creates it without any associated allocator.
218 /// The deleter must not be used if that is the case.
219 /// \notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.
220 allocator_deleter() noexcept : size_(0u) {}
221
222 /// \effects Creates it by passing it an \ref allocator_reference and the size of the array that will be deallocated.
223 /// It will store the reference to the allocator and uses the referenced allocator object for the deallocation.
224 allocator_deleter(allocator_reference<RawAllocator> alloc, std::size_t size) noexcept
225 : allocator_reference<RawAllocator>(alloc), size_(size)
226 {
227 }
228
229 /// \effects Calls the destructors and deallocates the memory given to it.
230 /// Calls \c deallocate_array(pointer, size, sizeof(value_type), alignof(value_type))
231 /// on the referenced allocator object with the size given in the constructor for the deallocation.
232 /// \requires The deleter must not have been created by the default constructor.
234 {
235 for (auto cur = pointer; cur != pointer + size_; ++cur)
236 cur->~value_type();
237 this->deallocate_array(pointer, size_, sizeof(value_type), alignof(value_type));
238 }
239
240 /// \returns The reference to the allocator.
241 /// It has the same type as the call to \ref allocator_reference::get_allocator().
242 /// \requires The deleter must not be created by the default constructor.
243 auto get_allocator() const noexcept
244 -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
245 {
247 }
248
249 /// \returns The size of the array that will be deallocated.
250 /// This is the same value as passed in the constructor, or `0` if it was created by the default constructor.
251 std::size_t array_size() const noexcept
252 {
253 return size_;
254 }
255
256 private:
257 std::size_t size_;
258 };
259
260 /// Similar to \ref allocator_polymorphic_deallocator but calls the destructors of the object.
261 /// Otherwise behaves the same.
262 /// \note It has a relatively high space overhead, so only use it if you have to.
263 /// \ingroup memory_adapter
264 template <typename BaseType, class RawAllocator>
265 class allocator_polymorphic_deleter : WPI_EBO(allocator_reference<RawAllocator>)
266 {
267 public:
269 using value_type = BaseType;
270
271 /// \effects Creates it from a deleter for a derived type.
272 /// It will deallocate the memory as if done by the derived type.
273 template <typename T, WPI_REQUIRES((std::is_base_of<BaseType, T>::value))>
275 : allocator_reference<RawAllocator>(deleter.get_allocator()),
276 derived_size_(sizeof(T)),
277 derived_alignment_(alignof(T))
278 {
279 WPI_MEMORY_ASSERT(std::size_t(derived_size_) == sizeof(T)
280 && std::size_t(derived_alignment_) == alignof(T));
281 }
282
283 /// \effects Deallocates the memory given to it.
284 /// Calls \c deallocate_node(pointer, size, alignment) on the referenced allocator object,
285 /// where \c size and \c alignment are the values of the type it was created with.
287 {
288 pointer->~value_type();
289 this->deallocate_node(pointer, derived_size_, derived_alignment_);
290 }
291
292 /// \returns The reference to the allocator.
293 /// It has the same type as the call to \ref allocator_reference::get_allocator().
294 auto get_allocator() const noexcept
295 -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
296 {
298 }
299
300 private:
301 unsigned short derived_size_,
302 derived_alignment_; // use unsigned short here to save space
303 };
304 } // namespace memory
305} // namespace wpi
306
307#endif //WPI_MEMORY_DELETER_HPP_INCLUDED
Class template wpi::memory::allocator_storage, some policies and resulting typedefs.
void operator()(value_type *pointer) noexcept
Definition deleter.hpp:94
std::size_t array_size() const noexcept
Definition deleter.hpp:110
allocator_deallocator() noexcept
Definition deleter.hpp:80
allocator_deallocator(allocator_reference< RawAllocator > alloc, std::size_t size) noexcept
Definition deleter.hpp:84
typename allocator_reference< RawAllocator >::allocator_type allocator_type
Definition deleter.hpp:74
auto get_allocator() const noexcept -> decltype(std::declval< allocator_reference< allocator_type > >().get_allocator())
Definition deleter.hpp:102
A deleter class that deallocates the memory through a specified RawAllocator.
Definition deleter.hpp:26
allocator_deallocator() noexcept=default
void operator()(value_type *pointer) noexcept
Definition deleter.hpp:49
Type value_type
Definition deleter.hpp:32
typename allocator_reference< RawAllocator >::allocator_type allocator_type
Definition deleter.hpp:31
auto get_allocator() const noexcept -> decltype(std::declval< allocator_reference< allocator_type > >().get_allocator())
Definition deleter.hpp:57
std::size_t array_size() const noexcept
Definition deleter.hpp:251
typename allocator_reference< RawAllocator >::allocator_type allocator_type
Definition deleter.hpp:214
void operator()(value_type *pointer) noexcept
Definition deleter.hpp:233
allocator_deleter(allocator_reference< RawAllocator > alloc, std::size_t size) noexcept
Definition deleter.hpp:224
allocator_deleter() noexcept
Definition deleter.hpp:220
auto get_allocator() const noexcept -> decltype(std::declval< allocator_reference< allocator_type > >().get_allocator())
Definition deleter.hpp:243
Similar to allocator_deallocator but calls the destructors of the object.
Definition deleter.hpp:165
Type value_type
Definition deleter.hpp:171
allocator_deleter() noexcept=default
void operator()(value_type *pointer) noexcept
Definition deleter.hpp:189
typename allocator_reference< RawAllocator >::allocator_type allocator_type
Definition deleter.hpp:170
auto get_allocator() const noexcept -> decltype(std::declval< allocator_reference< allocator_type > >().get_allocator())
Definition deleter.hpp:197
A deleter class that deallocates the memory of a derived type through a specified RawAllocator.
Definition deleter.hpp:125
BaseType value_type
Definition deleter.hpp:128
auto get_allocator() const noexcept -> decltype(std::declval< allocator_reference< allocator_type > >().get_allocator())
Definition deleter.hpp:150
typename allocator_reference< RawAllocator >::allocator_type allocator_type
Definition deleter.hpp:127
allocator_polymorphic_deallocator(allocator_deallocator< T, RawAllocator > dealloc)
Definition deleter.hpp:133
void operator()(value_type *pointer) noexcept
Definition deleter.hpp:143
Similar to allocator_polymorphic_deallocator but calls the destructors of the object.
Definition deleter.hpp:266
BaseType value_type
Definition deleter.hpp:269
void operator()(value_type *pointer) noexcept
Definition deleter.hpp:286
auto get_allocator() const noexcept -> decltype(std::declval< allocator_reference< allocator_type > >().get_allocator())
Definition deleter.hpp:294
allocator_polymorphic_deleter(allocator_deleter< T, RawAllocator > deleter)
Definition deleter.hpp:274
typename allocator_reference< RawAllocator >::allocator_type allocator_type
Definition deleter.hpp:268
An alias template for allocator_storage using the reference_storage policy.
Definition allocator_storage.hpp:900
typename reference_storage< RawAllocator >::allocator_type allocator_type
Definition allocator_storage.hpp:106
auto get_allocator() noexcept -> decltype(std::declval< storage_policy >().get_allocator())
Definition allocator_storage.hpp:277
Configuration macros.
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
Memory namespace.
Definition heap_allocator.hpp:20
Foonathan namespace.
Definition ntcore_cpp.h:26
The mutex types.
#define WPI_MEMORY_ASSERT(Expr)
Definition assert.hpp:46