2 // detail/handler_alloc_helpers.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
12 #define BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/detail/memory.hpp>
20 #include <boost/asio/detail/noncopyable.hpp>
21 #include <boost/asio/detail/recycling_allocator.hpp>
22 #include <boost/asio/associated_allocator.hpp>
23 #include <boost/asio/handler_alloc_hook.hpp>
25 #include <boost/asio/detail/push_options.hpp>
27 // Calls to asio_handler_allocate and asio_handler_deallocate must be made from
28 // a namespace that does not contain any overloads of these functions. The
29 // boost_asio_handler_alloc_helpers namespace is defined here for that purpose.
30 namespace boost_asio_handler_alloc_helpers {
32 template <typename Handler>
33 inline void* allocate(std::size_t s, Handler& h)
35 #if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
36 return ::operator new(s);
38 using boost::asio::asio_handler_allocate;
39 return asio_handler_allocate(s, boost::asio::detail::addressof(h));
43 template <typename Handler>
44 inline void deallocate(void* p, std::size_t s, Handler& h)
46 #if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS)
49 using boost::asio::asio_handler_deallocate;
50 asio_handler_deallocate(p, s, boost::asio::detail::addressof(h));
54 } // namespace boost_asio_handler_alloc_helpers
60 template <typename Handler, typename T>
69 typedef hook_allocator<Handler, U> other;
72 explicit hook_allocator(Handler& h)
78 hook_allocator(const hook_allocator<Handler, U>& a)
79 : handler_(a.handler_)
83 T* allocate(std::size_t n)
85 return static_cast<T*>(
86 boost_asio_handler_alloc_helpers::allocate(sizeof(T) * n, handler_));
89 void deallocate(T* p, std::size_t n)
91 boost_asio_handler_alloc_helpers::deallocate(p, sizeof(T) * n, handler_);
98 template <typename Handler>
99 class hook_allocator<Handler, void>
102 typedef void value_type;
104 template <typename U>
107 typedef hook_allocator<Handler, U> other;
110 explicit hook_allocator(Handler& h)
115 template <typename U>
116 hook_allocator(const hook_allocator<Handler, U>& a)
117 : handler_(a.handler_)
125 template <typename Handler, typename Allocator>
126 struct get_hook_allocator
128 typedef Allocator type;
130 static type get(Handler&, const Allocator& a)
136 template <typename Handler, typename T>
137 struct get_hook_allocator<Handler, std::allocator<T> >
139 typedef hook_allocator<Handler, T> type;
141 static type get(Handler& handler, const std::allocator<T>&)
143 return type(handler);
147 } // namespace detail
151 #define BOOST_ASIO_DEFINE_HANDLER_PTR(op) \
161 static op* allocate(Handler& handler) \
163 typedef typename ::boost::asio::associated_allocator< \
164 Handler>::type associated_allocator_type; \
165 typedef typename ::boost::asio::detail::get_hook_allocator< \
166 Handler, associated_allocator_type>::type hook_allocator_type; \
167 BOOST_ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \
168 ::boost::asio::detail::get_hook_allocator< \
169 Handler, associated_allocator_type>::get( \
170 handler, ::boost::asio::get_associated_allocator(handler))); \
171 return a.allocate(1); \
182 typedef typename ::boost::asio::associated_allocator< \
183 Handler>::type associated_allocator_type; \
184 typedef typename ::boost::asio::detail::get_hook_allocator< \
185 Handler, associated_allocator_type>::type hook_allocator_type; \
186 BOOST_ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \
187 ::boost::asio::detail::get_hook_allocator< \
188 Handler, associated_allocator_type>::get( \
189 *h, ::boost::asio::get_associated_allocator(*h))); \
190 a.deallocate(static_cast<op*>(v), 1); \
197 #define BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(purpose, op) \
207 static op* allocate(const Alloc& a) \
209 typedef typename ::boost::asio::detail::get_recycling_allocator< \
210 Alloc, purpose>::type recycling_allocator_type; \
211 BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
212 ::boost::asio::detail::get_recycling_allocator< \
213 Alloc, purpose>::get(a)); \
214 return a1.allocate(1); \
225 typedef typename ::boost::asio::detail::get_recycling_allocator< \
226 Alloc, purpose>::type recycling_allocator_type; \
227 BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
228 ::boost::asio::detail::get_recycling_allocator< \
229 Alloc, purpose>::get(*a)); \
230 a1.deallocate(static_cast<op*>(v), 1); \
237 #define BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \
238 BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR( \
239 ::boost::asio::detail::thread_info_base::default_tag, op ) \
242 #include <boost/asio/detail/pop_options.hpp>
244 #endif // BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP