handler_alloc_helpers.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. //
  2. // detail/handler_alloc_helpers.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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/associated_allocator.hpp>
  20. #include <boost/asio/handler_alloc_hook.hpp>
  21. #include <boost/asio/detail/push_options.hpp>
  22. // Calls to asio_handler_allocate and asio_handler_deallocate must be made from
  23. // a namespace that does not contain any overloads of these functions. The
  24. // boost_asio_handler_alloc_helpers namespace is defined here for that purpose.
  25. namespace boost_asio_handler_alloc_helpers {
  26. template <typename Handler>
  27. inline void* allocate(std::size_t s, Handler& h)
  28. {
  29. #if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
  30. return ::operator new(s);
  31. #else
  32. using boost::asio::asio_handler_allocate;
  33. return asio_handler_allocate(s, boost::asio::detail::addressof(h));
  34. #endif
  35. }
  36. template <typename Handler>
  37. inline void deallocate(void* p, std::size_t s, Handler& h)
  38. {
  39. #if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
  40. ::operator delete(p);
  41. #else
  42. using boost::asio::asio_handler_deallocate;
  43. asio_handler_deallocate(p, s, boost::asio::detail::addressof(h));
  44. #endif
  45. }
  46. } // namespace boost_asio_handler_alloc_helpers
  47. namespace boost {
  48. namespace asio {
  49. namespace detail {
  50. template <typename Handler, typename T>
  51. class hook_allocator
  52. {
  53. public:
  54. typedef T value_type;
  55. template <typename U>
  56. struct rebind
  57. {
  58. typedef hook_allocator<Handler, U> other;
  59. };
  60. explicit hook_allocator(Handler& h)
  61. : handler_(h)
  62. {
  63. }
  64. template <typename U>
  65. hook_allocator(const hook_allocator<Handler, U>& a)
  66. : handler_(a.handler_)
  67. {
  68. }
  69. T* allocate(std::size_t n)
  70. {
  71. return static_cast<T*>(
  72. boost_asio_handler_alloc_helpers::allocate(sizeof(T) * n, handler_));
  73. }
  74. void deallocate(T* p, std::size_t n)
  75. {
  76. boost_asio_handler_alloc_helpers::deallocate(p, sizeof(T) * n, handler_);
  77. }
  78. //private:
  79. Handler& handler_;
  80. };
  81. template <typename Handler>
  82. class hook_allocator<Handler, void>
  83. {
  84. public:
  85. typedef void value_type;
  86. template <typename U>
  87. struct rebind
  88. {
  89. typedef hook_allocator<Handler, U> other;
  90. };
  91. explicit hook_allocator(Handler& h)
  92. : handler_(h)
  93. {
  94. }
  95. template <typename U>
  96. hook_allocator(const hook_allocator<Handler, U>& a)
  97. : handler_(a.handler_)
  98. {
  99. }
  100. //private:
  101. Handler& handler_;
  102. };
  103. template <typename Handler, typename Allocator>
  104. struct get_hook_allocator
  105. {
  106. typedef Allocator type;
  107. static type get(Handler&, const Allocator& a)
  108. {
  109. return a;
  110. }
  111. };
  112. template <typename Handler, typename T>
  113. struct get_hook_allocator<Handler, std::allocator<T> >
  114. {
  115. typedef hook_allocator<Handler, T> type;
  116. static type get(Handler& handler, const std::allocator<T>&)
  117. {
  118. return type(handler);
  119. }
  120. };
  121. } // namespace detail
  122. } // namespace asio
  123. } // namespace boost
  124. #define BOOST_ASIO_DEFINE_HANDLER_PTR(op) \
  125. struct ptr \
  126. { \
  127. Handler* h; \
  128. op* v; \
  129. op* p; \
  130. ~ptr() \
  131. { \
  132. reset(); \
  133. } \
  134. static op* allocate(Handler& handler) \
  135. { \
  136. typedef typename ::boost::asio::associated_allocator< \
  137. Handler>::type associated_allocator_type; \
  138. typedef typename ::boost::asio::detail::get_hook_allocator< \
  139. Handler, associated_allocator_type>::type hook_allocator_type; \
  140. BOOST_ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \
  141. ::boost::asio::detail::get_hook_allocator< \
  142. Handler, associated_allocator_type>::get( \
  143. handler, ::boost::asio::get_associated_allocator(handler))); \
  144. return a.allocate(1); \
  145. } \
  146. void reset() \
  147. { \
  148. if (p) \
  149. { \
  150. p->~op(); \
  151. p = 0; \
  152. } \
  153. if (v) \
  154. { \
  155. typedef typename ::boost::asio::associated_allocator< \
  156. Handler>::type associated_allocator_type; \
  157. typedef typename ::boost::asio::detail::get_hook_allocator< \
  158. Handler, associated_allocator_type>::type hook_allocator_type; \
  159. BOOST_ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \
  160. ::boost::asio::detail::get_hook_allocator< \
  161. Handler, associated_allocator_type>::get( \
  162. *h, ::boost::asio::get_associated_allocator(*h))); \
  163. a.deallocate(static_cast<op*>(v), 1); \
  164. v = 0; \
  165. } \
  166. } \
  167. } \
  168. /**/
  169. #define BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \
  170. struct ptr \
  171. { \
  172. const Alloc* a; \
  173. void* v; \
  174. op* p; \
  175. ~ptr() \
  176. { \
  177. reset(); \
  178. } \
  179. static op* allocate(const Alloc& a) \
  180. { \
  181. typedef typename ::boost::asio::detail::get_recycling_allocator< \
  182. Alloc>::type recycling_allocator_type; \
  183. BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
  184. ::boost::asio::detail::get_recycling_allocator<Alloc>::get(a)); \
  185. return a1.allocate(1); \
  186. } \
  187. void reset() \
  188. { \
  189. if (p) \
  190. { \
  191. p->~op(); \
  192. p = 0; \
  193. } \
  194. if (v) \
  195. { \
  196. typedef typename ::boost::asio::detail::get_recycling_allocator< \
  197. Alloc>::type recycling_allocator_type; \
  198. BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
  199. ::boost::asio::detail::get_recycling_allocator<Alloc>::get(*a)); \
  200. a1.deallocate(static_cast<op*>(v), 1); \
  201. v = 0; \
  202. } \
  203. } \
  204. } \
  205. /**/
  206. #include <boost/asio/detail/pop_options.hpp>
  207. #endif // BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP