803 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			803 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //
 | ||
|  | // deferred.hpp
 | ||
|  | // ~~~~~~~~~~~~
 | ||
|  | //
 | ||
|  | // Copyright (c) 2003-2023 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 ASIO_DEFERRED_HPP
 | ||
|  | #define ASIO_DEFERRED_HPP
 | ||
|  | 
 | ||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 | ||
|  | # pragma once
 | ||
|  | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 | ||
|  | 
 | ||
|  | #include "asio/detail/config.hpp"
 | ||
|  | 
 | ||
|  | #if (defined(ASIO_HAS_STD_TUPLE) \
 | ||
|  |     && defined(ASIO_HAS_DECLTYPE) \ | ||
|  |     && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \ | ||
|  |   || defined(GENERATING_DOCUMENTATION) | ||
|  | 
 | ||
|  | #include <tuple>
 | ||
|  | #include "asio/associator.hpp"
 | ||
|  | #include "asio/async_result.hpp"
 | ||
|  | #include "asio/detail/type_traits.hpp"
 | ||
|  | #include "asio/detail/utility.hpp"
 | ||
|  | 
 | ||
|  | #include "asio/detail/push_options.hpp"
 | ||
|  | 
 | ||
|  | namespace asio { | ||
|  | 
 | ||
|  | /// Trait for detecting objects that are usable as deferred operations.
 | ||
|  | template <typename T> | ||
|  | struct is_deferred : false_type | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | /// Helper type to wrap multiple completion signatures.
 | ||
|  | template <typename... Signatures> | ||
|  | struct deferred_signatures | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | namespace detail { | ||
|  | 
 | ||
|  | // Helper trait for getting the completion signatures of the tail in a sequence
 | ||
|  | // when invoked with the specified arguments.
 | ||
|  | 
 | ||
|  | template <typename Tail, typename... Signatures> | ||
|  | struct deferred_sequence_signatures; | ||
|  | 
 | ||
|  | template <typename Tail, typename R, typename... Args, typename... Signatures> | ||
|  | struct deferred_sequence_signatures<Tail, R(Args...), Signatures...> | ||
|  |   : completion_signature_of<decltype(declval<Tail>()(declval<Args>()...))> | ||
|  | { | ||
|  |   static_assert( | ||
|  |       !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value, | ||
|  |       "deferred functions must produce a deferred return type"); | ||
|  | }; | ||
|  | 
 | ||
|  | // Completion handler for the head component of a deferred sequence.
 | ||
|  | template <typename Handler, typename Tail> | ||
|  | class deferred_sequence_handler | ||
|  | { | ||
|  | public: | ||
|  |   template <typename H, typename T> | ||
|  |   explicit deferred_sequence_handler( | ||
|  |       ASIO_MOVE_ARG(H) handler, ASIO_MOVE_ARG(T) tail) | ||
|  |     : handler_(ASIO_MOVE_CAST(H)(handler)), | ||
|  |       tail_(ASIO_MOVE_CAST(T)(tail)) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   template <typename... Args> | ||
|  |   void operator()(ASIO_MOVE_ARG(Args)... args) | ||
|  |   { | ||
|  |     ASIO_MOVE_OR_LVALUE(Tail)(tail_)( | ||
|  |         ASIO_MOVE_CAST(Args)(args)...)( | ||
|  |           ASIO_MOVE_OR_LVALUE(Handler)(handler_)); | ||
|  |   } | ||
|  | 
 | ||
|  | //private:
 | ||
|  |   Handler handler_; | ||
|  |   Tail tail_; | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename Head, typename Tail, typename... Signatures> | ||
|  | class deferred_sequence_base | ||
|  | { | ||
|  | private: | ||
|  |   struct initiate | ||
|  |   { | ||
|  |     template <typename Handler> | ||
|  |     void operator()(ASIO_MOVE_ARG(Handler) handler, | ||
|  |         Head head, ASIO_MOVE_ARG(Tail) tail) | ||
|  |     { | ||
|  |       ASIO_MOVE_OR_LVALUE(Head)(head)( | ||
|  |           deferred_sequence_handler< | ||
|  |             typename decay<Handler>::type, | ||
|  |             typename decay<Tail>::type>( | ||
|  |               ASIO_MOVE_CAST(Handler)(handler), | ||
|  |               ASIO_MOVE_CAST(Tail)(tail))); | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   Head head_; | ||
|  |   Tail tail_; | ||
|  | 
 | ||
|  | public: | ||
|  |   template <typename H, typename T> | ||
|  |   ASIO_CONSTEXPR explicit deferred_sequence_base( | ||
|  |       ASIO_MOVE_ARG(H) head, ASIO_MOVE_ARG(T) tail) | ||
|  |     : head_(ASIO_MOVE_CAST(H)(head)), | ||
|  |       tail_(ASIO_MOVE_CAST(T)(tail)) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL | ||
|  |     -> decltype( | ||
|  |         asio::async_initiate<CompletionToken, Signatures...>( | ||
|  |           declval<initiate>(), token, | ||
|  |           ASIO_MOVE_OR_LVALUE(Head)(this->head_), | ||
|  |           ASIO_MOVE_OR_LVALUE(Tail)(this->tail_))) | ||
|  |   { | ||
|  |     return asio::async_initiate<CompletionToken, Signatures...>( | ||
|  |         initiate(), token, | ||
|  |         ASIO_MOVE_OR_LVALUE(Head)(head_), | ||
|  |         ASIO_MOVE_OR_LVALUE(Tail)(tail_)); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token) const & | ||
|  |     -> decltype( | ||
|  |         asio::async_initiate<CompletionToken, Signatures...>( | ||
|  |           initiate(), token, this->head_, this->tail_)) | ||
|  |   { | ||
|  |     return asio::async_initiate<CompletionToken, Signatures...>( | ||
|  |         initiate(), token, head_, tail_); | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | }; | ||
|  | 
 | ||
|  | // Two-step application of variadic Signatures to determine correct base type.
 | ||
|  | 
 | ||
|  | template <typename Head, typename Tail> | ||
|  | struct deferred_sequence_types | ||
|  | { | ||
|  |   template <typename... Signatures> | ||
|  |   struct op1 | ||
|  |   { | ||
|  |     typedef deferred_sequence_base<Head, Tail, Signatures...> type; | ||
|  |   }; | ||
|  | 
 | ||
|  |   template <typename... Signatures> | ||
|  |   struct op2 | ||
|  |   { | ||
|  |     typedef typename deferred_sequence_signatures<Tail, Signatures...>::template | ||
|  |       apply<op1>::type::type type; | ||
|  |   }; | ||
|  | 
 | ||
|  |   typedef typename completion_signature_of<Head>::template | ||
|  |     apply<op2>::type::type base; | ||
|  | }; | ||
|  | 
 | ||
|  | } // namespace detail
 | ||
|  | 
 | ||
|  | /// Used to represent an empty deferred action.
 | ||
|  | struct deferred_noop | ||
|  | { | ||
|  |   /// No effect.
 | ||
|  |   template <typename... Args> | ||
|  |   void operator()(ASIO_MOVE_ARG(Args)...) ASIO_RVALUE_REF_QUAL | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   /// No effect.
 | ||
|  |   template <typename... Args> | ||
|  |   void operator()(ASIO_MOVE_ARG(Args)...) const & | ||
|  |   { | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | }; | ||
|  | 
 | ||
|  | #if !defined(GENERATING_DOCUMENTATION)
 | ||
|  | template <> | ||
|  | struct is_deferred<deferred_noop> : true_type | ||
|  | { | ||
|  | }; | ||
|  | #endif // !defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | /// Tag type to disambiguate deferred constructors.
 | ||
|  | struct deferred_init_tag {}; | ||
|  | 
 | ||
|  | /// Wraps a function object so that it may be used as an element in a deferred
 | ||
|  | /// composition.
 | ||
|  | template <typename Function> | ||
|  | class deferred_function | ||
|  | { | ||
|  | public: | ||
|  |   /// Constructor. 
 | ||
|  |   template <typename F> | ||
|  |   ASIO_CONSTEXPR explicit deferred_function( | ||
|  |       deferred_init_tag, ASIO_MOVE_ARG(F) function) | ||
|  |     : function_(ASIO_MOVE_CAST(F)(function)) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  | //private:
 | ||
|  |   Function function_; | ||
|  | 
 | ||
|  | public: | ||
|  |   template <typename... Args> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL | ||
|  |     -> decltype( | ||
|  |         ASIO_MOVE_CAST(Function)(this->function_)( | ||
|  |           ASIO_MOVE_CAST(Args)(args)...)) | ||
|  |   { | ||
|  |     return ASIO_MOVE_CAST(Function)(function_)( | ||
|  |         ASIO_MOVE_CAST(Args)(args)...); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <typename... Args> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(Args)... args) const & | ||
|  |     -> decltype(Function(function_)(ASIO_MOVE_CAST(Args)(args)...)) | ||
|  |   { | ||
|  |     return Function(function_)(ASIO_MOVE_CAST(Args)(args)...); | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | }; | ||
|  | 
 | ||
|  | #if !defined(GENERATING_DOCUMENTATION)
 | ||
|  | template <typename Function> | ||
|  | struct is_deferred<deferred_function<Function> > : true_type | ||
|  | { | ||
|  | }; | ||
|  | #endif // !defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | /// Encapsulates deferred values.
 | ||
|  | template <typename... Values> | ||
|  | class ASIO_NODISCARD deferred_values | ||
|  | { | ||
|  | private: | ||
|  |   std::tuple<Values...> values_; | ||
|  | 
 | ||
|  |   struct initiate | ||
|  |   { | ||
|  |     template <typename Handler, typename... V> | ||
|  |     void operator()(Handler handler, ASIO_MOVE_ARG(V)... values) | ||
|  |     { | ||
|  |       ASIO_MOVE_OR_LVALUE(Handler)(handler)( | ||
|  |           ASIO_MOVE_CAST(V)(values)...); | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   template <typename CompletionToken, std::size_t... I> | ||
|  |   auto invoke_helper( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token, | ||
|  |       detail::index_sequence<I...>) | ||
|  |     -> decltype( | ||
|  |         asio::async_initiate<CompletionToken, void(Values...)>( | ||
|  |           initiate(), token, | ||
|  |           std::get<I>( | ||
|  |             ASIO_MOVE_CAST(std::tuple<Values...>)(this->values_))...)) | ||
|  |   { | ||
|  |     return asio::async_initiate<CompletionToken, void(Values...)>( | ||
|  |         initiate(), token, | ||
|  |         std::get<I>(ASIO_MOVE_CAST(std::tuple<Values...>)(values_))...); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <typename CompletionToken, std::size_t... I> | ||
|  |   auto const_invoke_helper( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token, | ||
|  |       detail::index_sequence<I...>) | ||
|  |     -> decltype( | ||
|  |         asio::async_initiate<CompletionToken, void(Values...)>( | ||
|  |           initiate(), token, std::get<I>(values_)...)) | ||
|  |   { | ||
|  |     return asio::async_initiate<CompletionToken, void(Values...)>( | ||
|  |         initiate(), token, std::get<I>(values_)...); | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | 
 | ||
|  | public: | ||
|  |   /// Construct a deferred asynchronous operation from the arguments to an
 | ||
|  |   /// initiation function object.
 | ||
|  |   template <typename... V> | ||
|  |   ASIO_CONSTEXPR explicit deferred_values( | ||
|  |       deferred_init_tag, ASIO_MOVE_ARG(V)... values) | ||
|  |     : values_(ASIO_MOVE_CAST(V)(values)...) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Initiate the deferred operation using the supplied completion token.
 | ||
|  |   template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL | ||
|  |     -> decltype( | ||
|  |         this->invoke_helper( | ||
|  |           ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |           detail::index_sequence_for<Values...>())) | ||
|  |   { | ||
|  |     return this->invoke_helper( | ||
|  |         ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |         detail::index_sequence_for<Values...>()); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token) const & | ||
|  |     -> decltype( | ||
|  |         this->const_invoke_helper( | ||
|  |           ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |           detail::index_sequence_for<Values...>())) | ||
|  |   { | ||
|  |     return this->const_invoke_helper( | ||
|  |         ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |         detail::index_sequence_for<Values...>()); | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | }; | ||
|  | 
 | ||
|  | #if !defined(GENERATING_DOCUMENTATION)
 | ||
|  | template <typename... Values> | ||
|  | struct is_deferred<deferred_values<Values...> > : true_type | ||
|  | { | ||
|  | }; | ||
|  | #endif // !defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | /// Encapsulates a deferred asynchronous operation.
 | ||
|  | template <typename Signature, typename Initiation, typename... InitArgs> | ||
|  | class ASIO_NODISCARD deferred_async_operation | ||
|  | { | ||
|  | private: | ||
|  |   typedef typename decay<Initiation>::type initiation_t; | ||
|  |   initiation_t initiation_; | ||
|  |   typedef std::tuple<typename decay<InitArgs>::type...> init_args_t; | ||
|  |   init_args_t init_args_; | ||
|  | 
 | ||
|  |   template <typename CompletionToken, std::size_t... I> | ||
|  |   auto invoke_helper( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token, | ||
|  |       detail::index_sequence<I...>) | ||
|  |     -> decltype( | ||
|  |         asio::async_initiate<CompletionToken, Signature>( | ||
|  |           ASIO_MOVE_CAST(initiation_t)(initiation_), token, | ||
|  |           std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...)) | ||
|  |   { | ||
|  |     return asio::async_initiate<CompletionToken, Signature>( | ||
|  |         ASIO_MOVE_CAST(initiation_t)(initiation_), token, | ||
|  |         std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <typename CompletionToken, std::size_t... I> | ||
|  |   auto const_invoke_helper( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token, | ||
|  |       detail::index_sequence<I...>) const & | ||
|  |     -> decltype( | ||
|  |         asio::async_initiate<CompletionToken, Signature>( | ||
|  |           initiation_t(initiation_), token, std::get<I>(init_args_)...)) | ||
|  |     { | ||
|  |     return asio::async_initiate<CompletionToken, Signature>( | ||
|  |         initiation_t(initiation_), token, std::get<I>(init_args_)...); | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | 
 | ||
|  | public: | ||
|  |   /// Construct a deferred asynchronous operation from the arguments to an
 | ||
|  |   /// initiation function object.
 | ||
|  |   template <typename I, typename... A> | ||
|  |   ASIO_CONSTEXPR explicit deferred_async_operation( | ||
|  |       deferred_init_tag, ASIO_MOVE_ARG(I) initiation, | ||
|  |       ASIO_MOVE_ARG(A)... init_args) | ||
|  |     : initiation_(ASIO_MOVE_CAST(I)(initiation)), | ||
|  |       init_args_(ASIO_MOVE_CAST(A)(init_args)...) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Initiate the asynchronous operation using the supplied completion token.
 | ||
|  |   template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL | ||
|  |     -> decltype( | ||
|  |         this->invoke_helper( | ||
|  |           ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |           detail::index_sequence_for<InitArgs...>())) | ||
|  |   { | ||
|  |     return this->invoke_helper( | ||
|  |         ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |         detail::index_sequence_for<InitArgs...>()); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token) const & | ||
|  |     -> decltype( | ||
|  |         this->const_invoke_helper( | ||
|  |           ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |           detail::index_sequence_for<InitArgs...>())) | ||
|  |   { | ||
|  |     return this->const_invoke_helper( | ||
|  |         ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |         detail::index_sequence_for<InitArgs...>()); | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | }; | ||
|  | 
 | ||
|  | /// Encapsulates a deferred asynchronous operation thas has multiple completion
 | ||
|  | /// signatures.
 | ||
|  | template <typename... Signatures, typename Initiation, typename... InitArgs> | ||
|  | class ASIO_NODISCARD deferred_async_operation< | ||
|  |     deferred_signatures<Signatures...>, Initiation, InitArgs...> | ||
|  | { | ||
|  | private: | ||
|  |   typedef typename decay<Initiation>::type initiation_t; | ||
|  |   initiation_t initiation_; | ||
|  |   typedef std::tuple<typename decay<InitArgs>::type...> init_args_t; | ||
|  |   init_args_t init_args_; | ||
|  | 
 | ||
|  |   template <typename CompletionToken, std::size_t... I> | ||
|  |   auto invoke_helper( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token, | ||
|  |       detail::index_sequence<I...>) | ||
|  |     -> decltype( | ||
|  |         asio::async_initiate<CompletionToken, Signatures...>( | ||
|  |           ASIO_MOVE_CAST(initiation_t)(initiation_), token, | ||
|  |           std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...)) | ||
|  |   { | ||
|  |     return asio::async_initiate<CompletionToken, Signatures...>( | ||
|  |         ASIO_MOVE_CAST(initiation_t)(initiation_), token, | ||
|  |         std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <typename CompletionToken, std::size_t... I> | ||
|  |   auto const_invoke_helper( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token, | ||
|  |       detail::index_sequence<I...>) const & | ||
|  |     -> decltype( | ||
|  |         asio::async_initiate<CompletionToken, Signatures...>( | ||
|  |           initiation_t(initiation_), token, std::get<I>(init_args_)...)) | ||
|  |     { | ||
|  |     return asio::async_initiate<CompletionToken, Signatures...>( | ||
|  |         initiation_t(initiation_), token, std::get<I>(init_args_)...); | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | 
 | ||
|  | public: | ||
|  |   /// Construct a deferred asynchronous operation from the arguments to an
 | ||
|  |   /// initiation function object.
 | ||
|  |   template <typename I, typename... A> | ||
|  |   ASIO_CONSTEXPR explicit deferred_async_operation( | ||
|  |       deferred_init_tag, ASIO_MOVE_ARG(I) initiation, | ||
|  |       ASIO_MOVE_ARG(A)... init_args) | ||
|  |     : initiation_(ASIO_MOVE_CAST(I)(initiation)), | ||
|  |       init_args_(ASIO_MOVE_CAST(A)(init_args)...) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Initiate the asynchronous operation using the supplied completion token.
 | ||
|  |   template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL | ||
|  |     -> decltype( | ||
|  |         this->invoke_helper( | ||
|  |           ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |           detail::index_sequence_for<InitArgs...>())) | ||
|  |   { | ||
|  |     return this->invoke_helper( | ||
|  |         ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |         detail::index_sequence_for<InitArgs...>()); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken> | ||
|  |   auto operator()( | ||
|  |       ASIO_MOVE_ARG(CompletionToken) token) const & | ||
|  |     -> decltype( | ||
|  |         this->const_invoke_helper( | ||
|  |           ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |           detail::index_sequence_for<InitArgs...>())) | ||
|  |   { | ||
|  |     return this->const_invoke_helper( | ||
|  |         ASIO_MOVE_CAST(CompletionToken)(token), | ||
|  |         detail::index_sequence_for<InitArgs...>()); | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | }; | ||
|  | 
 | ||
|  | #if !defined(GENERATING_DOCUMENTATION)
 | ||
|  | template <typename Signature, typename Initiation, typename... InitArgs> | ||
|  | struct is_deferred< | ||
|  |     deferred_async_operation<Signature, Initiation, InitArgs...> > : true_type | ||
|  | { | ||
|  | }; | ||
|  | #endif // !defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | /// Defines a link between two consecutive operations in a sequence.
 | ||
|  | template <typename Head, typename Tail> | ||
|  | class ASIO_NODISCARD deferred_sequence : | ||
|  |   public detail::deferred_sequence_types<Head, Tail>::base | ||
|  | { | ||
|  | public: | ||
|  |   template <typename H, typename T> | ||
|  |   ASIO_CONSTEXPR explicit deferred_sequence(deferred_init_tag, | ||
|  |       ASIO_MOVE_ARG(H) head, ASIO_MOVE_ARG(T) tail) | ||
|  |     : detail::deferred_sequence_types<Head, Tail>::base( | ||
|  |         ASIO_MOVE_CAST(H)(head), ASIO_MOVE_CAST(T)(tail)) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(GENERATING_DOCUMENTATION)
 | ||
|  |   template <typename CompletionToken> | ||
|  |   auto operator()(ASIO_MOVE_ARG(CompletionToken) token) | ||
|  |     ASIO_RVALUE_REF_QUAL; | ||
|  | 
 | ||
|  |   template <typename CompletionToken> | ||
|  |   auto operator()(ASIO_MOVE_ARG(CompletionToken) token) const &; | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | }; | ||
|  | 
 | ||
|  | #if !defined(GENERATING_DOCUMENTATION)
 | ||
|  | template <typename Head, typename Tail> | ||
|  | struct is_deferred<deferred_sequence<Head, Tail> > : true_type | ||
|  | { | ||
|  | }; | ||
|  | #endif // !defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | /// Used to represent a deferred conditional branch.
 | ||
|  | template <typename OnTrue = deferred_noop, | ||
|  |     typename OnFalse = deferred_noop> | ||
|  | class ASIO_NODISCARD deferred_conditional | ||
|  | { | ||
|  | private: | ||
|  |   template <typename T, typename F> friend class deferred_conditional; | ||
|  | 
 | ||
|  |   // Helper constructor.
 | ||
|  |   template <typename T, typename F> | ||
|  |   explicit deferred_conditional(bool b, ASIO_MOVE_ARG(T) on_true, | ||
|  |       ASIO_MOVE_ARG(F) on_false) | ||
|  |     : on_true_(ASIO_MOVE_CAST(T)(on_true)), | ||
|  |       on_false_(ASIO_MOVE_CAST(F)(on_false)), | ||
|  |       bool_(b) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   OnTrue on_true_; | ||
|  |   OnFalse on_false_; | ||
|  |   bool bool_; | ||
|  | 
 | ||
|  | public: | ||
|  |   /// Construct a deferred conditional with the value to determine which branch
 | ||
|  |   /// will be executed.
 | ||
|  |   ASIO_CONSTEXPR explicit deferred_conditional(bool b) | ||
|  |     : on_true_(), | ||
|  |       on_false_(), | ||
|  |       bool_(b) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Invoke the conditional branch bsaed on the stored alue.
 | ||
|  |   template <typename... Args> | ||
|  |   auto operator()(ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL | ||
|  |     -> decltype( | ||
|  |         ASIO_MOVE_OR_LVALUE(OnTrue)(on_true_)( | ||
|  |           ASIO_MOVE_CAST(Args)(args)...)) | ||
|  |   { | ||
|  |     if (bool_) | ||
|  |     { | ||
|  |       return ASIO_MOVE_OR_LVALUE(OnTrue)(on_true_)( | ||
|  |           ASIO_MOVE_CAST(Args)(args)...); | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       return ASIO_MOVE_OR_LVALUE(OnFalse)(on_false_)( | ||
|  |           ASIO_MOVE_CAST(Args)(args)...); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  |   template <typename... Args> | ||
|  |   auto operator()(ASIO_MOVE_ARG(Args)... args) const & | ||
|  |     -> decltype(on_true_(ASIO_MOVE_CAST(Args)(args)...)) | ||
|  |   { | ||
|  |     if (bool_) | ||
|  |     { | ||
|  |       return on_true_(ASIO_MOVE_CAST(Args)(args)...); | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       return on_false_(ASIO_MOVE_CAST(Args)(args)...); | ||
|  |     } | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
 | ||
|  | 
 | ||
|  |   /// Set the true branch of the conditional.
 | ||
|  |   template <typename T> | ||
|  |   deferred_conditional<T, OnFalse> then(T on_true, | ||
|  |       typename constraint< | ||
|  |         is_deferred<T>::value | ||
|  |       >::type* = 0, | ||
|  |       typename constraint< | ||
|  |         is_same< | ||
|  |           typename conditional<true, OnTrue, T>::type, | ||
|  |           deferred_noop | ||
|  |         >::value | ||
|  |       >::type* = 0) ASIO_RVALUE_REF_QUAL | ||
|  |   { | ||
|  |     return deferred_conditional<T, OnFalse>( | ||
|  |         bool_, ASIO_MOVE_CAST(T)(on_true), | ||
|  |         ASIO_MOVE_CAST(OnFalse)(on_false_)); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Set the false branch of the conditional.
 | ||
|  |   template <typename T> | ||
|  |   deferred_conditional<OnTrue, T> otherwise(T on_false, | ||
|  |       typename constraint< | ||
|  |         is_deferred<T>::value | ||
|  |       >::type* = 0, | ||
|  |       typename constraint< | ||
|  |         !is_same< | ||
|  |           typename conditional<true, OnTrue, T>::type, | ||
|  |           deferred_noop | ||
|  |         >::value | ||
|  |       >::type* = 0, | ||
|  |       typename constraint< | ||
|  |         is_same< | ||
|  |           typename conditional<true, OnFalse, T>::type, | ||
|  |           deferred_noop | ||
|  |         >::value | ||
|  |       >::type* = 0) ASIO_RVALUE_REF_QUAL | ||
|  |   { | ||
|  |     return deferred_conditional<OnTrue, T>( | ||
|  |         bool_, ASIO_MOVE_CAST(OnTrue)(on_true_), | ||
|  |         ASIO_MOVE_CAST(T)(on_false)); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | #if !defined(GENERATING_DOCUMENTATION)
 | ||
|  | template <typename OnTrue, typename OnFalse> | ||
|  | struct is_deferred<deferred_conditional<OnTrue, OnFalse> > : true_type | ||
|  | { | ||
|  | }; | ||
|  | #endif // !defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | /// Class used to specify that an asynchronous operation should return a
 | ||
|  | /// function object to lazily launch the operation.
 | ||
|  | /**
 | ||
|  |  * The deferred_t class is used to indicate that an asynchronous operation | ||
|  |  * should return a function object which is itself an initiation function. A | ||
|  |  * deferred_t object may be passed as a completion token to an asynchronous | ||
|  |  * operation, typically using the special value @c asio::deferred. For | ||
|  |  * example: | ||
|  |  * | ||
|  |  * @code auto my_deferred_op | ||
|  |  *   = my_socket.async_read_some(my_buffer, | ||
|  |  *       asio::deferred); @endcode | ||
|  |  * | ||
|  |  * The initiating function (async_read_some in the above example) returns a | ||
|  |  * function object that will lazily initiate the operation. | ||
|  |  */ | ||
|  | class deferred_t | ||
|  | { | ||
|  | public: | ||
|  |   /// Default constructor.
 | ||
|  |   ASIO_CONSTEXPR deferred_t() | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Adapts an executor to add the @c deferred_t completion token as the
 | ||
|  |   /// default.
 | ||
|  |   template <typename InnerExecutor> | ||
|  |   struct executor_with_default : InnerExecutor | ||
|  |   { | ||
|  |     /// Specify @c deferred_t as the default completion token type.
 | ||
|  |     typedef deferred_t default_completion_token_type; | ||
|  | 
 | ||
|  |     /// Construct the adapted executor from the inner executor type.
 | ||
|  |     template <typename InnerExecutor1> | ||
|  |     executor_with_default(const InnerExecutor1& ex, | ||
|  |         typename constraint< | ||
|  |           conditional< | ||
|  |             !is_same<InnerExecutor1, executor_with_default>::value, | ||
|  |             is_convertible<InnerExecutor1, InnerExecutor>, | ||
|  |             false_type | ||
|  |           >::type::value | ||
|  |         >::type = 0) ASIO_NOEXCEPT | ||
|  |       : InnerExecutor(ex) | ||
|  |     { | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   /// Type alias to adapt an I/O object to use @c deferred_t as its
 | ||
|  |   /// default completion token type.
 | ||
|  | #if defined(ASIO_HAS_ALIAS_TEMPLATES) \
 | ||
|  |   || defined(GENERATING_DOCUMENTATION) | ||
|  |   template <typename T> | ||
|  |   using as_default_on_t = typename T::template rebind_executor< | ||
|  |       executor_with_default<typename T::executor_type> >::other; | ||
|  | #endif // defined(ASIO_HAS_ALIAS_TEMPLATES)
 | ||
|  |        //   || defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  |   /// Function helper to adapt an I/O object to use @c deferred_t as its
 | ||
|  |   /// default completion token type.
 | ||
|  |   template <typename T> | ||
|  |   static typename decay<T>::type::template rebind_executor< | ||
|  |       executor_with_default<typename decay<T>::type::executor_type> | ||
|  |     >::other | ||
|  |   as_default_on(ASIO_MOVE_ARG(T) object) | ||
|  |   { | ||
|  |     return typename decay<T>::type::template rebind_executor< | ||
|  |         executor_with_default<typename decay<T>::type::executor_type> | ||
|  |       >::other(ASIO_MOVE_CAST(T)(object)); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Creates a new deferred from a function.
 | ||
|  |   template <typename Function> | ||
|  |   typename constraint< | ||
|  |     !is_deferred<typename decay<Function>::type>::value, | ||
|  |     deferred_function<typename decay<Function>::type> | ||
|  |   >::type operator()(ASIO_MOVE_ARG(Function) function) const | ||
|  |   { | ||
|  |     return deferred_function<typename decay<Function>::type>( | ||
|  |         deferred_init_tag{}, ASIO_MOVE_CAST(Function)(function)); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Passes through anything that is already deferred.
 | ||
|  |   template <typename T> | ||
|  |   typename constraint< | ||
|  |     is_deferred<typename decay<T>::type>::value, | ||
|  |     typename decay<T>::type | ||
|  |   >::type operator()(ASIO_MOVE_ARG(T) t) const | ||
|  |   { | ||
|  |     return ASIO_MOVE_CAST(T)(t); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Returns a deferred operation that returns the provided values.
 | ||
|  |   template <typename... Args> | ||
|  |   static ASIO_CONSTEXPR deferred_values<typename decay<Args>::type...> | ||
|  |   values(ASIO_MOVE_ARG(Args)... args) | ||
|  |   { | ||
|  |     return deferred_values<typename decay<Args>::type...>( | ||
|  |         deferred_init_tag{}, ASIO_MOVE_CAST(Args)(args)...); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Creates a conditional object for branching deferred operations.
 | ||
|  |   static ASIO_CONSTEXPR deferred_conditional<> when(bool b) | ||
|  |   { | ||
|  |     return deferred_conditional<>(b); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /// Pipe operator used to chain deferred operations.
 | ||
|  | template <typename Head, typename Tail> | ||
|  | inline auto operator|(Head head, ASIO_MOVE_ARG(Tail) tail) | ||
|  |   -> typename constraint< | ||
|  |       is_deferred<Head>::value, | ||
|  |       decltype(ASIO_MOVE_OR_LVALUE(Head)(head)( | ||
|  |             ASIO_MOVE_CAST(Tail)(tail))) | ||
|  |     >::type | ||
|  | { | ||
|  |   return ASIO_MOVE_OR_LVALUE(Head)(head)( | ||
|  |       ASIO_MOVE_CAST(Tail)(tail)); | ||
|  | } | ||
|  | 
 | ||
|  | /// A @ref completion_token object used to specify that an asynchronous
 | ||
|  | /// operation should return a function object to lazily launch the operation.
 | ||
|  | /**
 | ||
|  |  * See the documentation for asio::deferred_t for a usage example. | ||
|  |  */ | ||
|  | #if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
 | ||
|  | constexpr deferred_t deferred; | ||
|  | #elif defined(ASIO_MSVC)
 | ||
|  | __declspec(selectany) deferred_t deferred; | ||
|  | #endif
 | ||
|  | 
 | ||
|  | } // namespace asio
 | ||
|  | 
 | ||
|  | #include "asio/detail/pop_options.hpp"
 | ||
|  | 
 | ||
|  | #include "asio/impl/deferred.hpp"
 | ||
|  | 
 | ||
|  | #endif // (defined(ASIO_HAS_STD_TUPLE)
 | ||
|  |        //     && defined(ASIO_HAS_DECLTYPE))
 | ||
|  |        //     && defined(ASIO_HAS_VARIADIC_TEMPLATES))
 | ||
|  |        //   || defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | #endif // ASIO_DEFERRED_HPP
 |