.. _program_listing_file__tmp_ws_src_proxsuite_include_proxsuite_linalg_veg_memory_alloc.hpp: Program Listing for File alloc.hpp ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/proxsuite/include/proxsuite/linalg/veg/memory/alloc.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef VEG_ALLOC_HPP_TAWYRUICS #define VEG_ALLOC_HPP_TAWYRUICS #include "proxsuite/fwd.hpp" #include "proxsuite/linalg/veg/ref.hpp" #include "proxsuite/linalg/veg/type_traits/constructible.hpp" #include "proxsuite/linalg/veg/type_traits/assignable.hpp" #include "proxsuite/linalg/veg/internal/typedefs.hpp" #include "proxsuite/linalg/veg/internal/macros.hpp" #include "proxsuite/linalg/veg/memory/placement.hpp" #include "proxsuite/linalg/veg/type_traits/alloc.hpp" #include // std::max_align_t #include // std::{malloc, free, realloc}, ::{aligned_alloc, free} #ifndef __APPLE__ #include // ::malloc_usable_size #else #include #include #define malloc_usable_size malloc_size #endif #include "proxsuite/linalg/veg/internal/prologue.hpp" namespace proxsuite { namespace linalg { namespace veg { #ifdef __APPLE__ namespace alignment { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101500 && \ (defined(_LIBCPP_HAS_ALIGNED_ALLOC) || defined(_LIBCPP_HAS_C11_FEATURES)) && \ defined(PROXSUITE_WITH_CPP_17) VEG_INLINE void* aligned_alloc(std::size_t alignment, std::size_t size) { return std::aligned_alloc(alignment, size); } #elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 VEG_INLINE void* aligned_alloc(std::size_t alignment, std::size_t size) { if (alignment < sizeof(void*)) { alignment = sizeof(void*); } void* p; if (::posix_memalign(&p, alignment, size) != 0) { p = 0; } return p; } #endif } // namespace alignment #endif // Support aligned_alloc for c++14, code from boost/align. namespace alignment { namespace detail { // Source: https://www.boost.org/doc/libs/1_65_0/boost/align/detail/min_size.hpp template struct min_size : std::integral_constant {}; template struct offset_value { char value; T object; }; // Source: // https://www.boost.org/doc/libs/1_65_0/boost/align/detail/alignment_of.hpp template struct alignment_of : min_size) - sizeof(T)> {}; // Source: // https://www.boost.org/doc/libs/1_65_0/boost/align/detail/is_alignment.hpp constexpr inline bool is_alignment(std::size_t value) { return (value > 0) && ((value & (value - 1)) == 0); } // Source: https://www.boost.org/doc/libs/1_74_0/boost/align/detail/align.hpp inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space) { assert(is_alignment(alignment)); char* p = reinterpret_cast( ~(alignment - 1) & (reinterpret_cast(ptr) + alignment - 1)); assert((p - static_cast(ptr)) >= 0); std::size_t n = std::size_t(p - static_cast(ptr)); if (size + n <= space) { ptr = p; space -= n; return p; } return 0; } // Source: // https://www.boost.org/doc/libs/1_65_0/boost/align/detail/aligned_alloc.hpp inline void* aligned_alloc(std::size_t alignment, std::size_t size) { assert(is_alignment(alignment)); enum { N = alignment_of::value }; if (alignment < N) { alignment = N; } std::size_t n = size + alignment - N; void* p = std::malloc(sizeof(void*) + n); if (p) { void* r = static_cast(p) + sizeof(void*); (void)align(alignment, size, r, n); *(static_cast(r) - 1) = p; p = r; } return p; } } // namespace detail } // namespace alignment namespace mem { enum struct CopyAvailable { no, yes_maythrow, yes_nothrow, }; enum struct DtorAvailable { no, yes_maythrow, yes_nothrow, }; template struct CopyAvailableFor : meta::constant) && VEG_CONCEPT(nothrow_copy_assignable)) ? CopyAvailable::yes_nothrow : (VEG_CONCEPT(copyable) && VEG_CONCEPT(copy_assignable)) ? CopyAvailable::yes_maythrow : CopyAvailable::no> {}; template struct DtorAvailableFor : meta::constant) ? DtorAvailable::yes_nothrow : DtorAvailable::yes_maythrow> {}; VEG_INLINE auto aligned_alloc(usize align, usize size) noexcept -> void* { usize const mask = align - 1; #if defined(_WIN32) return _aligned_malloc((size + mask) & ~mask, align); #elif defined(__APPLE__) #ifdef PROXSUITE_WITH_CPP_17 return alignment::aligned_alloc(align, (size + mask) & ~mask); #else return alignment::detail::aligned_alloc(align, (size + mask) & ~mask); #endif #else #ifdef PROXSUITE_WITH_CPP_17 return std::aligned_alloc(align, (size + mask) & ~mask); #else return alignment::detail::aligned_alloc(align, (size + mask) & ~mask); #endif #endif } VEG_INLINE void aligned_free(usize /*align*/, void* ptr) noexcept { #ifndef _WIN32 std::free(ptr); #else _aligned_free(ptr); #endif } struct SystemAlloc { constexpr friend auto operator==(SystemAlloc /*unused*/, SystemAlloc /*unused*/) noexcept -> bool { return true; } }; template<> struct Alloc { static constexpr usize max_base_align = alignof(std::max_align_t); VEG_INLINE static void dealloc(RefMut /*alloc*/, void* ptr, Layout layout) noexcept { (layout.align <= max_base_align) ? std::free(ptr) : mem::aligned_free(layout.align, ptr); } VEG_NODISCARD VEG_INLINE static auto alloc(RefMut /*alloc*/, Layout layout) noexcept -> mem::AllocBlock { void* ptr = (layout.align <= max_base_align) ? std::malloc(layout.byte_size) : mem::aligned_alloc(layout.align, layout.byte_size); if (HEDLEY_UNLIKELY(ptr == nullptr)) { _detail::terminate(); } #ifndef _WIN32 return { ptr, ::malloc_usable_size(ptr) }; #else return { ptr, _msize(ptr) }; #endif } VEG_NODISCARD VEG_NO_INLINE static auto realloc(RefMut /*alloc*/, void* ptr, Layout layout, usize new_size, usize copy_size, RelocFn reloc) noexcept -> mem::AllocBlock { void* new_ptr; // NOLINT bool typical_align = layout.align <= max_base_align; bool trivial_reloc = reloc.is_trivial(); bool use_realloc = typical_align && trivial_reloc; if (use_realloc) { new_ptr = std::realloc(ptr, new_size); } else { new_ptr = mem::aligned_alloc(layout.align, new_size); } if (HEDLEY_UNLIKELY(new_ptr == nullptr)) { _detail::terminate(); } if (!use_realloc) { reloc(new_ptr, ptr, copy_size); mem::aligned_free(layout.align, ptr); } #ifndef _WIN32 return { new_ptr, ::malloc_usable_size(new_ptr) }; #else return { new_ptr, _msize(new_ptr) }; #endif } VEG_NODISCARD VEG_INLINE auto try_grow_in_place( void* /*ptr*/, Layout /*layout*/, usize /*new_size*/) const noexcept -> bool { return false; } VEG_NODISCARD VEG_INLINE static auto grow(RefMut alloc, void* ptr, Layout layout, usize new_size, RelocFn reloc) noexcept -> mem::AllocBlock { return realloc( VEG_FWD(alloc), ptr, layout, new_size, layout.byte_size, reloc); } VEG_NODISCARD VEG_INLINE static auto shrink(RefMut alloc, void* ptr, Layout layout, usize new_size, RelocFn reloc) noexcept -> mem::AllocBlock { return realloc(VEG_FWD(alloc), ptr, layout, new_size, new_size, reloc); } }; struct DefaultCloner {}; template<> struct Cloner { template using trivial_clone = meta::bool_constant)>; template VEG_INLINE static void destroy(RefMut /*cloner*/, T* ptr, RefMut /*alloc*/) VEG_NOEXCEPT_IF(VEG_CONCEPT(nothrow_destructible)) { mem::destroy_at(ptr); } VEG_TEMPLATE((typename T, typename Alloc), requires(VEG_CONCEPT(copyable)), VEG_NODISCARD VEG_INLINE static auto clone, (/*cloner*/, RefMut), (rhs, Ref), (/*alloc*/, RefMut)) VEG_NOEXCEPT_IF(VEG_CONCEPT(nothrow_copyable))->T { return T(rhs.get()); } VEG_TEMPLATE((typename T, typename Alloc), requires(VEG_CONCEPT(copyable)), VEG_INLINE static void clone_from, (/*cloner*/, RefMut), (lhs, RefMut), (rhs, Ref), (/*alloc*/, RefMut)) VEG_NOEXCEPT_IF(VEG_CONCEPT(nothrow_copy_assignable)) { lhs.get() = rhs.get(); } }; VEG_INLINE_VAR(system_alloc, SystemAlloc); VEG_INLINE_VAR(default_cloner, DefaultCloner); } // namespace mem namespace _detail { namespace _mem { template struct ManagedAlloc /* NOLINT */ { void* data; mem::Layout layout; RefMut alloc; VEG_INLINE ~ManagedAlloc() { if (data != nullptr) { mem::Alloc::dealloc(VEG_FWD(alloc), VEG_FWD(data), VEG_FWD(layout)); } } }; } // namespace _mem } // namespace _detail } // namespace veg } // namespace linalg } // namespace proxsuite #include "proxsuite/linalg/veg/internal/epilogue.hpp" #endif /* end of include guard VEG_ALLOC_HPP_TAWYRUICS */