// impl/redirect_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP #define BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace asio { namespace detail { // Class to adapt a redirect_error_t as a completion handler. template class redirect_error_handler { public: typedef void result_type; template redirect_error_handler(redirect_error_t e) : ec_(e.ec_), handler_(BOOST_ASIO_MOVE_CAST(CompletionToken)(e.token_)) { } template redirect_error_handler(boost::system::error_code& ec, BOOST_ASIO_MOVE_ARG(RedirectedHandler) h) : ec_(ec), handler_(BOOST_ASIO_MOVE_CAST(RedirectedHandler)(h)) { } void operator()() { handler_(); } #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template typename enable_if< !is_same::type, boost::system::error_code>::value >::type operator()(BOOST_ASIO_MOVE_ARG(Arg) arg, BOOST_ASIO_MOVE_ARG(Args)... args) { handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg), BOOST_ASIO_MOVE_CAST(Args)(args)...); } template void operator()(const boost::system::error_code& ec, BOOST_ASIO_MOVE_ARG(Args)... args) { ec_ = ec; handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...); } #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template typename enable_if< !is_same::type, boost::system::error_code>::value >::type operator()(BOOST_ASIO_MOVE_ARG(Arg) arg) { handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg)); } void operator()(const boost::system::error_code& ec) { ec_ = ec; handler_(); } #define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \ template \ typename enable_if< \ !is_same::type, boost::system::error_code>::value \ >::type \ operator()(BOOST_ASIO_MOVE_ARG(Arg) arg, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ { \ handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg), \ BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ } \ \ template \ void operator()(const boost::system::error_code& ec, \ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ { \ ec_ = ec; \ handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ } \ /**/ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF) #undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) //private: boost::system::error_code& ec_; Handler handler_; }; template inline void* asio_handler_allocate(std::size_t size, redirect_error_handler* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } template inline void asio_handler_deallocate(void* pointer, std::size_t size, redirect_error_handler* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } template inline bool asio_handler_is_continuation( redirect_error_handler* this_handler) { return boost_asio_handler_cont_helpers::is_continuation( this_handler->handler_); } template inline void asio_handler_invoke(Function& function, redirect_error_handler* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } template inline void asio_handler_invoke(const Function& function, redirect_error_handler* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } template struct redirect_error_signature { typedef Signature type; }; #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template struct redirect_error_signature { typedef R type(Args...); }; template struct redirect_error_signature { typedef R type(Args...); }; #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template struct redirect_error_signature { typedef R type(); }; template struct redirect_error_signature { typedef R type(); }; #define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \ template \ struct redirect_error_signature< \ R(boost::system::error_code, BOOST_ASIO_VARIADIC_TARGS(n))> \ { \ typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)); \ }; \ \ template \ struct redirect_error_signature< \ R(const boost::system::error_code&, BOOST_ASIO_VARIADIC_TARGS(n))> \ { \ typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)); \ }; \ /**/ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF) #undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) } // namespace detail #if !defined(GENERATING_DOCUMENTATION) template struct async_result, Signature> { typedef typename async_result::type> ::return_type return_type; template struct init_wrapper { template init_wrapper(boost::system::error_code& ec, BOOST_ASIO_MOVE_ARG(Init) init) : ec_(ec), initiation_(BOOST_ASIO_MOVE_CAST(Init)(init)) { } #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template void operator()( BOOST_ASIO_MOVE_ARG(Handler) handler, BOOST_ASIO_MOVE_ARG(Args)... args) { BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( detail::redirect_error_handler< typename decay::type>( ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), BOOST_ASIO_MOVE_CAST(Args)(args)...); } #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template void operator()( BOOST_ASIO_MOVE_ARG(Handler) handler) { BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( detail::redirect_error_handler< typename decay::type>( ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler))); } #define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \ template \ void operator()( \ BOOST_ASIO_MOVE_ARG(Handler) handler, \ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ { \ BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \ detail::redirect_error_handler< \ typename decay::type>( \ ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \ BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ } \ /**/ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF) #undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) boost::system::error_code& ec_; Initiation initiation_; }; #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template static return_type initiate( BOOST_ASIO_MOVE_ARG(Initiation) initiation, BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, BOOST_ASIO_MOVE_ARG(Args)... args) { return async_initiate::type>( init_wrapper::type>( token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...); } #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template static return_type initiate( BOOST_ASIO_MOVE_ARG(Initiation) initiation, BOOST_ASIO_MOVE_ARG(RawCompletionToken) token) { return async_initiate::type>( init_wrapper::type>( token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), token.token_); } #define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \ template \ static return_type initiate( \ BOOST_ASIO_MOVE_ARG(Initiation) initiation, \ BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ { \ return async_initiate::type>( \ init_wrapper::type>( \ token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \ token.token_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ } \ /**/ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF) #undef BOOST_ASIO_PRIVATE_INITIATE_DEF #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) }; template struct associated_executor, Executor> { typedef typename associated_executor::type type; static type get( const detail::redirect_error_handler& h, const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT { return associated_executor::get(h.handler_, ex); } }; template struct associated_allocator, Allocator> { typedef typename associated_allocator::type type; static type get( const detail::redirect_error_handler& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator::get(h.handler_, a); } }; #endif // !defined(GENERATING_DOCUMENTATION) } // namespace asio } // namespace boost #include #endif // BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP