WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
memory_resource_adapter.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_MEMORY_RESOURCE_ADAPTER_HPP_INCLUDED
5#define WPI_MEMORY_MEMORY_RESOURCE_ADAPTER_HPP_INCLUDED
6
7/// \file
8/// Class \ref wpi::memory::memory_resource_adapter and \ref wpi::memory::memory_resource_allocator to allow usage of PMRs.
9
10#include "detail/assert.hpp"
11#include "detail/utility.hpp"
12#include "config.hpp"
13#include "allocator_traits.hpp"
14
15#if defined(__has_include) && __has_include(<memory_resource>)
16
17#if !defined(__GNUC__) || __cplusplus >= 201703L
18// The experimental/memory_resource header lacks a check for C++17 on older GCC,
19// so we have to do it for them.
20#include <memory_resource>
21#endif
22
23#elif defined(__has_include) && __has_include(<experimental/memory_resource>)
24
25#if !defined(__GNUC__) || __cplusplus >= 201402L
26// The experimental/memory_resource header lacks a check for C++14 on older GCC,
27// so we have to do it for them.
28#include <experimental/memory_resource>
29#endif
30
31#endif
32
33#if defined(__cpp_lib_memory_resource)
34
35// We use std::pmr::memory_resource.
36namespace wpi_memory_pmr = std::pmr;
37
38#elif defined(__cpp_lib_experimental_memory_resources)
39
40// We use std::experimental::pmr::memory_resource.
41namespace wpi_memory_pmr = std::experimental::pmr;
42
43#else
44
45// We use our own implementation.
47{
48 // see N3916 for documentation
50 {
51 static const std::size_t max_alignment = alignof(std::max_align_t);
52
53 public:
54 virtual ~memory_resource() noexcept {}
55 void* allocate(std::size_t bytes, std::size_t alignment = max_alignment)
56 {
57 return do_allocate(bytes, alignment);
58 }
59 void deallocate(void* p, std::size_t bytes, std::size_t alignment = max_alignment)
60 {
61 do_deallocate(p, bytes, alignment);
62 }
63 bool is_equal(const memory_resource& other) const noexcept
64 {
65 return do_is_equal(other);
66 }
67
68 protected:
69 virtual void* do_allocate(std::size_t bytes, std::size_t alignment) = 0;
70 virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) = 0;
71 virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
72 };
73 inline bool operator==(const memory_resource& a, const memory_resource& b) noexcept
74 {
75 return &a == &b || a.is_equal(b);
76 }
77 inline bool operator!=(const memory_resource& a, const memory_resource& b) noexcept
78 {
79 return !(a == b);
80 }
81} // namespace wpi_memory_pmr
82
83#endif
84
85namespace wpi
86{
87 namespace memory
88 {
89 /// The \c memory_resource abstract base class used in the implementation.
90 /// \ingroup memory_adapter
91 WPI_ALIAS_TEMPLATE(memory_resource, foonathan_memory_pmr::memory_resource);
92
93 /// Wraps a RawAllocator and makes it a \ref memory_resource.
94 /// \ingroup memory_adapter
95 template <class RawAllocator>
97 : public memory_resource,
98 WPI_EBO(allocator_traits<RawAllocator>::allocator_type)
99 {
100 public:
102
103 /// \effects Creates the resource by moving in the allocator.
106 {
107 }
108
109 /// @{
110 /// \returns A reference to the wrapped allocator.
112 {
113 return *this;
114 }
115
116 const allocator_type& get_allocator() const noexcept
117 {
118 return *this;
119 }
120 /// @}
121
122 protected:
124
125 /// \effects Allocates raw memory with given size and alignment.
126 /// It forwards to \c allocate_node() or \c allocate_array() depending on the size.
127 /// \returns The new memory as returned by the RawAllocator.
128 /// \throws Anything thrown by the allocation function.
129 void* do_allocate(std::size_t bytes, std::size_t alignment) override
130 {
131 auto max = traits_type::max_node_size(*this);
132 if (bytes <= max)
133 return traits_type::allocate_node(*this, bytes, alignment);
134 auto div = bytes / max;
135 auto mod = bytes % max;
136 auto n = div + (mod != 0);
137 return traits_type::allocate_array(*this, n, max, alignment);
138 }
139
140 /// \effects Deallocates memory previously allocated by \ref do_allocate.
141 /// It forwards to \c deallocate_node() or \c deallocate_array() depending on the size.
142 /// \throws Nothing.
143 void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) override
144 {
145 auto max = traits_type::max_node_size(*this);
146 if (bytes <= max)
147 traits_type::deallocate_node(*this, p, bytes, alignment);
148 else
149 {
150 auto div = bytes / max;
151 auto mod = bytes % max;
152 auto n = div + (mod != 0);
153 traits_type::deallocate_array(*this, p, n, max, alignment);
154 }
155 }
156
157 /// \returns Whether or not \c *this is equal to \c other
158 /// by comparing the addresses.
159 bool do_is_equal(const memory_resource& other) const noexcept override
160 {
161 return this == &other;
162 }
163 };
164
165 /// Wraps a \ref memory_resource and makes it a RawAllocator.
166 /// \ingroup memory_adapter
168 {
169 public:
170 /// \effects Creates it by giving it a pointer to the \ref memory_resource.
171 /// \requires \c ptr must not be \c nullptr.
176
177 /// \effects Allocates a node by forwarding to the \c allocate() function.
178 /// \returns The node as returned by the \ref memory_resource.
179 /// \throws Anything thrown by the \c allocate() function.
180 void* allocate_node(std::size_t size, std::size_t alignment)
181 {
182 return ptr_->allocate(size, alignment);
183 }
184
185 /// \effects Deallocates a node by forwarding to the \c deallocate() function.
186 void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
187 {
188 ptr_->deallocate(ptr, size, alignment);
189 }
190
191 /// \returns The maximum alignment which is the maximum value of type \c std::size_t.
192 std::size_t max_alignment() const noexcept
193 {
194 return std::size_t(-1);
195 }
196
197 /// \returns A pointer to the used \ref memory_resource, this is never \c nullptr.
198 memory_resource* resource() const noexcept
199 {
200 return ptr_;
201 }
202
203 private:
204 memory_resource* ptr_;
205 };
206
207 /// @{
208 /// \returns Whether `lhs` and `rhs` share the same resource.
209 /// \relates memory_resource_allocator
210 inline bool operator==(const memory_resource_allocator& lhs,
211 const memory_resource_allocator& rhs) noexcept
212 {
213 return lhs.resource() == rhs.resource();
214 }
215
216 inline bool operator!=(const memory_resource_allocator& lhs,
217 const memory_resource_allocator& rhs) noexcept
218 {
219 return !(lhs == rhs);
220 }
221 /// @}
222
223#if !defined(DOXYGEN)
224 template <class RawAllocator>
225 struct is_shared_allocator;
226#endif
227
228 /// Specialization of \ref is_shared_allocator to mark \ref memory_resource_allocator as shared.
229 /// This allows using it as \ref allocator_reference directly.
230 /// \ingroup memory_adapter
231 template <>
233 {
234 };
235 } // namespace memory
236} // namespace wpi
237
238#endif // WPI_MEMORY_MEMORY_RESOURCE_ADAPTER_HPP_INCLUDED
The default specialization of the wpi::memory::allocator_traits.
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_node_size(const allocator_type &state)
Definition allocator_traits.hpp:338
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
Wraps a RawAllocator and makes it a memory_resource.
Definition memory_resource_adapter.hpp:99
allocator_type & get_allocator() noexcept
Definition memory_resource_adapter.hpp:111
void do_deallocate(void *p, std::size_t bytes, std::size_t alignment) override
Definition memory_resource_adapter.hpp:143
const allocator_type & get_allocator() const noexcept
Definition memory_resource_adapter.hpp:116
bool do_is_equal(const memory_resource &other) const noexcept override
Definition memory_resource_adapter.hpp:159
memory_resource_adapter(allocator_type &&other) noexcept
Definition memory_resource_adapter.hpp:104
typename allocator_traits< RawAllocator >::allocator_type allocator_type
Definition memory_resource_adapter.hpp:101
void * do_allocate(std::size_t bytes, std::size_t alignment) override
Definition memory_resource_adapter.hpp:129
Wraps a memory_resource and makes it a RawAllocator.
Definition memory_resource_adapter.hpp:168
memory_resource * resource() const noexcept
Definition memory_resource_adapter.hpp:198
memory_resource_allocator(memory_resource *ptr) noexcept
Definition memory_resource_adapter.hpp:172
std::size_t max_alignment() const noexcept
Definition memory_resource_adapter.hpp:192
void deallocate_node(void *ptr, std::size_t size, std::size_t alignment) noexcept
Definition memory_resource_adapter.hpp:186
void * allocate_node(std::size_t size, std::size_t alignment)
Definition memory_resource_adapter.hpp:180
The memory_resource abstract base class used in the implementation.
Definition memory_resource_adapter.hpp:91
Definition memory_resource_adapter.hpp:50
void deallocate(void *p, std::size_t bytes, std::size_t alignment=max_alignment)
Definition memory_resource_adapter.hpp:59
virtual void * do_allocate(std::size_t bytes, std::size_t alignment)=0
void * allocate(std::size_t bytes, std::size_t alignment=max_alignment)
Definition memory_resource_adapter.hpp:55
bool is_equal(const memory_resource &other) const noexcept
Definition memory_resource_adapter.hpp:63
virtual ~memory_resource() noexcept
Definition memory_resource_adapter.hpp:54
virtual bool do_is_equal(const memory_resource &other) const noexcept=0
virtual void do_deallocate(void *p, std::size_t bytes, std::size_t alignment)=0
Configuration macros.
#define WPI_ALIAS_TEMPLATE(Name,...)
Definition config.hpp:73
auto ptr(T p) -> const void *
Converts p to const void* for pointer formatting.
Definition format.h:3821
std::remove_reference< T >::type && move(T &&arg) noexcept
Definition utility.hpp:25
Memory namespace.
Definition heap_allocator.hpp:20
bool operator!=(const memory_resource_allocator &lhs, const memory_resource_allocator &rhs) noexcept
Definition memory_resource_adapter.hpp:216
bool operator==(std::nullptr_t, const joint_ptr< T, RawAllocator > &ptr)
Definition joint_allocator.hpp:393
Definition memory_resource_adapter.hpp:47
bool operator!=(const memory_resource &a, const memory_resource &b) noexcept
Definition memory_resource_adapter.hpp:77
bool operator==(const memory_resource &a, const memory_resource &b) noexcept
Definition memory_resource_adapter.hpp:73
Foonathan namespace.
Definition ntcore_cpp.h:26
constexpr T mod(U Numerator, V Denominator)
Returns the remainder of the Euclidean division of LHS by RHS.
Definition MathExtras.h:432
Definition format.h:3858
Specifies whether or not a RawAllocator has shared semantics.
Definition allocator_storage.hpp:534
#define WPI_MEMORY_ASSERT(Expr)
Definition assert.hpp:46