handler_alloc_helpers.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. //
  2. // detail/handler_alloc_helpers.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 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_HANDLER_ALLOC_HELPERS_HPP
  11. #define BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_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 <boost/asio/detail/memory.hpp>
  17. #include <boost/asio/detail/noncopyable.hpp>
  18. #include <boost/asio/detail/recycling_allocator.hpp>
  19. #include <boost/asio/detail/thread_info_base.hpp>
  20. #include <boost/asio/associated_allocator.hpp>
  21. #include <boost/asio/handler_alloc_hook.hpp>
  22. #include <boost/asio/detail/push_options.hpp>
  23. // Calls to asio_handler_allocate and asio_handler_deallocate must be made from
  24. // a namespace that does not contain any overloads of these functions. The
  25. // boost_asio_handler_alloc_helpers namespace is defined here for that purpose.
  26. namespace boost_asio_handler_alloc_helpers {
  27. #if defined(BOOST_ASIO_NO_DEPRECATED)
  28. template <typename Handler>
  29. inline void error_if_hooks_are_defined(Handler& h)
  30. {
  31. using boost::asio::asio_handler_allocate;
  32. // If you get an error here it is because some of your handlers still
  33. // overload asio_handler_allocate, but this hook is no longer used.
  34. (void)static_cast<boost::asio::asio_handler_allocate_is_no_longer_used>(
  35. asio_handler_allocate(static_cast<std::size_t>(0),
  36. boost::asio::detail::addressof(h)));
  37. using boost::asio::asio_handler_deallocate;
  38. // If you get an error here it is because some of your handlers still
  39. // overload asio_handler_deallocate, but this hook is no longer used.
  40. (void)static_cast<boost::asio::asio_handler_deallocate_is_no_longer_used>(
  41. asio_handler_deallocate(static_cast<void*>(0),
  42. static_cast<std::size_t>(0), boost::asio::detail::addressof(h)));
  43. }
  44. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  45. template <typename Handler>
  46. inline void* allocate(std::size_t s, Handler& h)
  47. {
  48. #if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
  49. return ::operator new(s);
  50. #elif defined(BOOST_ASIO_NO_DEPRECATED)
  51. // The asio_handler_allocate hook is no longer used to obtain memory.
  52. (void)&error_if_hooks_are_defined<Handler>;
  53. (void)h;
  54. #if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
  55. return boost::asio::detail::thread_info_base::allocate(
  56. boost::asio::detail::thread_context::top_of_thread_call_stack(), s);
  57. #else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
  58. return ::operator new(size);
  59. #endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
  60. #else
  61. using boost::asio::asio_handler_allocate;
  62. return asio_handler_allocate(s, boost::asio::detail::addressof(h));
  63. #endif
  64. }
  65. template <typename Handler>
  66. inline void deallocate(void* p, std::size_t s, Handler& h)
  67. {
  68. #if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
  69. ::operator delete(p);
  70. #elif defined(BOOST_ASIO_NO_DEPRECATED)
  71. // The asio_handler_allocate hook is no longer used to obtain memory.
  72. (void)&error_if_hooks_are_defined<Handler>;
  73. (void)h;
  74. #if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
  75. boost::asio::detail::thread_info_base::deallocate(
  76. boost::asio::detail::thread_context::top_of_thread_call_stack(), p, s);
  77. #else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
  78. (void)s;
  79. ::operator delete(p);
  80. #endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
  81. #else
  82. using boost::asio::asio_handler_deallocate;
  83. asio_handler_deallocate(p, s, boost::asio::detail::addressof(h));
  84. #endif
  85. }
  86. } // namespace boost_asio_handler_alloc_helpers
  87. namespace boost {
  88. namespace asio {
  89. namespace detail {
  90. template <typename Handler, typename T>
  91. class hook_allocator
  92. {
  93. public:
  94. typedef T value_type;
  95. template <typename U>
  96. struct rebind
  97. {
  98. typedef hook_allocator<Handler, U> other;
  99. };
  100. explicit hook_allocator(Handler& h)
  101. : handler_(h)
  102. {
  103. }
  104. template <typename U>
  105. hook_allocator(const hook_allocator<Handler, U>& a)
  106. : handler_(a.handler_)
  107. {
  108. }
  109. T* allocate(std::size_t n)
  110. {
  111. return static_cast<T*>(
  112. boost_asio_handler_alloc_helpers::allocate(sizeof(T) * n, handler_));
  113. }
  114. void deallocate(T* p, std::size_t n)
  115. {
  116. boost_asio_handler_alloc_helpers::deallocate(p, sizeof(T) * n, handler_);
  117. }
  118. //private:
  119. Handler& handler_;
  120. };
  121. template <typename Handler>
  122. class hook_allocator<Handler, void>
  123. {
  124. public:
  125. typedef void value_type;
  126. template <typename U>
  127. struct rebind
  128. {
  129. typedef hook_allocator<Handler, U> other;
  130. };
  131. explicit hook_allocator(Handler& h)
  132. : handler_(h)
  133. {
  134. }
  135. template <typename U>
  136. hook_allocator(const hook_allocator<Handler, U>& a)
  137. : handler_(a.handler_)
  138. {
  139. }
  140. //private:
  141. Handler& handler_;
  142. };
  143. template <typename Handler, typename Allocator>
  144. struct get_hook_allocator
  145. {
  146. typedef Allocator type;
  147. static type get(Handler&, const Allocator& a)
  148. {
  149. return a;
  150. }
  151. };
  152. template <typename Handler, typename T>
  153. struct get_hook_allocator<Handler, std::allocator<T> >
  154. {
  155. typedef hook_allocator<Handler, T> type;
  156. static type get(Handler& handler, const std::allocator<T>&)
  157. {
  158. return type(handler);
  159. }
  160. };
  161. } // namespace detail
  162. } // namespace asio
  163. } // namespace boost
  164. #define BOOST_ASIO_DEFINE_HANDLER_PTR(op) \
  165. struct ptr \
  166. { \
  167. Handler* h; \
  168. op* v; \
  169. op* p; \
  170. ~ptr() \
  171. { \
  172. reset(); \
  173. } \
  174. static op* allocate(Handler& handler) \
  175. { \
  176. typedef typename ::boost::asio::associated_allocator< \
  177. Handler>::type associated_allocator_type; \
  178. typedef typename ::boost::asio::detail::get_hook_allocator< \
  179. Handler, associated_allocator_type>::type hook_allocator_type; \
  180. BOOST_ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \
  181. ::boost::asio::detail::get_hook_allocator< \
  182. Handler, associated_allocator_type>::get( \
  183. handler, ::boost::asio::get_associated_allocator(handler))); \
  184. return a.allocate(1); \
  185. } \
  186. void reset() \
  187. { \
  188. if (p) \
  189. { \
  190. p->~op(); \
  191. p = 0; \
  192. } \
  193. if (v) \
  194. { \
  195. typedef typename ::boost::asio::associated_allocator< \
  196. Handler>::type associated_allocator_type; \
  197. typedef typename ::boost::asio::detail::get_hook_allocator< \
  198. Handler, associated_allocator_type>::type hook_allocator_type; \
  199. BOOST_ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \
  200. ::boost::asio::detail::get_hook_allocator< \
  201. Handler, associated_allocator_type>::get( \
  202. *h, ::boost::asio::get_associated_allocator(*h))); \
  203. a.deallocate(static_cast<op*>(v), 1); \
  204. v = 0; \
  205. } \
  206. } \
  207. } \
  208. /**/
  209. #define BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(purpose, op) \
  210. struct ptr \
  211. { \
  212. const Alloc* a; \
  213. void* v; \
  214. op* p; \
  215. ~ptr() \
  216. { \
  217. reset(); \
  218. } \
  219. static op* allocate(const Alloc& a) \
  220. { \
  221. typedef typename ::boost::asio::detail::get_recycling_allocator< \
  222. Alloc, purpose>::type recycling_allocator_type; \
  223. BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
  224. ::boost::asio::detail::get_recycling_allocator< \
  225. Alloc, purpose>::get(a)); \
  226. return a1.allocate(1); \
  227. } \
  228. void reset() \
  229. { \
  230. if (p) \
  231. { \
  232. p->~op(); \
  233. p = 0; \
  234. } \
  235. if (v) \
  236. { \
  237. typedef typename ::boost::asio::detail::get_recycling_allocator< \
  238. Alloc, purpose>::type recycling_allocator_type; \
  239. BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
  240. ::boost::asio::detail::get_recycling_allocator< \
  241. Alloc, purpose>::get(*a)); \
  242. a1.deallocate(static_cast<op*>(v), 1); \
  243. v = 0; \
  244. } \
  245. } \
  246. } \
  247. /**/
  248. #define BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \
  249. BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR( \
  250. ::boost::asio::detail::thread_info_base::default_tag, op ) \
  251. /**/
  252. #include <boost/asio/detail/pop_options.hpp>
  253. #endif // BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP