memory.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //
  2. // detail/memory.hpp
  3. // ~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_DETAIL_MEMORY_HPP
  11. #define BOOST_ASIO_DETAIL_MEMORY_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <cstddef>
  17. #include <cstdlib>
  18. #include <memory>
  19. #include <new>
  20. #include <boost/asio/detail/cstdint.hpp>
  21. #include <boost/asio/detail/throw_exception.hpp>
  22. #if !defined(BOOST_ASIO_HAS_STD_ALIGNED_ALLOC) \
  23. && defined(BOOST_ASIO_HAS_BOOST_ALIGN)
  24. # include <boost/align/aligned_alloc.hpp>
  25. #endif // !defined(BOOST_ASIO_HAS_STD_ALIGNED_ALLOC)
  26. // && defined(BOOST_ASIO_HAS_BOOST_ALIGN)
  27. namespace boost {
  28. namespace asio {
  29. namespace detail {
  30. using std::allocate_shared;
  31. using std::make_shared;
  32. using std::shared_ptr;
  33. using std::weak_ptr;
  34. using std::addressof;
  35. #if defined(BOOST_ASIO_HAS_STD_TO_ADDRESS)
  36. using std::to_address;
  37. #else // defined(BOOST_ASIO_HAS_STD_TO_ADDRESS)
  38. template <typename T>
  39. inline T* to_address(T* p) { return p; }
  40. template <typename T>
  41. inline const T* to_address(const T* p) { return p; }
  42. template <typename T>
  43. inline volatile T* to_address(volatile T* p) { return p; }
  44. template <typename T>
  45. inline const volatile T* to_address(const volatile T* p) { return p; }
  46. #endif // defined(BOOST_ASIO_HAS_STD_TO_ADDRESS)
  47. inline void* align(std::size_t alignment,
  48. std::size_t size, void*& ptr, std::size_t& space)
  49. {
  50. return std::align(alignment, size, ptr, space);
  51. }
  52. template <typename T, typename Allocator, typename... Args>
  53. T* allocate_object(const Allocator& a, Args&&... args)
  54. {
  55. typename std::allocator_traits<Allocator>::template rebind_alloc<T> alloc(a);
  56. T* raw = std::allocator_traits<decltype(alloc)>::allocate(alloc, 1);
  57. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  58. try
  59. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  60. {
  61. return new (raw) T(static_cast<Args&&>(args)...);
  62. }
  63. #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
  64. catch (...)
  65. {
  66. std::allocator_traits<decltype(alloc)>::deallocate(alloc, raw, 1);
  67. throw;
  68. }
  69. #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
  70. }
  71. template <typename Allocator, typename T>
  72. void deallocate_object(const Allocator& a, T* ptr)
  73. {
  74. typename std::allocator_traits<Allocator>::template rebind_alloc<T> alloc(a);
  75. std::allocator_traits<decltype(alloc)>::destroy(alloc, ptr);
  76. std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1);
  77. }
  78. } // namespace detail
  79. using std::allocator_arg_t;
  80. # define BOOST_ASIO_USES_ALLOCATOR(t) \
  81. namespace std { \
  82. template <typename Allocator> \
  83. struct uses_allocator<t, Allocator> : true_type {}; \
  84. } \
  85. /**/
  86. # define BOOST_ASIO_REBIND_ALLOC(alloc, t) \
  87. typename std::allocator_traits<alloc>::template rebind_alloc<t>
  88. /**/
  89. inline void* aligned_new(std::size_t align, std::size_t size)
  90. {
  91. #if defined(BOOST_ASIO_HAS_STD_ALIGNED_ALLOC)
  92. align = (align < BOOST_ASIO_DEFAULT_ALIGN) ? BOOST_ASIO_DEFAULT_ALIGN : align;
  93. size = (size % align == 0) ? size : size + (align - size % align);
  94. void* ptr = std::aligned_alloc(align, size);
  95. if (!ptr)
  96. {
  97. std::bad_alloc ex;
  98. boost::asio::detail::throw_exception(ex);
  99. }
  100. return ptr;
  101. #elif defined(BOOST_ASIO_HAS_BOOST_ALIGN)
  102. align = (align < BOOST_ASIO_DEFAULT_ALIGN) ? BOOST_ASIO_DEFAULT_ALIGN : align;
  103. size = (size % align == 0) ? size : size + (align - size % align);
  104. void* ptr = boost::alignment::aligned_alloc(align, size);
  105. if (!ptr)
  106. {
  107. std::bad_alloc ex;
  108. boost::asio::detail::throw_exception(ex);
  109. }
  110. return ptr;
  111. #elif defined(BOOST_ASIO_MSVC)
  112. align = (align < BOOST_ASIO_DEFAULT_ALIGN) ? BOOST_ASIO_DEFAULT_ALIGN : align;
  113. size = (size % align == 0) ? size : size + (align - size % align);
  114. void* ptr = _aligned_malloc(size, align);
  115. if (!ptr)
  116. {
  117. std::bad_alloc ex;
  118. boost::asio::detail::throw_exception(ex);
  119. }
  120. return ptr;
  121. #else // defined(BOOST_ASIO_MSVC)
  122. (void)align;
  123. return ::operator new(size);
  124. #endif // defined(BOOST_ASIO_MSVC)
  125. }
  126. inline void aligned_delete(void* ptr)
  127. {
  128. #if defined(BOOST_ASIO_HAS_STD_ALIGNED_ALLOC)
  129. std::free(ptr);
  130. #elif defined(BOOST_ASIO_HAS_BOOST_ALIGN)
  131. boost::alignment::aligned_free(ptr);
  132. #elif defined(BOOST_ASIO_MSVC)
  133. _aligned_free(ptr);
  134. #else // defined(BOOST_ASIO_MSVC)
  135. ::operator delete(ptr);
  136. #endif // defined(BOOST_ASIO_MSVC)
  137. }
  138. } // namespace asio
  139. } // namespace boost
  140. #endif // BOOST_ASIO_DETAIL_MEMORY_HPP