// // async_result.hpp // ~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2024 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_ASYNC_RESULT_HPP #define BOOST_ASIO_ASYNC_RESULT_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include namespace boost { namespace asio { namespace detail { template struct is_completion_signature : false_type { }; template struct is_completion_signature : true_type { }; template struct is_completion_signature : true_type { }; template struct is_completion_signature : true_type { }; # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct is_completion_signature : true_type { }; template struct is_completion_signature : true_type { }; template struct is_completion_signature : true_type { }; # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct are_completion_signatures : false_type { }; template <> struct are_completion_signatures<> : true_type { }; template struct are_completion_signatures : is_completion_signature { }; template struct are_completion_signatures : integral_constant::value && are_completion_signatures::value)> { }; } // namespace detail #if defined(BOOST_ASIO_HAS_CONCEPTS) namespace detail { template BOOST_ASIO_CONCEPT callable_with = requires(T&& t, Args&&... args) { static_cast(t)(static_cast(args)...); }; template struct is_completion_handler_for : false_type { }; template struct is_completion_handler_for : integral_constant, Args...>)> { }; template struct is_completion_handler_for : integral_constant&, Args...>)> { }; template struct is_completion_handler_for : integral_constant&&, Args...>)> { }; # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct is_completion_handler_for : integral_constant, Args...>)> { }; template struct is_completion_handler_for : integral_constant&, Args...>)> { }; template struct is_completion_handler_for : integral_constant&&, Args...>)> { }; # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct is_completion_handler_for : integral_constant::value && is_completion_handler_for::value)> { }; } // namespace detail template BOOST_ASIO_CONCEPT completion_signature = detail::is_completion_signature::value; #define BOOST_ASIO_COMPLETION_SIGNATURE \ ::boost::asio::completion_signature template BOOST_ASIO_CONCEPT completion_handler_for = detail::are_completion_signatures::value && detail::is_completion_handler_for::value; #define BOOST_ASIO_COMPLETION_HANDLER_FOR(sig) \ ::boost::asio::completion_handler_for #define BOOST_ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) \ ::boost::asio::completion_handler_for #define BOOST_ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) \ ::boost::asio::completion_handler_for #else // defined(BOOST_ASIO_HAS_CONCEPTS) #define BOOST_ASIO_COMPLETION_SIGNATURE typename #define BOOST_ASIO_COMPLETION_HANDLER_FOR(sig) typename #define BOOST_ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) typename #define BOOST_ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) typename #endif // defined(BOOST_ASIO_HAS_CONCEPTS) namespace detail { template struct is_lvalue_completion_signature : false_type { }; template struct is_lvalue_completion_signature : true_type { }; # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct is_lvalue_completion_signature : true_type { }; # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct are_any_lvalue_completion_signatures : false_type { }; template struct are_any_lvalue_completion_signatures : is_lvalue_completion_signature { }; template struct are_any_lvalue_completion_signatures : integral_constant::value || are_any_lvalue_completion_signatures::value)> { }; template struct is_rvalue_completion_signature : false_type { }; template struct is_rvalue_completion_signature : true_type { }; # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct is_rvalue_completion_signature : true_type { }; # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct are_any_rvalue_completion_signatures : false_type { }; template struct are_any_rvalue_completion_signatures : is_rvalue_completion_signature { }; template struct are_any_rvalue_completion_signatures : integral_constant::value || are_any_rvalue_completion_signatures::value)> { }; template struct simple_completion_signature; template struct simple_completion_signature { typedef R type(Args...); }; template struct simple_completion_signature { typedef R type(Args...); }; template struct simple_completion_signature { typedef R type(Args...); }; # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template struct simple_completion_signature { typedef R type(Args...); }; template struct simple_completion_signature { typedef R type(Args...); }; template struct simple_completion_signature { typedef R type(Args...); }; # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template class completion_handler_async_result { public: typedef CompletionToken completion_handler_type; typedef void return_type; explicit completion_handler_async_result(completion_handler_type&) { } return_type get() { } template static return_type initiate(Initiation&& initiation, RawCompletionToken&& token, Args&&... args) { static_cast(initiation)( static_cast(token), static_cast(args)...); } private: completion_handler_async_result( const completion_handler_async_result&) = delete; completion_handler_async_result& operator=( const completion_handler_async_result&) = delete; }; } // namespace detail #if defined(GENERATING_DOCUMENTATION) /// An interface for customising the behaviour of an initiating function. /** * The async_result traits class is used for determining: * * @li the concrete completion handler type to be called at the end of the * asynchronous operation; * * @li the initiating function return type; and * * @li how the return value of the initiating function is obtained. * * The trait allows the handler and return types to be determined at the point * where the specific completion handler signature is known. * * This template may be specialised for user-defined completion token types. * The primary template assumes that the CompletionToken is the completion * handler. */ template class async_result { public: /// The concrete completion handler type for the specific signature. typedef CompletionToken completion_handler_type; /// The return type of the initiating function. typedef void return_type; /// Construct an async result from a given handler. /** * When using a specalised async_result, the constructor has an opportunity * to initialise some state associated with the completion handler, which is * then returned from the initiating function. */ explicit async_result(completion_handler_type& h); /// Obtain the value to be returned from the initiating function. return_type get(); /// Initiate the asynchronous operation that will produce the result, and /// obtain the value to be returned from the initiating function. template static return_type initiate( Initiation&& initiation, RawCompletionToken&& token, Args&&... args); private: async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; }; #else // defined(GENERATING_DOCUMENTATION) template class async_result : public conditional_t< detail::are_any_lvalue_completion_signatures::value || !detail::are_any_rvalue_completion_signatures::value, detail::completion_handler_async_result, async_result::type...> > { public: typedef conditional_t< detail::are_any_lvalue_completion_signatures::value || !detail::are_any_rvalue_completion_signatures::value, detail::completion_handler_async_result, async_result::type...> > base_type; using base_type::base_type; private: async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; }; template class async_result { // Empty. }; #endif // defined(GENERATING_DOCUMENTATION) /// Helper template to deduce the handler type from a CompletionToken, capture /// a local copy of the handler, and then create an async_result for the /// handler. template struct async_completion { /// The real handler type to be used for the asynchronous operation. typedef typename boost::asio::async_result< decay_t, Signatures...>::completion_handler_type completion_handler_type; /// Constructor. /** * The constructor creates the concrete completion handler and makes the link * between the handler and the asynchronous result. */ explicit async_completion(CompletionToken& token) : completion_handler(static_cast::value, completion_handler_type&, CompletionToken&&>>(token)), result(completion_handler) { } /// A copy of, or reference to, a real handler object. conditional_t< is_same::value, completion_handler_type&, completion_handler_type> completion_handler; /// The result of the asynchronous operation's initiating function. async_result, Signatures...> result; }; namespace detail { struct async_result_memfns_base { void initiate(); }; template struct async_result_memfns_derived : T, async_result_memfns_base { }; template struct async_result_memfns_check { }; template char (&async_result_initiate_memfn_helper(...))[2]; template char async_result_initiate_memfn_helper( async_result_memfns_check< void (async_result_memfns_base::*)(), &async_result_memfns_derived::initiate>*); template struct async_result_has_initiate_memfn : integral_constant, Signatures...> >(0)) != 1> { }; } // namespace detail #if defined(GENERATING_DOCUMENTATION) # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \ void_or_deduced # define BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \ void_or_deduced # define BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \ void_or_deduced #else # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \ typename ::boost::asio::async_result< \ typename ::boost::asio::decay::type, sig>::return_type # define BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \ typename ::boost::asio::async_result< \ typename ::boost::asio::decay::type, sig0, sig1>::return_type # define BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \ typename ::boost::asio::async_result< \ typename ::boost::asio::decay::type, sig0, sig1, sig2>::return_type #define BOOST_ASIO_HANDLER_TYPE(ct, sig) \ typename ::boost::asio::async_result< \ typename ::boost::asio::decay::type, sig>::completion_handler_type #define BOOST_ASIO_HANDLER_TYPE2(ct, sig0, sig1) \ typename ::boost::asio::async_result< \ typename ::boost::asio::decay::type, \ sig0, sig1>::completion_handler_type #define BOOST_ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \ typename ::boost::asio::async_result< \ typename ::boost::asio::decay::type, \ sig0, sig1, sig2>::completion_handler_type #endif #if defined(GENERATING_DOCUMENTATION) # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \ auto #elif defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION) # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \ auto #else # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \ BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \ BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \ BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) #endif #if defined(GENERATING_DOCUMENTATION) # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) #elif defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION) # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) #else # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ auto # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) -> decltype expr #endif #if defined(GENERATING_DOCUMENTATION) # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \ void_or_deduced # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \ void_or_deduced # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \ void_or_deduced #else # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \ decltype expr # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \ decltype expr # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \ decltype expr #endif #if defined(GENERATING_DOCUMENTATION) template void_or_deduced async_initiate( Initiation&& initiation, type_identity_t& token, Args&&... args); #else // defined(GENERATING_DOCUMENTATION) template inline auto async_initiate(Initiation&& initiation, type_identity_t& token, Args&&... args) -> decltype(enable_if_t< enable_if_t< detail::are_completion_signatures::value, detail::async_result_has_initiate_memfn< CompletionToken, Signatures...>>::value, async_result, Signatures...>>::initiate( static_cast(initiation), static_cast(token), static_cast(args)...)) { return async_result, Signatures...>::initiate( static_cast(initiation), static_cast(token), static_cast(args)...); } template < BOOST_ASIO_COMPLETION_SIGNATURE... Signatures, typename CompletionToken, typename Initiation, typename... Args> inline auto async_initiate(Initiation&& initiation, CompletionToken&& token, Args&&... args) -> decltype(enable_if_t< enable_if_t< detail::are_completion_signatures::value, detail::async_result_has_initiate_memfn< CompletionToken, Signatures...>>::value, async_result, Signatures...>>::initiate( static_cast(initiation), static_cast(token), static_cast(args)...)) { return async_result, Signatures...>::initiate( static_cast(initiation), static_cast(token), static_cast(args)...); } template inline typename enable_if_t< !enable_if_t< detail::are_completion_signatures::value, detail::async_result_has_initiate_memfn< CompletionToken, Signatures...>>::value, async_result, Signatures...> >::return_type async_initiate(Initiation&& initiation, type_identity_t& token, Args&&... args) { async_completion completion(token); static_cast(initiation)( static_cast< typename async_result, Signatures...>::completion_handler_type&&>( completion.completion_handler), static_cast(args)...); return completion.result.get(); } template inline typename enable_if_t< !enable_if_t< detail::are_completion_signatures::value, detail::async_result_has_initiate_memfn< CompletionToken, Signatures...>>::value, async_result, Signatures...> >::return_type async_initiate(Initiation&& initiation, CompletionToken&& token, Args&&... args) { async_completion completion(token); static_cast(initiation)( static_cast< typename async_result, Signatures...>::completion_handler_type&&>( completion.completion_handler), static_cast(args)...); return completion.result.get(); } #endif // defined(GENERATING_DOCUMENTATION) #if defined(BOOST_ASIO_HAS_CONCEPTS) namespace detail { template struct initiation_archetype { template CompletionHandler> void operator()(CompletionHandler&&) const { } }; } // namespace detail template BOOST_ASIO_CONCEPT completion_token_for = detail::are_completion_signatures::value && requires(T&& t) { async_initiate( detail::initiation_archetype{}, t); }; #define BOOST_ASIO_COMPLETION_TOKEN_FOR(sig) \ ::boost::asio::completion_token_for #define BOOST_ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) \ ::boost::asio::completion_token_for #define BOOST_ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) \ ::boost::asio::completion_token_for #else // defined(BOOST_ASIO_HAS_CONCEPTS) #define BOOST_ASIO_COMPLETION_TOKEN_FOR(sig) typename #define BOOST_ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) typename #define BOOST_ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) typename #endif // defined(BOOST_ASIO_HAS_CONCEPTS) namespace detail { struct async_operation_probe {}; struct async_operation_probe_result {}; template struct is_async_operation_call : false_type { }; template struct is_async_operation_call, async_operation_probe_result >::value > > > : true_type { }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) template class async_result { public: typedef detail::async_operation_probe_result return_type; template static return_type initiate(Initiation&&, detail::async_operation_probe, InitArgs&&...) { return return_type(); } }; #endif // !defined(GENERATING_DOCUMENTATION) #if defined(GENERATING_DOCUMENTATION) /// The is_async_operation trait detects whether a type @c T and arguments /// @c Args... may be used to initiate an asynchronous operation. /** * Class template @c is_async_operation is a trait is derived from @c true_type * if the expression T(Args..., token) initiates an asynchronous * operation, where @c token is an unspecified completion token type. Otherwise, * @c is_async_operation is derived from @c false_type. */ template struct is_async_operation : integral_constant { }; #else // defined(GENERATING_DOCUMENTATION) template struct is_async_operation : detail::is_async_operation_call< T(Args..., detail::async_operation_probe)> { }; #endif // defined(GENERATING_DOCUMENTATION) #if defined(BOOST_ASIO_HAS_CONCEPTS) template BOOST_ASIO_CONCEPT async_operation = is_async_operation::value; #define BOOST_ASIO_ASYNC_OPERATION(t) \ ::boost::asio::async_operation #define BOOST_ASIO_ASYNC_OPERATION1(t, a0) \ ::boost::asio::async_operation #define BOOST_ASIO_ASYNC_OPERATION2(t, a0, a1) \ ::boost::asio::async_operation #define BOOST_ASIO_ASYNC_OPERATION3(t, a0, a1, a2) \ ::boost::asio::async_operation #else // defined(BOOST_ASIO_HAS_CONCEPTS) #define BOOST_ASIO_ASYNC_OPERATION(t) typename #define BOOST_ASIO_ASYNC_OPERATION1(t, a0) typename #define BOOST_ASIO_ASYNC_OPERATION2(t, a0, a1) typename #define BOOST_ASIO_ASYNC_OPERATION3(t, a0, a1, a2) typename #endif // defined(BOOST_ASIO_HAS_CONCEPTS) namespace detail { struct completion_signature_probe {}; template struct completion_signature_probe_result { template