• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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