proxsuite 0.6.7
The Advanced Proximal Optimization Toolbox
Loading...
Searching...
No Matches
alloc.hpp
Go to the documentation of this file.
1#ifndef VEG_ALLOC_HPP_TAWYRUICS
2#define VEG_ALLOC_HPP_TAWYRUICS
3
4#include "proxsuite/fwd.hpp"
12
13#include <cstddef> // std::max_align_t
14#include <cstdlib> // std::{malloc, free, realloc}, ::{aligned_alloc, free}
15#ifndef __APPLE__
16#include <malloc.h> // ::malloc_usable_size
17#else
18#include <AvailabilityMacros.h>
19#include <malloc/malloc.h>
20#define malloc_usable_size malloc_size
21#endif
23
24namespace proxsuite {
25namespace linalg {
26namespace veg {
27
28#ifdef __APPLE__
29namespace alignment {
30
31#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101500 && \
32 (defined(_LIBCPP_HAS_ALIGNED_ALLOC) || defined(_LIBCPP_HAS_C11_FEATURES)) && \
33 defined(PROXSUITE_WITH_CPP_17)
34VEG_INLINE void*
35aligned_alloc(std::size_t alignment, std::size_t size)
36{
37 return std::aligned_alloc(alignment, size);
38}
39#elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
40VEG_INLINE void*
41aligned_alloc(std::size_t alignment, std::size_t size)
42{
43 if (alignment < sizeof(void*)) {
44 alignment = sizeof(void*);
45 }
46 void* p;
47 if (::posix_memalign(&p, alignment, size) != 0) {
48 p = 0;
49 }
50 return p;
51}
52#endif
53
54} // namespace alignment
55#endif
56
57// Support aligned_alloc for c++14, code from boost/align.
58namespace alignment {
59namespace detail {
60// Source: https://www.boost.org/doc/libs/1_65_0/boost/align/detail/min_size.hpp
61template<std::size_t A, std::size_t B>
62struct min_size : std::integral_constant<std::size_t, (A < B) ? A : B>
63{};
64
65template<class T>
66struct offset_value
67{
68 char value;
69 T object;
70};
71
72// Source:
73// https://www.boost.org/doc/libs/1_65_0/boost/align/detail/alignment_of.hpp
74template<class T>
75struct alignment_of : min_size<sizeof(T), sizeof(offset_value<T>) - sizeof(T)>
76{};
77
78// Source:
79// https://www.boost.org/doc/libs/1_65_0/boost/align/detail/is_alignment.hpp
80constexpr inline bool
81is_alignment(std::size_t value)
82{
83 return (value > 0) && ((value & (value - 1)) == 0);
84}
85
86// Source: https://www.boost.org/doc/libs/1_74_0/boost/align/detail/align.hpp
87inline void*
88align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space)
89{
90 assert(is_alignment(alignment));
91 char* p = reinterpret_cast<char*>(
92 ~(alignment - 1) & (reinterpret_cast<std::size_t>(ptr) + alignment - 1));
93 assert((p - static_cast<char*>(ptr)) >= 0);
94 std::size_t n = std::size_t(p - static_cast<char*>(ptr));
95 if (size + n <= space) {
96 ptr = p;
97 space -= n;
98 return p;
99 }
100 return 0;
101}
102
103// Source:
104// https://www.boost.org/doc/libs/1_65_0/boost/align/detail/aligned_alloc.hpp
105inline void*
106aligned_alloc(std::size_t alignment, std::size_t size)
107{
108 assert(is_alignment(alignment));
109 enum
110 {
112 };
113 if (alignment < N) {
114 alignment = N;
115 }
116 std::size_t n = size + alignment - N;
117 void* p = std::malloc(sizeof(void*) + n);
118 if (p) {
119 void* r = static_cast<char*>(p) + sizeof(void*);
120 (void)align(alignment, size, r, n);
121 *(static_cast<void**>(r) - 1) = p;
122 p = r;
123 }
124 return p;
125}
126} // namespace detail
127} // namespace alignment
128
129namespace mem {
130enum struct CopyAvailable
131{
132 no,
135};
136enum struct DtorAvailable
137{
138 no,
141};
142template<typename T>
144 : meta::constant<mem::CopyAvailable,
145 (VEG_CONCEPT(nothrow_copyable<T>) &&
146 VEG_CONCEPT(nothrow_copy_assignable<T>))
147 ? CopyAvailable::yes_nothrow
148 : (VEG_CONCEPT(copyable<T>) &&
149 VEG_CONCEPT(copy_assignable<T>))
150 ? CopyAvailable::yes_maythrow
151 : CopyAvailable::no>
152{};
153template<typename T>
155 : meta::constant<mem::DtorAvailable,
156 VEG_CONCEPT(nothrow_destructible<T>)
157 ? DtorAvailable::yes_nothrow
158 : DtorAvailable::yes_maythrow>
159{};
160
161VEG_INLINE auto
162aligned_alloc(usize align, usize size) noexcept -> void*
163{
164 usize const mask = align - 1;
165#if defined(_WIN32)
166 return _aligned_malloc((size + mask) & ~mask, align);
167#elif defined(__APPLE__)
168#if defined(PROXSUITE_WITH_CPP_17) && defined(_LIBCPP_HAS_ALIGNED_ALLOC)
169 return alignment::aligned_alloc(align, (size + mask) & ~mask);
170#else
171 return alignment::detail::aligned_alloc(align, (size + mask) & ~mask);
172#endif
173#else
174#if defined(PROXSUITE_WITH_CPP_17) && defined(_LIBCPP_HAS_ALIGNED_ALLOC)
175 return std::aligned_alloc(align, (size + mask) & ~mask);
176#else
177 return alignment::detail::aligned_alloc(align, (size + mask) & ~mask);
178#endif
179#endif
180}
181
182VEG_INLINE void
183aligned_free(usize /*align*/, void* ptr) noexcept
184{
185#ifndef _WIN32
186 std::free(ptr);
187#else
188 _aligned_free(ptr);
189#endif
190}
191
193{
194 constexpr friend auto operator==(SystemAlloc /*unused*/,
195 SystemAlloc /*unused*/) noexcept -> bool
196 {
197 return true;
198 }
199};
200template<>
202{
203 static constexpr usize max_base_align = alignof(std::max_align_t);
204
206 void* ptr,
207 Layout layout) noexcept
208 {
209 (layout.align <= max_base_align) ? std::free(ptr)
210 : mem::aligned_free(layout.align, ptr);
211 }
213 Layout layout) noexcept
215 {
216 void* ptr = (layout.align <= max_base_align)
217 ? std::malloc(layout.byte_size)
218 : mem::aligned_alloc(layout.align, layout.byte_size);
219 if (HEDLEY_UNLIKELY(ptr == nullptr)) {
221 }
222#ifndef _WIN32
223 return { ptr, ::malloc_usable_size(ptr) };
224#else
225 return { ptr, _msize(ptr) };
226#endif
227 }
229 void* ptr,
230 Layout layout,
233 RelocFn reloc) noexcept
235 {
236 void* new_ptr; // NOLINT
237 bool typical_align = layout.align <= max_base_align;
238 bool trivial_reloc = reloc.is_trivial();
240
241 if (use_realloc) {
242 new_ptr = std::realloc(ptr, new_size);
243 } else {
244 new_ptr = mem::aligned_alloc(layout.align, new_size);
245 }
246
247 if (HEDLEY_UNLIKELY(new_ptr == nullptr)) {
249 }
250
251 if (!use_realloc) {
252 reloc(new_ptr, ptr, copy_size);
253 mem::aligned_free(layout.align, ptr);
254 }
255#ifndef _WIN32
256 return { new_ptr, ::malloc_usable_size(new_ptr) };
257#else
258 return { new_ptr, _msize(new_ptr) };
259#endif
260 }
262 void* /*ptr*/,
263 Layout /*layout*/,
264 usize /*new_size*/) const noexcept -> bool
265 {
266 return false;
267 }
269 void* ptr,
270 Layout layout,
272 RelocFn reloc) noexcept
274 {
275 return realloc(
276 VEG_FWD(alloc), ptr, layout, new_size, layout.byte_size, reloc);
277 }
279 void* ptr,
280 Layout layout,
282 RelocFn reloc) noexcept
284 {
285 return realloc(VEG_FWD(alloc), ptr, layout, new_size, new_size, reloc);
286 }
287};
288
290{};
291template<>
293{
294 template<typename T>
296
297 template<typename T, typename Alloc>
299 T* ptr,
300 RefMut<Alloc> /*alloc*/)
302 {
303 mem::destroy_at(ptr);
304 }
305 VEG_TEMPLATE((typename T, typename Alloc),
306 requires(VEG_CONCEPT(copyable<T>)),
307 VEG_NODISCARD VEG_INLINE static auto clone,
308 (/*cloner*/, RefMut<DefaultCloner>),
309 (rhs, Ref<T>),
310 (/*alloc*/, RefMut<Alloc>))
311 VEG_NOEXCEPT_IF(VEG_CONCEPT(nothrow_copyable<T>))->T { return T(rhs.get()); }
312 VEG_TEMPLATE((typename T, typename Alloc),
313 requires(VEG_CONCEPT(copyable<T>)),
314 VEG_INLINE static void clone_from,
315 (/*cloner*/, RefMut<DefaultCloner>),
316 (lhs, RefMut<T>),
317 (rhs, Ref<T>),
318 (/*alloc*/, RefMut<Alloc>))
320 {
321 lhs.get() = rhs.get();
322 }
323};
324
327} // namespace mem
328
329namespace _detail {
330namespace _mem {
331template<typename A>
332struct ManagedAlloc /* NOLINT */
333{
334 void* data;
337
339 {
340 if (data != nullptr) {
342 }
343 }
344};
345} // namespace _mem
346} // namespace _detail
347} // namespace veg
348} // namespace linalg
349} // namespace proxsuite
350
352#endif /* end of include guard VEG_ALLOC_HPP_TAWYRUICS */
#define HEDLEY_UNLIKELY(expr)
#define VEG_CONCEPT(...)
Definition macros.hpp:1243
#define VEG_INLINE_VAR(Name, Obj)
Definition macros.hpp:523
#define VEG_INLINE
Definition macros.hpp:118
#define VEG_NO_INLINE
Definition macros.hpp:123
#define VEG_FWD(X)
Definition macros.hpp:569
void * aligned_alloc(std::size_t alignment, std::size_t size)
Definition alloc.hpp:106
void * align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t &space)
Definition alloc.hpp:88
constexpr bool is_alignment(std::size_t value)
Definition alloc.hpp:81
VEG_INLINE void aligned_free(usize, void *ptr) noexcept
Definition alloc.hpp:183
VEG_INLINE auto aligned_alloc(usize align, usize size) noexcept -> void *
Definition alloc.hpp:162
decltype(sizeof(0)) usize
Definition macros.hpp:702
#define VEG_NODISCARD
Definition prologue.hpp:97
#define VEG_NOEXCEPT_IF(...)
Definition prologue.hpp:31
VEG_NODISCARD VEG_INLINE constexpr auto get() const noexcept -> T const &
Definition ref.hpp:41
VEG_NODISCARD static VEG_INLINE auto shrink(RefMut< SystemAlloc > alloc, void *ptr, Layout layout, usize new_size, RelocFn reloc) noexcept -> mem::AllocBlock
Definition alloc.hpp:278
VEG_NODISCARD static VEG_INLINE auto grow(RefMut< SystemAlloc > alloc, void *ptr, Layout layout, usize new_size, RelocFn reloc) noexcept -> mem::AllocBlock
Definition alloc.hpp:268
static VEG_INLINE void dealloc(RefMut< SystemAlloc >, void *ptr, Layout layout) noexcept
Definition alloc.hpp:205
VEG_NODISCARD static VEG_NO_INLINE auto realloc(RefMut< SystemAlloc >, void *ptr, Layout layout, usize new_size, usize copy_size, RelocFn reloc) noexcept -> mem::AllocBlock
Definition alloc.hpp:228
VEG_NODISCARD VEG_INLINE auto try_grow_in_place(void *, Layout, usize) const noexcept -> bool
Definition alloc.hpp:261
VEG_NODISCARD static VEG_INLINE auto alloc(RefMut< SystemAlloc >, Layout layout) noexcept -> mem::AllocBlock
Definition alloc.hpp:212
VEG_TEMPLATE((typename T, typename Alloc), requires(VEG_CONCEPT(copyable< T >)), VEG_NODISCARD VEG_INLINE static auto clone,(, RefMut< DefaultCloner >),(rhs, Ref< T >),(, RefMut< Alloc >)) VEG_NOEXCEPT_IF(VEG_CONCEPT(nothrow_copyable< T >)) -> T
Definition alloc.hpp:305
VEG_TEMPLATE((typename T, typename Alloc), requires(VEG_CONCEPT(copyable< T >)), VEG_INLINE static void clone_from,(, RefMut< DefaultCloner >),(lhs, RefMut< T >),(rhs, Ref< T >),(, RefMut< Alloc >))
Definition alloc.hpp:312
static VEG_INLINE void destroy(RefMut< DefaultCloner >, T *ptr, RefMut< Alloc >)
Definition alloc.hpp:298
constexpr friend auto operator==(SystemAlloc, SystemAlloc) noexcept -> bool
Definition alloc.hpp:194