1054 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			1054 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //
 | ||
|  | // impl/use_future.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_IMPL_USE_FUTURE_HPP
 | ||
|  | #define ASIO_IMPL_USE_FUTURE_HPP
 | ||
|  | 
 | ||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 | ||
|  | # pragma once
 | ||
|  | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 | ||
|  | 
 | ||
|  | #include "asio/detail/config.hpp"
 | ||
|  | #include <tuple>
 | ||
|  | #include "asio/async_result.hpp"
 | ||
|  | #include "asio/detail/memory.hpp"
 | ||
|  | #include "asio/dispatch.hpp"
 | ||
|  | #include "asio/error_code.hpp"
 | ||
|  | #include "asio/execution.hpp"
 | ||
|  | #include "asio/packaged_task.hpp"
 | ||
|  | #include "asio/system_error.hpp"
 | ||
|  | #include "asio/system_executor.hpp"
 | ||
|  | 
 | ||
|  | #include "asio/detail/push_options.hpp"
 | ||
|  | 
 | ||
|  | namespace asio { | ||
|  | namespace detail { | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | template <typename T, typename F, typename... Args> | ||
|  | inline void promise_invoke_and_set(std::promise<T>& p, | ||
|  |     F& f, ASIO_MOVE_ARG(Args)... args) | ||
|  | { | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   try | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   { | ||
|  |     p.set_value(f(ASIO_MOVE_CAST(Args)(args)...)); | ||
|  |   } | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   catch (...) | ||
|  |   { | ||
|  |     p.set_exception(std::current_exception()); | ||
|  |   } | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  | } | ||
|  | 
 | ||
|  | template <typename F, typename... Args> | ||
|  | inline void promise_invoke_and_set(std::promise<void>& p, | ||
|  |     F& f, ASIO_MOVE_ARG(Args)... args) | ||
|  | { | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   try | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   { | ||
|  |     f(ASIO_MOVE_CAST(Args)(args)...); | ||
|  |     p.set_value(); | ||
|  |   } | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   catch (...) | ||
|  |   { | ||
|  |     p.set_exception(std::current_exception()); | ||
|  |   } | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  | } | ||
|  | 
 | ||
|  | #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | template <typename T, typename F> | ||
|  | inline void promise_invoke_and_set(std::promise<T>& p, F& f) | ||
|  | { | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   try | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   { | ||
|  |     p.set_value(f()); | ||
|  |   } | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   catch (...) | ||
|  |   { | ||
|  |     p.set_exception(std::current_exception()); | ||
|  |   } | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  | } | ||
|  | 
 | ||
|  | template <typename F, typename Args> | ||
|  | inline void promise_invoke_and_set(std::promise<void>& p, F& f) | ||
|  | { | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   try | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   { | ||
|  |     f(); | ||
|  |     p.set_value(); | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   } | ||
|  |   catch (...) | ||
|  |   { | ||
|  |     p.set_exception(std::current_exception()); | ||
|  |   } | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  | } | ||
|  | 
 | ||
|  | #if defined(ASIO_NO_EXCEPTIONS)
 | ||
|  | 
 | ||
|  | #define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
 | ||
|  |   template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   inline void promise_invoke_and_set(std::promise<T>& p, \ | ||
|  |       F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ | ||
|  |   { \ | ||
|  |     p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \ | ||
|  |   } \ | ||
|  |   \ | ||
|  |   template <typename F, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   inline void promise_invoke_and_set(std::promise<void>& p, \ | ||
|  |       F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ | ||
|  |   { \ | ||
|  |     f(ASIO_VARIADIC_MOVE_ARGS(n)); \ | ||
|  |     p.set_value(); \ | ||
|  |   } \ | ||
|  |   /**/ | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF) | ||
|  | #undef ASIO_PRIVATE_PROMISE_INVOKE_DEF
 | ||
|  | 
 | ||
|  | #else // defined(ASIO_NO_EXCEPTIONS)
 | ||
|  | 
 | ||
|  | #define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
 | ||
|  |   template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   inline void promise_invoke_and_set(std::promise<T>& p, \ | ||
|  |       F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ | ||
|  |   { \ | ||
|  |     try \ | ||
|  |     { \ | ||
|  |       p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \ | ||
|  |     } \ | ||
|  |     catch (...) \ | ||
|  |     { \ | ||
|  |       p.set_exception(std::current_exception()); \ | ||
|  |     } \ | ||
|  |   } \ | ||
|  |   \ | ||
|  |   template <typename F, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   inline void promise_invoke_and_set(std::promise<void>& p, \ | ||
|  |       F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ | ||
|  |   { \ | ||
|  |     try \ | ||
|  |     { \ | ||
|  |       f(ASIO_VARIADIC_MOVE_ARGS(n)); \ | ||
|  |       p.set_value(); \ | ||
|  |     } \ | ||
|  |     catch (...) \ | ||
|  |     { \ | ||
|  |       p.set_exception(std::current_exception()); \ | ||
|  |     } \ | ||
|  |   } \ | ||
|  |   /**/ | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF) | ||
|  | #undef ASIO_PRIVATE_PROMISE_INVOKE_DEF
 | ||
|  | 
 | ||
|  | #endif // defined(ASIO_NO_EXCEPTIONS)
 | ||
|  | 
 | ||
|  | #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | // A function object adapter to invoke a nullary function object and capture
 | ||
|  | // any exception thrown into a promise.
 | ||
|  | template <typename T, typename F> | ||
|  | class promise_invoker | ||
|  | { | ||
|  | public: | ||
|  |   promise_invoker(const shared_ptr<std::promise<T> >& p, | ||
|  |       ASIO_MOVE_ARG(F) f) | ||
|  |     : p_(p), f_(ASIO_MOVE_CAST(F)(f)) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   void operator()() | ||
|  |   { | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |     try | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |     { | ||
|  |       f_(); | ||
|  |     } | ||
|  | #if !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |     catch (...) | ||
|  |     { | ||
|  |       p_->set_exception(std::current_exception()); | ||
|  |     } | ||
|  | #endif // !defined(ASIO_NO_EXCEPTIONS)
 | ||
|  |   } | ||
|  | 
 | ||
|  | private: | ||
|  |   shared_ptr<std::promise<T> > p_; | ||
|  |   typename decay<F>::type f_; | ||
|  | }; | ||
|  | 
 | ||
|  | // An executor that adapts the system_executor to capture any exeption thrown
 | ||
|  | // by a submitted function object and save it into a promise.
 | ||
|  | template <typename T, typename Blocking = execution::blocking_t::possibly_t> | ||
|  | class promise_executor | ||
|  | { | ||
|  | public: | ||
|  |   explicit promise_executor(const shared_ptr<std::promise<T> >& p) | ||
|  |     : p_(p) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   execution_context& query(execution::context_t) const ASIO_NOEXCEPT | ||
|  |   { | ||
|  |     return asio::query(system_executor(), execution::context); | ||
|  |   } | ||
|  | 
 | ||
|  |   static ASIO_CONSTEXPR Blocking query(execution::blocking_t) | ||
|  |   { | ||
|  |     return Blocking(); | ||
|  |   } | ||
|  | 
 | ||
|  |   promise_executor<T, execution::blocking_t::possibly_t> | ||
|  |   require(execution::blocking_t::possibly_t) const | ||
|  |   { | ||
|  |     return promise_executor<T, execution::blocking_t::possibly_t>(p_); | ||
|  |   } | ||
|  | 
 | ||
|  |   promise_executor<T, execution::blocking_t::never_t> | ||
|  |   require(execution::blocking_t::never_t) const | ||
|  |   { | ||
|  |     return promise_executor<T, execution::blocking_t::never_t>(p_); | ||
|  |   } | ||
|  | 
 | ||
|  |   template <typename F> | ||
|  |   void execute(ASIO_MOVE_ARG(F) f) const | ||
|  |   { | ||
|  | #if defined(ASIO_NO_DEPRECATED)
 | ||
|  |     asio::require(system_executor(), Blocking()).execute( | ||
|  |         promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f))); | ||
|  | #else // defined(ASIO_NO_DEPRECATED)
 | ||
|  |     execution::execute( | ||
|  |         asio::require(system_executor(), Blocking()), | ||
|  |         promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f))); | ||
|  | #endif // defined(ASIO_NO_DEPRECATED)
 | ||
|  |   } | ||
|  | 
 | ||
|  | #if !defined(ASIO_NO_TS_EXECUTORS)
 | ||
|  |   execution_context& context() const ASIO_NOEXCEPT | ||
|  |   { | ||
|  |     return system_executor().context(); | ||
|  |   } | ||
|  | 
 | ||
|  |   void on_work_started() const ASIO_NOEXCEPT {} | ||
|  |   void on_work_finished() const ASIO_NOEXCEPT {} | ||
|  | 
 | ||
|  |   template <typename F, typename A> | ||
|  |   void dispatch(ASIO_MOVE_ARG(F) f, const A&) const | ||
|  |   { | ||
|  |     promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f))(); | ||
|  |   } | ||
|  | 
 | ||
|  |   template <typename F, typename A> | ||
|  |   void post(ASIO_MOVE_ARG(F) f, const A& a) const | ||
|  |   { | ||
|  |     system_executor().post( | ||
|  |         promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a); | ||
|  |   } | ||
|  | 
 | ||
|  |   template <typename F, typename A> | ||
|  |   void defer(ASIO_MOVE_ARG(F) f, const A& a) const | ||
|  |   { | ||
|  |     system_executor().defer( | ||
|  |         promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a); | ||
|  |   } | ||
|  | #endif // !defined(ASIO_NO_TS_EXECUTORS)
 | ||
|  | 
 | ||
|  |   friend bool operator==(const promise_executor& a, | ||
|  |       const promise_executor& b) ASIO_NOEXCEPT | ||
|  |   { | ||
|  |     return a.p_ == b.p_; | ||
|  |   } | ||
|  | 
 | ||
|  |   friend bool operator!=(const promise_executor& a, | ||
|  |       const promise_executor& b) ASIO_NOEXCEPT | ||
|  |   { | ||
|  |     return a.p_ != b.p_; | ||
|  |   } | ||
|  | 
 | ||
|  | private: | ||
|  |   shared_ptr<std::promise<T> > p_; | ||
|  | }; | ||
|  | 
 | ||
|  | // The base class for all completion handlers that create promises.
 | ||
|  | template <typename T> | ||
|  | class promise_creator | ||
|  | { | ||
|  | public: | ||
|  |   typedef promise_executor<T> executor_type; | ||
|  | 
 | ||
|  |   executor_type get_executor() const ASIO_NOEXCEPT | ||
|  |   { | ||
|  |     return executor_type(p_); | ||
|  |   } | ||
|  | 
 | ||
|  |   typedef std::future<T> future_type; | ||
|  | 
 | ||
|  |   future_type get_future() | ||
|  |   { | ||
|  |     return p_->get_future(); | ||
|  |   } | ||
|  | 
 | ||
|  | protected: | ||
|  |   template <typename Allocator> | ||
|  |   void create_promise(const Allocator& a) | ||
|  |   { | ||
|  |     ASIO_REBIND_ALLOC(Allocator, char) b(a); | ||
|  |     p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b); | ||
|  |   } | ||
|  | 
 | ||
|  |   shared_ptr<std::promise<T> > p_; | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void().
 | ||
|  | class promise_handler_0 | ||
|  |   : public promise_creator<void> | ||
|  | { | ||
|  | public: | ||
|  |   void operator()() | ||
|  |   { | ||
|  |     this->p_->set_value(); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void(error_code).
 | ||
|  | class promise_handler_ec_0 | ||
|  |   : public promise_creator<void> | ||
|  | { | ||
|  | public: | ||
|  |   void operator()(const asio::error_code& ec) | ||
|  |   { | ||
|  |     if (ec) | ||
|  |     { | ||
|  |       this->p_->set_exception( | ||
|  |           std::make_exception_ptr( | ||
|  |             asio::system_error(ec))); | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       this->p_->set_value(); | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void(exception_ptr).
 | ||
|  | class promise_handler_ex_0 | ||
|  |   : public promise_creator<void> | ||
|  | { | ||
|  | public: | ||
|  |   void operator()(const std::exception_ptr& ex) | ||
|  |   { | ||
|  |     if (ex) | ||
|  |     { | ||
|  |       this->p_->set_exception(ex); | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       this->p_->set_value(); | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void(T).
 | ||
|  | template <typename T> | ||
|  | class promise_handler_1 | ||
|  |   : public promise_creator<T> | ||
|  | { | ||
|  | public: | ||
|  |   template <typename Arg> | ||
|  |   void operator()(ASIO_MOVE_ARG(Arg) arg) | ||
|  |   { | ||
|  |     this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void(error_code, T).
 | ||
|  | template <typename T> | ||
|  | class promise_handler_ec_1 | ||
|  |   : public promise_creator<T> | ||
|  | { | ||
|  | public: | ||
|  |   template <typename Arg> | ||
|  |   void operator()(const asio::error_code& ec, | ||
|  |       ASIO_MOVE_ARG(Arg) arg) | ||
|  |   { | ||
|  |     if (ec) | ||
|  |     { | ||
|  |       this->p_->set_exception( | ||
|  |           std::make_exception_ptr( | ||
|  |             asio::system_error(ec))); | ||
|  |     } | ||
|  |     else | ||
|  |       this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void(exception_ptr, T).
 | ||
|  | template <typename T> | ||
|  | class promise_handler_ex_1 | ||
|  |   : public promise_creator<T> | ||
|  | { | ||
|  | public: | ||
|  |   template <typename Arg> | ||
|  |   void operator()(const std::exception_ptr& ex, | ||
|  |       ASIO_MOVE_ARG(Arg) arg) | ||
|  |   { | ||
|  |     if (ex) | ||
|  |       this->p_->set_exception(ex); | ||
|  |     else | ||
|  |       this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void(T1, ..., Tn);
 | ||
|  | template <typename T> | ||
|  | class promise_handler_n | ||
|  |   : public promise_creator<T> | ||
|  | { | ||
|  | public: | ||
|  | #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  |   template <typename... Args> | ||
|  |   void operator()(ASIO_MOVE_ARG(Args)... args) | ||
|  |   { | ||
|  |     this->p_->set_value( | ||
|  |         std::forward_as_tuple( | ||
|  |           ASIO_MOVE_CAST(Args)(args)...)); | ||
|  |   } | ||
|  | 
 | ||
|  | #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | #define ASIO_PRIVATE_CALL_OP_DEF(n) \
 | ||
|  |   template <ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \ | ||
|  |   {\ | ||
|  |     this->p_->set_value( \ | ||
|  |         std::forward_as_tuple( \ | ||
|  |           ASIO_VARIADIC_MOVE_ARGS(n))); \ | ||
|  |   } \ | ||
|  |   /**/ | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) | ||
|  | #undef ASIO_PRIVATE_CALL_OP_DEF
 | ||
|  | 
 | ||
|  | #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void(error_code, T1, ..., Tn);
 | ||
|  | template <typename T> | ||
|  | class promise_handler_ec_n | ||
|  |   : public promise_creator<T> | ||
|  | { | ||
|  | public: | ||
|  | #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  |   template <typename... Args> | ||
|  |   void operator()(const asio::error_code& ec, | ||
|  |       ASIO_MOVE_ARG(Args)... args) | ||
|  |   { | ||
|  |     if (ec) | ||
|  |     { | ||
|  |       this->p_->set_exception( | ||
|  |           std::make_exception_ptr( | ||
|  |             asio::system_error(ec))); | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       this->p_->set_value( | ||
|  |           std::forward_as_tuple( | ||
|  |             ASIO_MOVE_CAST(Args)(args)...)); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  | #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | #define ASIO_PRIVATE_CALL_OP_DEF(n) \
 | ||
|  |   template <ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   void operator()(const asio::error_code& ec, \ | ||
|  |       ASIO_VARIADIC_MOVE_PARAMS(n)) \ | ||
|  |   {\ | ||
|  |     if (ec) \ | ||
|  |     { \ | ||
|  |       this->p_->set_exception( \ | ||
|  |           std::make_exception_ptr( \ | ||
|  |             asio::system_error(ec))); \ | ||
|  |     } \ | ||
|  |     else \ | ||
|  |     { \ | ||
|  |       this->p_->set_value( \ | ||
|  |           std::forward_as_tuple( \ | ||
|  |             ASIO_VARIADIC_MOVE_ARGS(n))); \ | ||
|  |     } \ | ||
|  |   } \ | ||
|  |   /**/ | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) | ||
|  | #undef ASIO_PRIVATE_CALL_OP_DEF
 | ||
|  | 
 | ||
|  | #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | }; | ||
|  | 
 | ||
|  | // For completion signature void(exception_ptr, T1, ..., Tn);
 | ||
|  | template <typename T> | ||
|  | class promise_handler_ex_n | ||
|  |   : public promise_creator<T> | ||
|  | { | ||
|  | public: | ||
|  | #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  |   template <typename... Args> | ||
|  |   void operator()(const std::exception_ptr& ex, | ||
|  |       ASIO_MOVE_ARG(Args)... args) | ||
|  |   { | ||
|  |     if (ex) | ||
|  |       this->p_->set_exception(ex); | ||
|  |     else | ||
|  |     { | ||
|  |       this->p_->set_value( | ||
|  |           std::forward_as_tuple( | ||
|  |             ASIO_MOVE_CAST(Args)(args)...)); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  | #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | #define ASIO_PRIVATE_CALL_OP_DEF(n) \
 | ||
|  |   template <ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   void operator()(const std::exception_ptr& ex, \ | ||
|  |       ASIO_VARIADIC_MOVE_PARAMS(n)) \ | ||
|  |   {\ | ||
|  |     if (ex) \ | ||
|  |       this->p_->set_exception(ex); \ | ||
|  |     else \ | ||
|  |     { \ | ||
|  |       this->p_->set_value( \ | ||
|  |           std::forward_as_tuple( \ | ||
|  |             ASIO_VARIADIC_MOVE_ARGS(n))); \ | ||
|  |     } \ | ||
|  |   } \ | ||
|  |   /**/ | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) | ||
|  | #undef ASIO_PRIVATE_CALL_OP_DEF
 | ||
|  | 
 | ||
|  | #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | }; | ||
|  | 
 | ||
|  | // Helper template to choose the appropriate concrete promise handler
 | ||
|  | // implementation based on the supplied completion signature.
 | ||
|  | template <typename> class promise_handler_selector; | ||
|  | 
 | ||
|  | template <> | ||
|  | class promise_handler_selector<void()> | ||
|  |   : public promise_handler_0 {}; | ||
|  | 
 | ||
|  | template <> | ||
|  | class promise_handler_selector<void(asio::error_code)> | ||
|  |   : public promise_handler_ec_0 {}; | ||
|  | 
 | ||
|  | template <> | ||
|  | class promise_handler_selector<void(std::exception_ptr)> | ||
|  |   : public promise_handler_ex_0 {}; | ||
|  | 
 | ||
|  | template <typename Arg> | ||
|  | class promise_handler_selector<void(Arg)> | ||
|  |   : public promise_handler_1<Arg> {}; | ||
|  | 
 | ||
|  | template <typename Arg> | ||
|  | class promise_handler_selector<void(asio::error_code, Arg)> | ||
|  |   : public promise_handler_ec_1<Arg> {}; | ||
|  | 
 | ||
|  | template <typename Arg> | ||
|  | class promise_handler_selector<void(std::exception_ptr, Arg)> | ||
|  |   : public promise_handler_ex_1<Arg> {}; | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | template <typename... Arg> | ||
|  | class promise_handler_selector<void(Arg...)> | ||
|  |   : public promise_handler_n<std::tuple<Arg...> > {}; | ||
|  | 
 | ||
|  | template <typename... Arg> | ||
|  | class promise_handler_selector<void(asio::error_code, Arg...)> | ||
|  |   : public promise_handler_ec_n<std::tuple<Arg...> > {}; | ||
|  | 
 | ||
|  | template <typename... Arg> | ||
|  | class promise_handler_selector<void(std::exception_ptr, Arg...)> | ||
|  |   : public promise_handler_ex_n<std::tuple<Arg...> > {}; | ||
|  | 
 | ||
|  | #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | #define ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \
 | ||
|  |   template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   class promise_handler_selector< \ | ||
|  |     void(Arg, ASIO_VARIADIC_TARGS(n))> \ | ||
|  |       : public promise_handler_n< \ | ||
|  |         std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ | ||
|  |   \ | ||
|  |   template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   class promise_handler_selector< \ | ||
|  |     void(asio::error_code, Arg, ASIO_VARIADIC_TARGS(n))> \ | ||
|  |       : public promise_handler_ec_n< \ | ||
|  |         std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ | ||
|  |   \ | ||
|  |   template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   class promise_handler_selector< \ | ||
|  |     void(std::exception_ptr, Arg, ASIO_VARIADIC_TARGS(n))> \ | ||
|  |       : public promise_handler_ex_n< \ | ||
|  |         std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ | ||
|  |   /**/ | ||
|  |   ASIO_VARIADIC_GENERATE_5(ASIO_PRIVATE_PROMISE_SELECTOR_DEF) | ||
|  | #undef ASIO_PRIVATE_PROMISE_SELECTOR_DEF
 | ||
|  | 
 | ||
|  | #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | // Completion handlers produced from the use_future completion token, when not
 | ||
|  | // using use_future::operator().
 | ||
|  | template <typename Signature, typename Allocator> | ||
|  | class promise_handler | ||
|  |   : public promise_handler_selector<Signature> | ||
|  | { | ||
|  | public: | ||
|  |   typedef Allocator allocator_type; | ||
|  |   typedef void result_type; | ||
|  | 
 | ||
|  |   promise_handler(use_future_t<Allocator> u) | ||
|  |     : allocator_(u.get_allocator()) | ||
|  |   { | ||
|  |     this->create_promise(allocator_); | ||
|  |   } | ||
|  | 
 | ||
|  |   allocator_type get_allocator() const ASIO_NOEXCEPT | ||
|  |   { | ||
|  |     return allocator_; | ||
|  |   } | ||
|  | 
 | ||
|  | private: | ||
|  |   Allocator allocator_; | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename Function> | ||
|  | struct promise_function_wrapper | ||
|  | { | ||
|  |   explicit promise_function_wrapper(Function& f) | ||
|  |     : function_(ASIO_MOVE_CAST(Function)(f)) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   explicit promise_function_wrapper(const Function& f) | ||
|  |     : function_(f) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   void operator()() | ||
|  |   { | ||
|  |     function_(); | ||
|  |   } | ||
|  | 
 | ||
|  |   Function function_; | ||
|  | }; | ||
|  | 
 | ||
|  | #if !defined(ASIO_NO_DEPRECATED)
 | ||
|  | 
 | ||
|  | template <typename Function, typename Signature, typename Allocator> | ||
|  | inline void asio_handler_invoke(Function& f, | ||
|  |     promise_handler<Signature, Allocator>* h) | ||
|  | { | ||
|  |   typename promise_handler<Signature, Allocator>::executor_type | ||
|  |     ex(h->get_executor()); | ||
|  |   asio::dispatch(ex, promise_function_wrapper<Function>(f)); | ||
|  | } | ||
|  | 
 | ||
|  | template <typename Function, typename Signature, typename Allocator> | ||
|  | inline void asio_handler_invoke(const Function& f, | ||
|  |     promise_handler<Signature, Allocator>* h) | ||
|  | { | ||
|  |   typename promise_handler<Signature, Allocator>::executor_type | ||
|  |     ex(h->get_executor()); | ||
|  |   asio::dispatch(ex, promise_function_wrapper<Function>(f)); | ||
|  | } | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_NO_DEPRECATED)
 | ||
|  | 
 | ||
|  | // Helper base class for async_result specialisation.
 | ||
|  | template <typename Signature, typename Allocator> | ||
|  | class promise_async_result | ||
|  | { | ||
|  | public: | ||
|  |   typedef promise_handler<Signature, Allocator> completion_handler_type; | ||
|  |   typedef typename completion_handler_type::future_type return_type; | ||
|  | 
 | ||
|  |   explicit promise_async_result(completion_handler_type& h) | ||
|  |     : future_(h.get_future()) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   return_type get() | ||
|  |   { | ||
|  |     return ASIO_MOVE_CAST(return_type)(future_); | ||
|  |   } | ||
|  | 
 | ||
|  | private: | ||
|  |   return_type future_; | ||
|  | }; | ||
|  | 
 | ||
|  | // Return value from use_future::operator().
 | ||
|  | template <typename Function, typename Allocator> | ||
|  | class packaged_token | ||
|  | { | ||
|  | public: | ||
|  |   packaged_token(Function f, const Allocator& a) | ||
|  |     : function_(ASIO_MOVE_CAST(Function)(f)), | ||
|  |       allocator_(a) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  | //private:
 | ||
|  |   Function function_; | ||
|  |   Allocator allocator_; | ||
|  | }; | ||
|  | 
 | ||
|  | // Completion handlers produced from the use_future completion token, when
 | ||
|  | // using use_future::operator().
 | ||
|  | template <typename Function, typename Allocator, typename Result> | ||
|  | class packaged_handler | ||
|  |   : public promise_creator<Result> | ||
|  | { | ||
|  | public: | ||
|  |   typedef Allocator allocator_type; | ||
|  |   typedef void result_type; | ||
|  | 
 | ||
|  |   packaged_handler(packaged_token<Function, Allocator> t) | ||
|  |     : function_(ASIO_MOVE_CAST(Function)(t.function_)), | ||
|  |       allocator_(t.allocator_) | ||
|  |   { | ||
|  |     this->create_promise(allocator_); | ||
|  |   } | ||
|  | 
 | ||
|  |   allocator_type get_allocator() const ASIO_NOEXCEPT | ||
|  |   { | ||
|  |     return allocator_; | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  |   template <typename... Args> | ||
|  |   void operator()(ASIO_MOVE_ARG(Args)... args) | ||
|  |   { | ||
|  |     (promise_invoke_and_set)(*this->p_, | ||
|  |         function_, ASIO_MOVE_CAST(Args)(args)...); | ||
|  |   } | ||
|  | 
 | ||
|  | #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  |   void operator()() | ||
|  |   { | ||
|  |     (promise_invoke_and_set)(*this->p_, function_); | ||
|  |   } | ||
|  | 
 | ||
|  | #define ASIO_PRIVATE_CALL_OP_DEF(n) \
 | ||
|  |   template <ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \ | ||
|  |   {\ | ||
|  |     (promise_invoke_and_set)(*this->p_, \ | ||
|  |         function_, ASIO_VARIADIC_MOVE_ARGS(n)); \ | ||
|  |   } \ | ||
|  |   /**/ | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) | ||
|  | #undef ASIO_PRIVATE_CALL_OP_DEF
 | ||
|  | 
 | ||
|  | #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | private: | ||
|  |   Function function_; | ||
|  |   Allocator allocator_; | ||
|  | }; | ||
|  | 
 | ||
|  | #if !defined(ASIO_NO_DEPRECATED)
 | ||
|  | 
 | ||
|  | template <typename Function, | ||
|  |     typename Function1, typename Allocator, typename Result> | ||
|  | inline void asio_handler_invoke(Function& f, | ||
|  |     packaged_handler<Function1, Allocator, Result>* h) | ||
|  | { | ||
|  |   typename packaged_handler<Function1, Allocator, Result>::executor_type | ||
|  |     ex(h->get_executor()); | ||
|  |   asio::dispatch(ex, promise_function_wrapper<Function>(f)); | ||
|  | } | ||
|  | 
 | ||
|  | template <typename Function, | ||
|  |     typename Function1, typename Allocator, typename Result> | ||
|  | inline void asio_handler_invoke(const Function& f, | ||
|  |     packaged_handler<Function1, Allocator, Result>* h) | ||
|  | { | ||
|  |   typename packaged_handler<Function1, Allocator, Result>::executor_type | ||
|  |     ex(h->get_executor()); | ||
|  |   asio::dispatch(ex, promise_function_wrapper<Function>(f)); | ||
|  | } | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_NO_DEPRECATED)
 | ||
|  | 
 | ||
|  | // Helper base class for async_result specialisation.
 | ||
|  | template <typename Function, typename Allocator, typename Result> | ||
|  | class packaged_async_result | ||
|  | { | ||
|  | public: | ||
|  |   typedef packaged_handler<Function, Allocator, Result> completion_handler_type; | ||
|  |   typedef typename completion_handler_type::future_type return_type; | ||
|  | 
 | ||
|  |   explicit packaged_async_result(completion_handler_type& h) | ||
|  |     : future_(h.get_future()) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   return_type get() | ||
|  |   { | ||
|  |     return ASIO_MOVE_CAST(return_type)(future_); | ||
|  |   } | ||
|  | 
 | ||
|  | private: | ||
|  |   return_type future_; | ||
|  | }; | ||
|  | 
 | ||
|  | } // namespace detail
 | ||
|  | 
 | ||
|  | template <typename Allocator> template <typename Function> | ||
|  | inline detail::packaged_token<typename decay<Function>::type, Allocator> | ||
|  | use_future_t<Allocator>::operator()(ASIO_MOVE_ARG(Function) f) const | ||
|  | { | ||
|  |   return detail::packaged_token<typename decay<Function>::type, Allocator>( | ||
|  |       ASIO_MOVE_CAST(Function)(f), allocator_); | ||
|  | } | ||
|  | 
 | ||
|  | #if !defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | template <typename Allocator, typename Result, typename... Args> | ||
|  | class async_result<use_future_t<Allocator>, Result(Args...)> | ||
|  |   : public detail::promise_async_result< | ||
|  |       void(typename decay<Args>::type...), Allocator> | ||
|  | { | ||
|  | public: | ||
|  |   explicit async_result( | ||
|  |     typename detail::promise_async_result<void(typename decay<Args>::type...), | ||
|  |       Allocator>::completion_handler_type& h) | ||
|  |     : detail::promise_async_result< | ||
|  |         void(typename decay<Args>::type...), Allocator>(h) | ||
|  |   { | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename Function, typename Allocator, | ||
|  |     typename Result, typename... Args> | ||
|  | class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)> | ||
|  |   : public detail::packaged_async_result<Function, Allocator, | ||
|  |       typename result_of<Function(Args...)>::type> | ||
|  | { | ||
|  | public: | ||
|  |   explicit async_result( | ||
|  |     typename detail::packaged_async_result<Function, Allocator, | ||
|  |       typename result_of<Function(Args...)>::type>::completion_handler_type& h) | ||
|  |     : detail::packaged_async_result<Function, Allocator, | ||
|  |         typename result_of<Function(Args...)>::type>(h) | ||
|  |   { | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | template <typename Allocator, typename Result> | ||
|  | class async_result<use_future_t<Allocator>, Result()> | ||
|  |   : public detail::promise_async_result<void(), Allocator> | ||
|  | { | ||
|  | public: | ||
|  |   explicit async_result( | ||
|  |     typename detail::promise_async_result< | ||
|  |       void(), Allocator>::completion_handler_type& h) | ||
|  |     : detail::promise_async_result<void(), Allocator>(h) | ||
|  |   { | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename Function, typename Allocator, typename Result> | ||
|  | class async_result<detail::packaged_token<Function, Allocator>, Result()> | ||
|  |   : public detail::packaged_async_result<Function, Allocator, | ||
|  |       typename result_of<Function()>::type> | ||
|  | { | ||
|  | public: | ||
|  |   explicit async_result( | ||
|  |     typename detail::packaged_async_result<Function, Allocator, | ||
|  |       typename result_of<Function()>::type>::completion_handler_type& h) | ||
|  |     : detail::packaged_async_result<Function, Allocator, | ||
|  |         typename result_of<Function()>::type>(h) | ||
|  |   { | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | #define ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \
 | ||
|  |   template <typename Allocator, \ | ||
|  |       typename Result, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   class async_result<use_future_t<Allocator>, \ | ||
|  |       Result(ASIO_VARIADIC_TARGS(n))> \ | ||
|  |     : public detail::promise_async_result< \ | ||
|  |         void(ASIO_VARIADIC_DECAY(n)), Allocator> \ | ||
|  |   { \ | ||
|  |   public: \ | ||
|  |     explicit async_result( \ | ||
|  |       typename detail::promise_async_result< \ | ||
|  |         void(ASIO_VARIADIC_DECAY(n)), \ | ||
|  |         Allocator>::completion_handler_type& h) \ | ||
|  |       : detail::promise_async_result< \ | ||
|  |           void(ASIO_VARIADIC_DECAY(n)), Allocator>(h) \ | ||
|  |     { \ | ||
|  |     } \ | ||
|  |   }; \ | ||
|  |   \ | ||
|  |   template <typename Function, typename Allocator, \ | ||
|  |       typename Result, ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   class async_result<detail::packaged_token<Function, Allocator>, \ | ||
|  |       Result(ASIO_VARIADIC_TARGS(n))> \ | ||
|  |     : public detail::packaged_async_result<Function, Allocator, \ | ||
|  |         typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type> \ | ||
|  |   { \ | ||
|  |   public: \ | ||
|  |     explicit async_result( \ | ||
|  |       typename detail::packaged_async_result<Function, Allocator, \ | ||
|  |         typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type \ | ||
|  |         >::completion_handler_type& h) \ | ||
|  |       : detail::packaged_async_result<Function, Allocator, \ | ||
|  |           typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type>(h) \ | ||
|  |     { \ | ||
|  |     } \ | ||
|  |   }; \ | ||
|  |   /**/ | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_RESULT_DEF) | ||
|  | #undef ASIO_PRIVATE_ASYNC_RESULT_DEF
 | ||
|  | 
 | ||
|  | #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | namespace traits { | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
 | ||
|  | 
 | ||
|  | template <typename T, typename Blocking> | ||
|  | struct equality_comparable< | ||
|  |     asio::detail::promise_executor<T, Blocking> > | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | ||
|  | }; | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
 | ||
|  | 
 | ||
|  | template <typename T, typename Blocking, typename Function> | ||
|  | struct execute_member< | ||
|  |     asio::detail::promise_executor<T, Blocking>, Function> | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | ||
|  |   typedef void result_type; | ||
|  | }; | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
 | ||
|  | 
 | ||
|  | template <typename T, typename Blocking, typename Property> | ||
|  | struct query_static_constexpr_member< | ||
|  |     asio::detail::promise_executor<T, Blocking>, | ||
|  |     Property, | ||
|  |     typename asio::enable_if< | ||
|  |       asio::is_convertible< | ||
|  |         Property, | ||
|  |         asio::execution::blocking_t | ||
|  |       >::value | ||
|  |     >::type | ||
|  |   > | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | ||
|  |   typedef Blocking result_type; | ||
|  | 
 | ||
|  |   static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT | ||
|  |   { | ||
|  |     return Blocking(); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
 | ||
|  | 
 | ||
|  | template <typename T, typename Blocking> | ||
|  | struct query_member< | ||
|  |     asio::detail::promise_executor<T, Blocking>, | ||
|  |     execution::context_t | ||
|  |   > | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | ||
|  |   typedef asio::system_context& result_type; | ||
|  | }; | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
 | ||
|  | 
 | ||
|  | template <typename T, typename Blocking> | ||
|  | struct require_member< | ||
|  |     asio::detail::promise_executor<T, Blocking>, | ||
|  |     execution::blocking_t::possibly_t | ||
|  |   > | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | ||
|  |   typedef asio::detail::promise_executor<T, | ||
|  |       execution::blocking_t::possibly_t> result_type; | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename T, typename Blocking> | ||
|  | struct require_member< | ||
|  |     asio::detail::promise_executor<T, Blocking>, | ||
|  |     execution::blocking_t::never_t | ||
|  |   > | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | ||
|  |   typedef asio::detail::promise_executor<T, | ||
|  |       execution::blocking_t::never_t> result_type; | ||
|  | }; | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
 | ||
|  | 
 | ||
|  | } // namespace traits
 | ||
|  | 
 | ||
|  | #endif // !defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | } // namespace asio
 | ||
|  | 
 | ||
|  | #include "asio/detail/pop_options.hpp"
 | ||
|  | 
 | ||
|  | #endif // ASIO_IMPL_USE_FUTURE_HPP
 |