1
2 // impl/redirect_error.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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
11 #ifndef BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP
12 #define BOOST_ASIO_IMPL_REDIRECT_ERROR_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/associated_executor.hpp>
20 #include <boost/asio/associated_allocator.hpp>
21 #include <boost/asio/async_result.hpp>
22 #include <boost/asio/detail/handler_alloc_helpers.hpp>
23 #include <boost/asio/detail/handler_cont_helpers.hpp>
24 #include <boost/asio/detail/handler_invoke_helpers.hpp>
25 #include <boost/asio/detail/type_traits.hpp>
26 #include <boost/asio/detail/variadic_templates.hpp>
27 #include <boost/system/system_error.hpp>
28
29 #include <boost/asio/detail/push_options.hpp>
30
31 namespace boost {
32 namespace asio {
33 namespace detail {
34
35 // Class to adapt a redirect_error_t as a completion handler.
36 template <typename Handler>
37 class redirect_error_handler
38 {
39 public:
40 typedef void result_type;
41
42 template <typename CompletionToken>
redirect_error_handler(redirect_error_t<CompletionToken> e)43 redirect_error_handler(redirect_error_t<CompletionToken> e)
44 : ec_(e.ec_),
45 handler_(BOOST_ASIO_MOVE_CAST(CompletionToken)(e.token_))
46 {
47 }
48
49 template <typename RedirectedHandler>
redirect_error_handler(boost::system::error_code & ec,BOOST_ASIO_MOVE_ARG (RedirectedHandler)h)50 redirect_error_handler(boost::system::error_code& ec,
51 BOOST_ASIO_MOVE_ARG(RedirectedHandler) h)
52 : ec_(ec),
53 handler_(BOOST_ASIO_MOVE_CAST(RedirectedHandler)(h))
54 {
55 }
56
operator ()()57 void operator()()
58 {
59 handler_();
60 }
61
62 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
63
64 template <typename Arg, typename... Args>
65 typename enable_if<
66 !is_same<typename decay<Arg>::type, boost::system::error_code>::value
67 >::type
operator ()(BOOST_ASIO_MOVE_ARG (Arg)arg,BOOST_ASIO_MOVE_ARG (Args)...args)68 operator()(BOOST_ASIO_MOVE_ARG(Arg) arg, BOOST_ASIO_MOVE_ARG(Args)... args)
69 {
70 handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg),
71 BOOST_ASIO_MOVE_CAST(Args)(args)...);
72 }
73
74 template <typename... Args>
operator ()(const boost::system::error_code & ec,BOOST_ASIO_MOVE_ARG (Args)...args)75 void operator()(const boost::system::error_code& ec,
76 BOOST_ASIO_MOVE_ARG(Args)... args)
77 {
78 ec_ = ec;
79 handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
80 }
81
82 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
83
84 template <typename Arg>
85 typename enable_if<
86 !is_same<typename decay<Arg>::type, boost::system::error_code>::value
87 >::type
operator ()(BOOST_ASIO_MOVE_ARG (Arg)arg)88 operator()(BOOST_ASIO_MOVE_ARG(Arg) arg)
89 {
90 handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg));
91 }
92
operator ()(const boost::system::error_code & ec)93 void operator()(const boost::system::error_code& ec)
94 {
95 ec_ = ec;
96 handler_();
97 }
98
99 #define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \
100 template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
101 typename enable_if< \
102 !is_same<typename decay<Arg>::type, boost::system::error_code>::value \
103 >::type \
104 operator()(BOOST_ASIO_MOVE_ARG(Arg) arg, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
105 { \
106 handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg), \
107 BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
108 } \
109 \
110 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
111 void operator()(const boost::system::error_code& ec, \
112 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
113 { \
114 ec_ = ec; \
115 handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
116 } \
117 /**/
118 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF)
119 #undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF
120
121 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
122
123 //private:
124 boost::system::error_code& ec_;
125 Handler handler_;
126 };
127
128 template <typename Handler>
129 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,redirect_error_handler<Handler> * this_handler)130 asio_handler_allocate(std::size_t size,
131 redirect_error_handler<Handler>* this_handler)
132 {
133 #if defined(BOOST_ASIO_NO_DEPRECATED)
134 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
135 return asio_handler_allocate_is_no_longer_used();
136 #else // defined(BOOST_ASIO_NO_DEPRECATED)
137 return boost_asio_handler_alloc_helpers::allocate(
138 size, this_handler->handler_);
139 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
140 }
141
142 template <typename Handler>
143 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,redirect_error_handler<Handler> * this_handler)144 asio_handler_deallocate(void* pointer, std::size_t size,
145 redirect_error_handler<Handler>* this_handler)
146 {
147 boost_asio_handler_alloc_helpers::deallocate(
148 pointer, size, this_handler->handler_);
149 #if defined(BOOST_ASIO_NO_DEPRECATED)
150 return asio_handler_deallocate_is_no_longer_used();
151 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
152 }
153
154 template <typename Handler>
asio_handler_is_continuation(redirect_error_handler<Handler> * this_handler)155 inline bool asio_handler_is_continuation(
156 redirect_error_handler<Handler>* this_handler)
157 {
158 return boost_asio_handler_cont_helpers::is_continuation(
159 this_handler->handler_);
160 }
161
162 template <typename Function, typename Handler>
163 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,redirect_error_handler<Handler> * this_handler)164 asio_handler_invoke(Function& function,
165 redirect_error_handler<Handler>* this_handler)
166 {
167 boost_asio_handler_invoke_helpers::invoke(
168 function, this_handler->handler_);
169 #if defined(BOOST_ASIO_NO_DEPRECATED)
170 return asio_handler_invoke_is_no_longer_used();
171 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
172 }
173
174 template <typename Function, typename Handler>
175 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,redirect_error_handler<Handler> * this_handler)176 asio_handler_invoke(const Function& function,
177 redirect_error_handler<Handler>* this_handler)
178 {
179 boost_asio_handler_invoke_helpers::invoke(
180 function, this_handler->handler_);
181 #if defined(BOOST_ASIO_NO_DEPRECATED)
182 return asio_handler_invoke_is_no_longer_used();
183 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
184 }
185
186 template <typename Signature>
187 struct redirect_error_signature
188 {
189 typedef Signature type;
190 };
191
192 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
193
194 template <typename R, typename... Args>
195 struct redirect_error_signature<R(boost::system::error_code, Args...)>
196 {
197 typedef R type(Args...);
198 };
199
200 template <typename R, typename... Args>
201 struct redirect_error_signature<R(const boost::system::error_code&, Args...)>
202 {
203 typedef R type(Args...);
204 };
205
206 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
207
208 template <typename R>
209 struct redirect_error_signature<R(boost::system::error_code)>
210 {
211 typedef R type();
212 };
213
214 template <typename R>
215 struct redirect_error_signature<R(const boost::system::error_code&)>
216 {
217 typedef R type();
218 };
219
220 #define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \
221 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
222 struct redirect_error_signature< \
223 R(boost::system::error_code, BOOST_ASIO_VARIADIC_TARGS(n))> \
224 { \
225 typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)); \
226 }; \
227 \
228 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
229 struct redirect_error_signature< \
230 R(const boost::system::error_code&, BOOST_ASIO_VARIADIC_TARGS(n))> \
231 { \
232 typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)); \
233 }; \
234 /**/
235 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF)
236 #undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF
237
238 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
239
240 } // namespace detail
241
242 #if !defined(GENERATING_DOCUMENTATION)
243
244 template <typename CompletionToken, typename Signature>
245 struct async_result<redirect_error_t<CompletionToken>, Signature>
246 {
247 typedef typename async_result<CompletionToken,
248 typename detail::redirect_error_signature<Signature>::type>
249 ::return_type return_type;
250
251 template <typename Initiation>
252 struct init_wrapper
253 {
254 template <typename Init>
init_wrapperboost::asio::async_result::init_wrapper255 init_wrapper(boost::system::error_code& ec, BOOST_ASIO_MOVE_ARG(Init) init)
256 : ec_(ec),
257 initiation_(BOOST_ASIO_MOVE_CAST(Init)(init))
258 {
259 }
260
261 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
262
263 template <typename Handler, typename... Args>
operator ()boost::asio::async_result::init_wrapper264 void operator()(
265 BOOST_ASIO_MOVE_ARG(Handler) handler,
266 BOOST_ASIO_MOVE_ARG(Args)... args)
267 {
268 BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
269 detail::redirect_error_handler<
270 typename decay<Handler>::type>(
271 ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
272 BOOST_ASIO_MOVE_CAST(Args)(args)...);
273 }
274
275 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
276
277 template <typename Handler>
operator ()boost::asio::async_result::init_wrapper278 void operator()(
279 BOOST_ASIO_MOVE_ARG(Handler) handler)
280 {
281 BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
282 detail::redirect_error_handler<
283 typename decay<Handler>::type>(
284 ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
285 }
286
287 #define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
288 template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
289 void operator()( \
290 BOOST_ASIO_MOVE_ARG(Handler) handler, \
291 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
292 { \
293 BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \
294 detail::redirect_error_handler< \
295 typename decay<Handler>::type>( \
296 ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
297 BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
298 } \
299 /**/
300 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF)
301 #undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF
302
303 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
304
305 boost::system::error_code& ec_;
306 Initiation initiation_;
307 };
308
309 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
310
311 template <typename Initiation, typename RawCompletionToken, typename... Args>
initiateboost::asio::async_result312 static return_type initiate(
313 BOOST_ASIO_MOVE_ARG(Initiation) initiation,
314 BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
315 BOOST_ASIO_MOVE_ARG(Args)... args)
316 {
317 return async_initiate<CompletionToken,
318 typename detail::redirect_error_signature<Signature>::type>(
319 init_wrapper<typename decay<Initiation>::type>(
320 token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
321 token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
322 }
323
324 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
325
326 template <typename Initiation, typename RawCompletionToken>
initiateboost::asio::async_result327 static return_type initiate(
328 BOOST_ASIO_MOVE_ARG(Initiation) initiation,
329 BOOST_ASIO_MOVE_ARG(RawCompletionToken) token)
330 {
331 return async_initiate<CompletionToken,
332 typename detail::redirect_error_signature<Signature>::type>(
333 init_wrapper<typename decay<Initiation>::type>(
334 token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
335 token.token_);
336 }
337
338 #define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
339 template <typename Initiation, typename RawCompletionToken, \
340 BOOST_ASIO_VARIADIC_TPARAMS(n)> \
341 static return_type initiate( \
342 BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
343 BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \
344 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
345 { \
346 return async_initiate<CompletionToken, \
347 typename detail::redirect_error_signature<Signature>::type>( \
348 init_wrapper<typename decay<Initiation>::type>( \
349 token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \
350 token.token_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
351 } \
352 /**/
353 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
354 #undef BOOST_ASIO_PRIVATE_INITIATE_DEF
355
356 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
357 };
358
359 template <typename Handler, typename Executor>
360 struct associated_executor<detail::redirect_error_handler<Handler>, Executor>
361 {
362 typedef typename associated_executor<Handler, Executor>::type type;
363
getboost::asio::associated_executor364 static type get(
365 const detail::redirect_error_handler<Handler>& h,
366 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
367 {
368 return associated_executor<Handler, Executor>::get(h.handler_, ex);
369 }
370 };
371
372 template <typename Handler, typename Allocator>
373 struct associated_allocator<detail::redirect_error_handler<Handler>, Allocator>
374 {
375 typedef typename associated_allocator<Handler, Allocator>::type type;
376
getboost::asio::associated_allocator377 static type get(
378 const detail::redirect_error_handler<Handler>& h,
379 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
380 {
381 return associated_allocator<Handler, Allocator>::get(h.handler_, a);
382 }
383 };
384
385 #endif // !defined(GENERATING_DOCUMENTATION)
386
387 } // namespace asio
388 } // namespace boost
389
390 #include <boost/asio/detail/pop_options.hpp>
391
392 #endif // BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP
393