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