WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
segregator.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_SEGREGATOR_HPP_INCLUDED
5#define WPI_MEMORY_SEGREGATOR_HPP_INCLUDED
6
7/// \file
8/// Class template \ref wpi::memory::segregator and related classes.
9
11#include "detail/utility.hpp"
12#include "allocator_traits.hpp"
13#include "config.hpp"
14#include "error.hpp"
15
16namespace wpi
17{
18 namespace memory
19 {
20 /// A Segregatable that allocates until a maximum size.
21 /// \ingroup memory_adapter
22 template <class RawAllocator>
23 class threshold_segregatable : WPI_EBO(allocator_traits<RawAllocator>::allocator_type)
24 {
25 public:
27
28 /// \effects Creates it by passing the maximum size it will allocate
29 /// and the allocator it uses.
30 explicit threshold_segregatable(std::size_t max_size,
32 : allocator_type(detail::move(alloc)), max_size_(max_size)
33 {
34 }
35
36 /// \returns `true` if `size` is less then or equal to the maximum size,
37 /// `false` otherwise.
38 /// \note A return value of `true` means that the allocator will be used for the allocation.
39 bool use_allocate_node(std::size_t size, std::size_t) noexcept
40 {
41 return size <= max_size_;
42 }
43
44 /// \returns `true` if `count * size` is less then or equal to the maximum size,
45 /// `false` otherwise.
46 /// \note A return value of `true` means that the allocator will be used for the allocation.
47 bool use_allocate_array(std::size_t count, std::size_t size, std::size_t) noexcept
48 {
49 return count * size <= max_size_;
50 }
51
52 /// @{
53 /// \returns A reference to the allocator it owns.
55 {
56 return *this;
57 }
58
59 const allocator_type& get_allocator() const noexcept
60 {
61 return *this;
62 }
63 /// @}
64
65 private:
66 std::size_t max_size_;
67 };
68
69 /// \returns A \ref threshold_segregatable with the same parameter.
70 template <class RawAllocator>
72 std::size_t max_size, RawAllocator&& alloc)
73 {
75 typename std::decay<RawAllocator>::type>(max_size,
76 std::forward<RawAllocator>(alloc));
77 }
78
79 /// A composable RawAllocator that will always fail.
80 /// This is useful for compositioning or as last resort in \ref binary_segregator.
81 /// \ingroup memory_allocator
83 {
84 public:
85 /// \effects Will always throw.
86 /// \throws A \ref out_of_fixed_memory exception.
87 void* allocate_node(std::size_t size, std::size_t)
88 {
89 throw out_of_fixed_memory(info(), size);
90 }
91
92 /// \requires Must not be called.
93 void deallocate_node(void*, std::size_t, std::size_t) noexcept
94 {
95 WPI_MEMORY_UNREACHABLE("cannot be called with proper values");
96 }
97
98 /// \effects Does nothing.
99 /// \returns Always returns `nullptr`.
100 void* try_allocate_node(std::size_t, std::size_t) noexcept
101 {
102 return nullptr;
103 }
104
105 /// \effects Does nothing.
106 /// \returns Always returns `false`.
107 bool try_deallocate_node(void*, std::size_t, std::size_t) noexcept
108 {
109 return false;
110 }
111
112 private:
113 allocator_info info() const noexcept
114 {
115 return {WPI_MEMORY_LOG_PREFIX "::null_allocator", this};
116 }
117 };
118
119 /// A RawAllocator that either uses the Segregatable or the other `RawAllocator`.
120 /// It is a faster alternative to \ref fallback_allocator that doesn't require a composable allocator
121 /// and decides about the allocator to use purely with the `Segregatable` based on size and alignment.
122 /// \ingroup memory_adapter
123 template <class Segregatable, class RawAllocator>
125 : WPI_EBO(
126 detail::ebo_storage<1, typename allocator_traits<RawAllocator>::allocator_type>)
127 {
130
131 public:
132 using segregatable = Segregatable;
133 using segregatable_allocator_type = typename segregatable::allocator_type;
135
136 /// \effects Creates it by giving the Segregatable
137 /// and the RawAllocator.
140 : detail::ebo_storage<1, fallback_allocator_type>(detail::move(fallback)),
141 s_(detail::move(s))
142 {
143 }
144
145 /// @{
146 /// \effects Uses the Segregatable to decide which allocator to use.
147 /// Then forwards to the chosen allocator.
148 void* allocate_node(std::size_t size, std::size_t alignment)
149 {
150 if (get_segregatable().use_allocate_node(size, alignment))
152 alignment);
153 else
155 alignment);
156 }
157
158 void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
159 {
160 if (get_segregatable().use_allocate_node(size, alignment))
162 alignment);
163 else
165 alignment);
166 }
167
168 void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)
169 {
170 if (get_segregatable().use_allocate_array(count, size, alignment))
172 size, alignment);
173 else
175 alignment);
176 }
177
178 void deallocate_array(void* array, std::size_t count, std::size_t size,
179 std::size_t alignment) noexcept
180 {
181 if (get_segregatable().use_allocate_array(count, size, alignment))
183 count, size, alignment);
184 else
186 alignment);
187 }
188 /// @}
189
190 /// @{
191 /// \returns The maximum value of the fallback.
192 /// \note It assumes that the fallback will be used for larger allocations,
193 /// and the `Segregatable` for smaller ones.
194 std::size_t max_node_size() const
195 {
197 }
198
199 std::size_t max_array_size() const
200 {
202 }
203
204 std::size_t max_alignemnt() const
205 {
207 }
208 /// @}
209
210 /// @{
211 /// \returns A reference to the segregatable allocator.
212 /// This is the one primarily used.
214 {
215 return get_segregatable().get_allocator();
216 }
217
219 {
220 return get_segregatable().get_allocator();
221 }
222 /// @}
223
224 /// @{
225 /// \returns A reference to the fallback allocator.
226 /// It will be used if the Segregator doesn't want the alloction.
231
236 /// @}
237
238 private:
239 segregatable& get_segregatable() noexcept
240 {
241 return s_;
242 }
243
244 segregatable s_;
245 };
246
247 namespace detail
248 {
249 template <class... Segregatables>
251
252 template <class Segregatable>
257
258 template <class Segregatable, class RawAllocator>
259 struct make_segregator_t<Segregatable, RawAllocator>
260 {
262 };
263
264 template <class Segregatable, class... Tail>
265 struct make_segregator_t<Segregatable, Tail...>
266 {
267 using type =
268 binary_segregator<Segregatable, typename make_segregator_t<Tail...>::type>;
269 };
270
271 template <class Segregator, class Fallback = null_allocator>
272 auto make_segregator(Segregator&& seg, Fallback&& f = null_allocator{})
273 -> binary_segregator<typename std::decay<Segregator>::type,
274 typename std::decay<Fallback>::type>
275 {
276 return binary_segregator<
277 typename std::decay<Segregator>::type,
278 typename std::decay<Fallback>::type>(std::forward<Segregator>(seg),
279 std::forward<Fallback>(f));
280 }
281
282 template <class Segregator, typename... Rest>
283 auto make_segregator(Segregator&& seg, Rest&&... rest)
285 decltype(make_segregator(std::forward<Rest>(rest)...))>
286 {
288 decltype(make_segregator(std::forward<Rest>(
289 rest)...))>(std::forward<Segregator>(seg),
291 std::forward<Rest>(rest)...));
292 }
293
294 template <std::size_t I, class Segregator>
296
297 template <class Segregator, class Fallback>
298 struct segregatable_type<0, binary_segregator<Segregator, Fallback>>
299 {
300 using type = typename Segregator::allocator_type;
301
306
308 {
310 }
311 };
312
313 template <std::size_t I, class Segregator, class Fallback>
314 struct segregatable_type<I, binary_segregator<Segregator, Fallback>>
315 {
316 using base = segregatable_type<I - 1, Fallback>;
317 using type = typename base::type;
318
320 {
321 return base::get(s.get_fallback_allocator());
322 }
323
325 {
326 return base::get(s.get_fallback_allocator());
327 }
328 };
329
330 template <class Fallback>
332 {
333 using type = Fallback;
334
335 static const std::size_t size = 0u;
336
337 static type& get(Fallback& f)
338 {
339 return f;
340 }
341
342 static const type& get(const Fallback& f)
343 {
344 return f;
345 }
346 };
347
348 template <class Segregator, class Fallback>
349 struct fallback_type<binary_segregator<Segregator, Fallback>>
350 {
352 using type = typename base::type;
353
354 static const std::size_t size = base::size + 1u;
355
357 {
358 return base::get(s.get_fallback_allocator());
359 }
360
362 {
363 return base::get(s.get_fallback_allocator());
364 }
365 };
366 } // namespace detail
367
368 /// Creates multiple nested \ref binary_segregator.
369 /// If you pass one type, it must be a Segregatable.
370 /// Then the result is a \ref binary_segregator with that `Segregatable` and \ref null_allocator as fallback.
371 /// If you pass two types, the first one must be a `Segregatable`,
372 /// the second one a RawAllocator.
373 /// Then the result is a simple \ref binary_segregator with those arguments.
374 /// If you pass more than one, the last one must be a `RawAllocator` all others `Segregatable`,
375 /// the result is `binary_segregator<Head, segregator<Tail...>>`.
376 /// \note It will result in an allocator that tries each `Segregatable` in the order specified
377 /// using the last parameter as final fallback.
378 /// \ingroup memory_adapter
379 template <class... Allocators>
380 WPI_ALIAS_TEMPLATE(segregator,
382
383 /// \returns A \ref segregator created from the allocators `args`.
384 /// \relates segregator
385 template <typename... Args>
387 {
388 return detail::make_segregator(std::forward<Args>(args)...);
389 }
390
391 /// The number of Segregatable a \ref segregator has.
392 /// \relates segregator
393 template <class Segregator>
395 {
397 };
398
399 /// The type of the `I`th Segregatable.
400 /// \relates segregator
401 template <std::size_t I, class Segregator>
403
404 /// @{
405 /// \returns The `I`th Segregatable.
406 /// \relates segregrator
407 template <std::size_t I, class Segregator, class Fallback>
410 {
412 }
413
414 template <std::size_t I, class Segregator, class Fallback>
416 -> const segregatable_allocator_type<I, binary_segregator<Segregator, Fallback>>
417 {
419 }
420 /// @}
421
422 /// The type of the final fallback RawAllocator.
423 /// \relates segregator
424 template <class Segregator>
426
427 /// @{
428 /// \returns The final fallback RawAllocator.
429 /// \relates segregator
430 template <class Segregator, class Fallback>
433 {
435 }
436
437 template <class Segregator, class Fallback>
439 -> const fallback_allocator_type<binary_segregator<Segregator, Fallback>>&
440 {
442 }
443 /// @}
444 } // namespace memory
445} // namespace wpi
446
447#endif // WPI_MEMORY_SEGREGATOR_HPP_INCLUDED
The default specialization of the wpi::memory::allocator_traits.
This class is a wrapper around std::array that does compile time size checking.
Definition array.h:26
The default specialization of the allocator_traits for a RawAllocator.
Definition allocator_traits.hpp:292
static void deallocate_array(allocator_type &state, void *array, std::size_t count, std::size_t size, std::size_t alignment) noexcept
Definition allocator_traits.hpp:328
traits_detail::allocator_type< Allocator > allocator_type
Definition allocator_traits.hpp:294
static void * allocate_array(allocator_type &state, std::size_t count, std::size_t size, std::size_t alignment)
Definition allocator_traits.hpp:308
static std::size_t max_array_size(const allocator_type &state)
Definition allocator_traits.hpp:346
static std::size_t max_node_size(const allocator_type &state)
Definition allocator_traits.hpp:338
static std::size_t max_alignment(const allocator_type &state)
Definition allocator_traits.hpp:354
static void * allocate_node(allocator_type &state, std::size_t size, std::size_t alignment)
Definition allocator_traits.hpp:298
static void deallocate_node(allocator_type &state, void *node, std::size_t size, std::size_t alignment) noexcept
Definition allocator_traits.hpp:318
A RawAllocator that either uses the Segregatable or the other RawAllocator.
Definition segregator.hpp:127
std::size_t max_array_size() const
Definition segregator.hpp:199
void deallocate_node(void *ptr, std::size_t size, std::size_t alignment) noexcept
Definition segregator.hpp:158
typename allocator_traits< RawAllocator >::allocator_type fallback_allocator_type
Definition segregator.hpp:134
void deallocate_array(void *array, std::size_t count, std::size_t size, std::size_t alignment) noexcept
Definition segregator.hpp:178
typename segregatable::allocator_type segregatable_allocator_type
Definition segregator.hpp:133
segregatable_allocator_type & get_segregatable_allocator() noexcept
Definition segregator.hpp:213
std::size_t max_node_size() const
Definition segregator.hpp:194
void * allocate_node(std::size_t size, std::size_t alignment)
Definition segregator.hpp:148
fallback_allocator_type & get_fallback_allocator() noexcept
Definition segregator.hpp:227
std::size_t max_alignemnt() const
Definition segregator.hpp:204
const segregatable_allocator_type & get_segregatable_allocator() const noexcept
Definition segregator.hpp:218
const fallback_allocator_type & get_fallback_allocator() const noexcept
Definition segregator.hpp:232
void * allocate_array(std::size_t count, std::size_t size, std::size_t alignment)
Definition segregator.hpp:168
Segregatable segregatable
Definition segregator.hpp:132
binary_segregator(segregatable s, fallback_allocator_type fallback=fallback_allocator_type())
Definition segregator.hpp:138
T & get() noexcept
Definition ebo_storage.hpp:27
A composable RawAllocator that will always fail.
Definition segregator.hpp:83
void * allocate_node(std::size_t size, std::size_t)
Definition segregator.hpp:87
void deallocate_node(void *, std::size_t, std::size_t) noexcept
Definition segregator.hpp:93
void * try_allocate_node(std::size_t, std::size_t) noexcept
Definition segregator.hpp:100
bool try_deallocate_node(void *, std::size_t, std::size_t) noexcept
Definition segregator.hpp:107
A special case of out_of_memory errors thrown when a low-level allocator with a fixed size runs out o...
Definition error.hpp:121
Creates multiple nested binary_segregator.
Definition segregator.hpp:381
auto make_segregator(Args &&... args) -> segregator< typename std::decay< Args >::type... >
Definition segregator.hpp:386
typename detail::fallback_type< Segregator >::type fallback_allocator_type
The type of the final fallback RawAllocator.
Definition segregator.hpp:425
typename detail::segregatable_type< I, Segregator >::type segregatable_allocator_type
The type of the Ith Segregatable.
Definition segregator.hpp:402
A Segregatable that allocates until a maximum size.
Definition segregator.hpp:24
allocator_type & get_allocator() noexcept
Definition segregator.hpp:54
const allocator_type & get_allocator() const noexcept
Definition segregator.hpp:59
threshold_segregatable(std::size_t max_size, allocator_type alloc=allocator_type())
Definition segregator.hpp:30
bool use_allocate_array(std::size_t count, std::size_t size, std::size_t) noexcept
Definition segregator.hpp:47
typename allocator_traits< RawAllocator >::allocator_type allocator_type
Definition segregator.hpp:26
bool use_allocate_node(std::size_t size, std::size_t) noexcept
Definition segregator.hpp:39
Configuration macros.
#define WPI_MEMORY_LOG_PREFIX
Definition config.hpp:46
#define WPI_ALIAS_TEMPLATE(Name,...)
Definition config.hpp:73
The exception classes.
auto ptr(T p) -> const void *
Converts p to const void* for pointer formatting.
Definition format.h:3821
detail namespace with internal helper functions
Definition input_adapters.h:32
auto make_segregator(Segregator &&seg, Fallback &&f=null_allocator{}) -> binary_segregator< typename std::decay< Segregator >::type, typename std::decay< Fallback >::type >
Definition segregator.hpp:272
Memory namespace.
Definition heap_allocator.hpp:20
threshold_segregatable< typename std::decay< RawAllocator >::type > threshold(std::size_t max_size, RawAllocator &&alloc)
Definition segregator.hpp:71
auto get_fallback_allocator(const binary_segregator< Segregator, Fallback > &s) -> const fallback_allocator_type< binary_segregator< Segregator, Fallback > > &
Definition segregator.hpp:438
auto get_segregatable_allocator(const binary_segregator< Segregator, Fallback > &s) -> const segregatable_allocator_type< I, binary_segregator< Segregator, Fallback > >
Definition segregator.hpp:415
Foonathan namespace.
Definition ntcore_cpp.h:26
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
Definition PointerIntPair.h:270
Contains information about an allocator.
Definition error.hpp:23
static const type & get(const binary_segregator< Segregator, Fallback > &s)
Definition segregator.hpp:361
static type & get(binary_segregator< Segregator, Fallback > &s)
Definition segregator.hpp:356
Definition segregator.hpp:332
static const type & get(const Fallback &f)
Definition segregator.hpp:342
static type & get(Fallback &f)
Definition segregator.hpp:337
Fallback type
Definition segregator.hpp:333
Definition segregator.hpp:250
static const type & get(const binary_segregator< Segregator, Fallback > &s)
Definition segregator.hpp:307
static type & get(binary_segregator< Segregator, Fallback > &s)
Definition segregator.hpp:302
typename Segregator::allocator_type type
Definition segregator.hpp:300
static type & get(binary_segregator< Segregator, Fallback > &s)
Definition segregator.hpp:319
static const type & get(const binary_segregator< Segregator, Fallback > &s)
Definition segregator.hpp:324
Definition segregator.hpp:295
The number of Segregatable a segregator has.
Definition segregator.hpp:395
static const std::size_t value
Definition segregator.hpp:396
#define WPI_MEMORY_UNREACHABLE(Msg)
Definition assert.hpp:48