handler_alloc_helpers.hpp 7.7 KB

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