diff --git a/asio/include/Makefile.am b/asio/include/Makefile.am index ca48a874..49907032 100644 --- a/asio/include/Makefile.am +++ b/asio/include/Makefile.am @@ -142,6 +142,7 @@ nobase_include_HEADERS = \ asio/detail/macos_fenced_block.hpp \ asio/detail/memory.hpp \ asio/detail/mutex.hpp \ + asio/detail/non_const_lvalue.hpp \ asio/detail/noncopyable.hpp \ asio/detail/null_event.hpp \ asio/detail/null_fenced_block.hpp \ diff --git a/asio/include/asio/async_result.hpp b/asio/include/asio/async_result.hpp index 5a836b3c..6113c599 100644 --- a/asio/include/asio/async_result.hpp +++ b/asio/include/asio/async_result.hpp @@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" +#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" @@ -66,6 +67,53 @@ public: { } +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ + || defined(GENERATING_DOCUMENTATION) + + /// 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( + ASIO_MOVE_ARG(Initiation) initiation, + ASIO_MOVE_ARG(RawCompletionToken) token, + ASIO_MOVE_ARG(Args)... args) + { + ASIO_MOVE_CAST(Initiation)(initiation)( + ASIO_MOVE_CAST(RawCompletionToken)(token), + ASIO_MOVE_CAST(Args)(args)...); + } + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + // || defined(GENERATING_DOCUMENTATION) + + template + static return_type initiate( + ASIO_MOVE_ARG(Initiation) initiation, + ASIO_MOVE_ARG(RawCompletionToken) token) + { + ASIO_MOVE_CAST(Initiation)(initiation)( + ASIO_MOVE_CAST(RawCompletionToken)(token)); + } + +#define ASIO_PRIVATE_INITIATE_DEF(n) \ + template \ + static return_type initiate( \ + ASIO_MOVE_ARG(Initiation) initiation, \ + ASIO_MOVE_ARG(RawCompletionToken) token, \ + ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + ASIO_MOVE_CAST(Initiation)(initiation)( \ + ASIO_MOVE_CAST(RawCompletionToken)(token), \ + ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + /**/ + ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF) +#undef ASIO_PRIVATE_INITIATE_DEF + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + // || defined(GENERATING_DOCUMENTATION) + private: async_result(const async_result&) ASIO_DELETED; async_result& operator=(const async_result&) ASIO_DELETED; @@ -130,10 +178,40 @@ struct async_result_helper { }; -} // namespace detail -} // namespace asio +struct async_result_memfns_base +{ + void initiate(); +}; -#include "asio/detail/pop_options.hpp" +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::type, Signature> + >(0)) != 1> +{ +}; + +} // namespace detail #if defined(GENERATING_DOCUMENTATION) # define ASIO_INITFN_RESULT_TYPE(ct, sig) \ @@ -154,4 +232,125 @@ struct async_result_helper typename ::asio::decay::type, sig>::completion_handler_type #endif +#if defined(GENERATING_DOCUMENTATION) + +template +ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) +async_initiate(ASIO_MOVE_ARG(Initiation) initiation, + ASIO_NONDEDUCED_MOVE_ARG(CompletionToken), + ASIO_MOVE_ARG(Args)... args); + +#elif defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template +inline typename enable_if< + detail::async_result_has_initiate_memfn::value, + ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type +async_initiate(ASIO_MOVE_ARG(Initiation) initiation, + ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, + ASIO_MOVE_ARG(Args)... args) +{ + return async_result::type, + Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), + ASIO_MOVE_CAST(CompletionToken)(token), + ASIO_MOVE_CAST(Args)(args)...); +} + +template +inline typename enable_if< + !detail::async_result_has_initiate_memfn::value, + ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type +async_initiate(ASIO_MOVE_ARG(Initiation) initiation, + ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, + ASIO_MOVE_ARG(Args)... args) +{ + async_completion completion(token); + + ASIO_MOVE_CAST(Initiation)(initiation)( + ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, + Signature))(completion.completion_handler), + ASIO_MOVE_CAST(Args)(args)...); + + return completion.result.get(); +} + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template +inline typename enable_if< + detail::async_result_has_initiate_memfn::value, + ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type +async_initiate(ASIO_MOVE_ARG(Initiation) initiation, + ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) +{ + return async_result::type, + Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), + ASIO_MOVE_CAST(CompletionToken)(token)); +} + +template +inline typename enable_if< + !detail::async_result_has_initiate_memfn::value, + ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type +async_initiate(ASIO_MOVE_ARG(Initiation) initiation, + ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) +{ + async_completion completion(token); + + ASIO_MOVE_CAST(Initiation)(initiation)( + ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, + Signature))(completion.completion_handler)); + + return completion.result.get(); +} + +#define ASIO_PRIVATE_INITIATE_DEF(n) \ + template \ + inline typename enable_if< \ + detail::async_result_has_initiate_memfn< \ + CompletionToken, Signature>::value, \ + ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \ + async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \ + ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ + ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + return async_result::type, \ + Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), \ + ASIO_MOVE_CAST(CompletionToken)(token), \ + ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + \ + template \ + inline typename enable_if< \ + !detail::async_result_has_initiate_memfn< \ + CompletionToken, Signature>::value, \ + ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \ + async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \ + ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ + ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + async_completion completion(token); \ + \ + ASIO_MOVE_CAST(Initiation)(initiation)( \ + ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \ + Signature))(completion.completion_handler), \ + ASIO_VARIADIC_MOVE_ARGS(n)); \ + \ + return completion.result.get(); \ + } \ + /**/ + ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF) +#undef ASIO_PRIVATE_INITIATE_DEF + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + #endif // ASIO_ASYNC_RESULT_HPP diff --git a/asio/include/asio/basic_datagram_socket.hpp b/asio/include/asio/basic_datagram_socket.hpp index eb845735..bbd4885e 100644 --- a/asio/include/asio/basic_datagram_socket.hpp +++ b/asio/include/asio/basic_datagram_socket.hpp @@ -19,6 +19,7 @@ #include #include "asio/basic_socket.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" @@ -452,18 +453,10 @@ public: async_send(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send(this->impl_.get_implementation(), - buffers, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous send on a connected socket. @@ -501,18 +494,9 @@ public: socket_base::message_flags flags, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send(this->impl_.get_implementation(), - buffers, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send(), handler, this, buffers, flags); } /// Send a datagram to the specified endpoint. @@ -647,18 +631,10 @@ public: const endpoint_type& destination, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send_to(this->impl_.get_implementation(), - buffers, destination, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send_to(), handler, this, buffers, + destination, socket_base::message_flags(0)); } /// Start an asynchronous send. @@ -695,18 +671,9 @@ public: const endpoint_type& destination, socket_base::message_flags flags, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send_to( - this->impl_.get_implementation(), buffers, destination, flags, - init.completion_handler, this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send_to(), handler, this, buffers, destination, flags); } /// Receive some data on a connected socket. @@ -840,18 +807,10 @@ public: async_receive(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive(this->impl_.get_implementation(), - buffers, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive on a connected socket. @@ -889,18 +848,9 @@ public: socket_base::message_flags flags, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive(this->impl_.get_implementation(), - buffers, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive(), handler, this, buffers, flags); } /// Receive a datagram with the endpoint of the sender. @@ -1035,19 +985,10 @@ public: endpoint_type& sender_endpoint, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive_from( - this->impl_.get_implementation(), buffers, - sender_endpoint, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive_from(), handler, this, buffers, + &sender_endpoint, socket_base::message_flags(0)); } /// Start an asynchronous receive. @@ -1086,20 +1027,85 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive_from( - this->impl_.get_implementation(), buffers, - sender_endpoint, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive_from(), handler, + this, buffers, &sender_endpoint, flags); } + +private: + struct initiate_async_send + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + basic_datagram_socket* self, const ConstBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_send_to + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + basic_datagram_socket* self, const ConstBufferSequence& buffers, + const endpoint_type& destination, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send_to( + self->impl_.get_implementation(), buffers, destination, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_receive + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + basic_datagram_socket* self, const MutableBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_receive_from + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + basic_datagram_socket* self, const MutableBufferSequence& buffers, + endpoint_type* sender_endpoint, socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive_from( + self->impl_.get_implementation(), buffers, *sender_endpoint, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; }; } // namespace asio diff --git a/asio/include/asio/basic_deadline_timer.hpp b/asio/include/asio/basic_deadline_timer.hpp index 21d80def..d8100a79 100644 --- a/asio/include/asio/basic_deadline_timer.hpp +++ b/asio/include/asio/basic_deadline_timer.hpp @@ -24,6 +24,7 @@ #include "asio/detail/deadline_timer_service.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" @@ -624,17 +625,8 @@ public: void (asio::error_code)) async_wait(ASIO_MOVE_ARG(WaitHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WaitHandler. - ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_wait(impl_.get_implementation(), - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_wait(), handler, this); } private: @@ -643,6 +635,23 @@ private: basic_deadline_timer& operator=( const basic_deadline_timer&) ASIO_DELETED; + struct initiate_async_wait + { + template + void operator()(ASIO_MOVE_ARG(WaitHandler) handler, + basic_deadline_timer* self) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), handler2.value, + self->impl_.get_implementation_executor()); + } + }; + detail::io_object_impl< detail::deadline_timer_service, Executor> impl_; }; diff --git a/asio/include/asio/basic_raw_socket.hpp b/asio/include/asio/basic_raw_socket.hpp index 10a810fd..1cc54f49 100644 --- a/asio/include/asio/basic_raw_socket.hpp +++ b/asio/include/asio/basic_raw_socket.hpp @@ -19,6 +19,7 @@ #include #include "asio/basic_socket.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" @@ -444,18 +445,10 @@ public: async_send(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send(this->impl_.get_implementation(), - buffers, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous send on a connected socket. @@ -493,18 +486,9 @@ public: socket_base::message_flags flags, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send(this->impl_.get_implementation(), - buffers, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send(), handler, this, buffers, flags); } /// Send raw data to the specified endpoint. @@ -639,18 +623,10 @@ public: const endpoint_type& destination, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send_to(this->impl_.get_implementation(), - buffers, destination, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send_to(), handler, this, buffers, + destination, socket_base::message_flags(0)); } /// Start an asynchronous send. @@ -687,18 +663,9 @@ public: const endpoint_type& destination, socket_base::message_flags flags, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send_to( - this->impl_.get_implementation(), buffers, destination, flags, - init.completion_handler, this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send_to(), handler, this, buffers, destination, flags); } /// Receive some data on a connected socket. @@ -832,18 +799,10 @@ public: async_receive(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive(this->impl_.get_implementation(), - buffers, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive on a connected socket. @@ -881,18 +840,9 @@ public: socket_base::message_flags flags, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive(this->impl_.get_implementation(), - buffers, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive(), handler, this, buffers, flags); } /// Receive raw data with the endpoint of the sender. @@ -1027,19 +977,10 @@ public: endpoint_type& sender_endpoint, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive_from( - this->impl_.get_implementation(), buffers, - sender_endpoint, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive_from(), handler, this, buffers, + &sender_endpoint, socket_base::message_flags(0)); } /// Start an asynchronous receive. @@ -1078,20 +1019,85 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive_from( - this->impl_.get_implementation(), buffers, - sender_endpoint, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive_from(), handler, + this, buffers, &sender_endpoint, flags); } + +private: + struct initiate_async_send + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + basic_raw_socket* self, const ConstBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_send_to + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + basic_raw_socket* self, const ConstBufferSequence& buffers, + const endpoint_type& destination, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send_to( + self->impl_.get_implementation(), buffers, destination, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_receive + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + basic_raw_socket* self, const MutableBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_receive_from + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + basic_raw_socket* self, const MutableBufferSequence& buffers, + endpoint_type* sender_endpoint, socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive_from( + self->impl_.get_implementation(), buffers, *sender_endpoint, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; }; } // namespace asio diff --git a/asio/include/asio/basic_seq_packet_socket.hpp b/asio/include/asio/basic_seq_packet_socket.hpp index ed0d8a72..4ee1079b 100644 --- a/asio/include/asio/basic_seq_packet_socket.hpp +++ b/asio/include/asio/basic_seq_packet_socket.hpp @@ -435,18 +435,9 @@ public: socket_base::message_flags flags, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send(this->impl_.get_implementation(), - buffers, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send(), handler, this, buffers, flags); } /// Receive some data on the socket. @@ -613,19 +604,10 @@ public: socket_base::message_flags& out_flags, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive_with_flags( - this->impl_.get_implementation(), buffers, - 0, out_flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive_with_flags(), handler, this, + buffers, socket_base::message_flags(0), &out_flags); } /// Start an asynchronous receive. @@ -678,20 +660,49 @@ public: socket_base::message_flags& out_flags, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive_with_flags( - this->impl_.get_implementation(), buffers, - in_flags, out_flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive_with_flags(), handler, + this, buffers, in_flags, &out_flags); } + +private: + struct initiate_async_send + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + basic_seq_packet_socket* self, const ConstBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_receive_with_flags + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + basic_seq_packet_socket* self, const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags* out_flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive_with_flags( + self->impl_.get_implementation(), buffers, in_flags, *out_flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; }; } // namespace asio diff --git a/asio/include/asio/basic_serial_port.hpp b/asio/include/asio/basic_serial_port.hpp index 9476e039..5cbd1f1c 100644 --- a/asio/include/asio/basic_serial_port.hpp +++ b/asio/include/asio/basic_serial_port.hpp @@ -25,6 +25,7 @@ #include "asio/async_result.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" @@ -685,17 +686,9 @@ public: async_write_some(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_write_some(impl_.get_implementation(), buffers, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_write_some(), handler, this, buffers); } /// Read some data from the serial port. @@ -804,17 +797,9 @@ public: async_read_some(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_read_some(impl_.get_implementation(), buffers, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_read_some(), handler, this, buffers); } private: @@ -822,6 +807,40 @@ private: basic_serial_port(const basic_serial_port&) ASIO_DELETED; basic_serial_port& operator=(const basic_serial_port&) ASIO_DELETED; + struct initiate_async_write_some + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + basic_serial_port* self, const ConstBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_write_some( + self->impl_.get_implementation(), buffers, handler2.value, + self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_read_some + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + basic_serial_port* self, const MutableBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_read_some( + self->impl_.get_implementation(), buffers, handler2.value, + self->impl_.get_implementation_executor()); + } + }; + #if defined(ASIO_HAS_IOCP) detail::io_object_impl impl_; #else diff --git a/asio/include/asio/basic_signal_set.hpp b/asio/include/asio/basic_signal_set.hpp index ca01fee3..f044e575 100644 --- a/asio/include/asio/basic_signal_set.hpp +++ b/asio/include/asio/basic_signal_set.hpp @@ -20,6 +20,7 @@ #include "asio/async_result.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/signal_set_service.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp" @@ -506,17 +507,8 @@ public: void (asio::error_code, int)) async_wait(ASIO_MOVE_ARG(SignalHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a SignalHandler. - ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_wait(impl_.get_implementation(), - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_wait(), handler, this); } private: @@ -524,6 +516,23 @@ private: basic_signal_set(const basic_signal_set&) ASIO_DELETED; basic_signal_set& operator=(const basic_signal_set&) ASIO_DELETED; + struct initiate_async_wait + { + template + void operator()(ASIO_MOVE_ARG(SignalHandler) handler, + basic_signal_set* self) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a SignalHandler. + ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), handler2.value, + self->impl_.get_implementation_executor()); + } + }; + detail::io_object_impl impl_; }; diff --git a/asio/include/asio/basic_socket.hpp b/asio/include/asio/basic_socket.hpp index 4bd6e7e0..42efbda4 100644 --- a/asio/include/asio/basic_socket.hpp +++ b/asio/include/asio/basic_socket.hpp @@ -19,6 +19,7 @@ #include "asio/async_result.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" @@ -944,37 +945,15 @@ public: async_connect(const endpoint_type& peer_endpoint, ASIO_MOVE_ARG(ConnectHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ConnectHandler. - ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; - + asio::error_code open_ec; if (!is_open()) { - asio::error_code ec; const protocol_type protocol = peer_endpoint.protocol(); - impl_.get_service().open(impl_.get_implementation(), protocol, ec); - if (ec) - { - async_completion init(handler); - - asio::post(impl_.get_executor(), - asio::detail::bind_handler( - ASIO_MOVE_CAST(ASIO_HANDLER_TYPE( - ConnectHandler, void (asio::error_code)))( - init.completion_handler), ec)); - - return init.result.get(); - } + impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); } - async_completion init(handler); - - impl_.get_service().async_connect(impl_.get_implementation(), peer_endpoint, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_connect(), handler, this, peer_endpoint, open_ec); } /// Set an option on the socket. @@ -1795,17 +1774,8 @@ public: void (asio::error_code)) async_wait(wait_type w, ASIO_MOVE_ARG(WaitHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WaitHandler. - ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_wait(impl_.get_implementation(), w, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_wait(), handler, this, w); } protected: @@ -1833,6 +1803,50 @@ private: // Disallow copying and assignment. basic_socket(const basic_socket&) ASIO_DELETED; basic_socket& operator=(const basic_socket&) ASIO_DELETED; + + struct initiate_async_connect + { + template + void operator()(ASIO_MOVE_ARG(ConnectHandler) handler, + basic_socket* self, const endpoint_type& peer_endpoint, + const asio::error_code& open_ec) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ConnectHandler. + ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; + + if (open_ec) + { + asio::post(self->impl_.get_executor(), + asio::detail::bind_handler( + ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); + } + else + { + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_connect( + self->impl_.get_implementation(), peer_endpoint, + handler2.value, self->impl_.get_implementation_executor()); + } + } + }; + + struct initiate_async_wait + { + template + void operator()(ASIO_MOVE_ARG(WaitHandler) handler, + basic_socket* self, wait_type w) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), w, handler2.value, + self->impl_.get_implementation_executor()); + } + }; }; } // namespace asio diff --git a/asio/include/asio/basic_socket_acceptor.hpp b/asio/include/asio/basic_socket_acceptor.hpp index 61b7a487..87f24c26 100644 --- a/asio/include/asio/basic_socket_acceptor.hpp +++ b/asio/include/asio/basic_socket_acceptor.hpp @@ -19,6 +19,7 @@ #include "asio/basic_socket.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" @@ -1214,17 +1215,8 @@ public: void (asio::error_code)) async_wait(wait_type w, ASIO_MOVE_ARG(WaitHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WaitHandler. - ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_wait(impl_.get_implementation(), w, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_wait(), handler, this, w); } #if !defined(ASIO_NO_EXTENSIONS) @@ -1340,18 +1332,9 @@ public: is_convertible::value >::type* = 0) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a AcceptHandler. - ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_accept( - impl_.get_implementation(), peer, static_cast(0), - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_accept(), handler, this, + &peer, static_cast(0)); } /// Accept a new connection and obtain the endpoint of the peer @@ -1456,18 +1439,8 @@ public: async_accept(basic_socket& peer, endpoint_type& peer_endpoint, ASIO_MOVE_ARG(AcceptHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a AcceptHandler. - ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_accept( - impl_.get_implementation(), peer, &peer_endpoint, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_accept(), handler, this, &peer, &peer_endpoint); } #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1576,20 +1549,11 @@ public: void (asio::error_code, typename Protocol::socket)) async_accept(ASIO_MOVE_ARG(MoveAcceptHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - - async_completion init(handler); - - impl_.get_service().async_move_accept(impl_.get_implementation(), + return async_initiate( + initiate_async_move_accept(), handler, this, impl_.get_executor(), static_cast(0), - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + static_cast(0)); } /// Accept a new connection. @@ -1805,22 +1769,14 @@ public: is_executor::value >::type* = 0) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket::template rebind_executor< - Executor1>::other) type_check; + typedef typename Protocol::socket::template rebind_executor< + Executor1>::other other_socket_type; - async_completion::other)> init(handler); - - impl_.get_service().async_move_accept( - impl_.get_implementation(), ex, static_cast(0), - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_move_accept(), handler, this, + ex, static_cast(0), + static_cast(0)); } /// Start an asynchronous accept. @@ -1877,22 +1833,14 @@ public: is_convertible::value >::type* = 0) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket::template rebind_executor< - typename ExecutionContext::executor_type>::other) type_check; + typedef typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other other_socket_type; - async_completion::other)> init(handler); - - impl_.get_service().async_move_accept(impl_.get_implementation(), + return async_initiate( + initiate_async_move_accept(), handler, this, context.get_executor(), static_cast(0), - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + static_cast(0)); } /// Accept a new connection. @@ -2017,20 +1965,11 @@ public: async_accept(endpoint_type& peer_endpoint, ASIO_MOVE_ARG(MoveAcceptHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - - async_completion init(handler); - - impl_.get_service().async_move_accept( - impl_.get_implementation(), impl_.get_executor(), &peer_endpoint, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_move_accept(), handler, this, + impl_.get_executor(), &peer_endpoint, + static_cast(0)); } /// Accept a new connection. @@ -2278,22 +2217,14 @@ public: is_executor::value >::type* = 0) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket::template rebind_executor< - Executor1>::other) type_check; + typedef typename Protocol::socket::template rebind_executor< + Executor1>::other other_socket_type; - async_completion::other)> init(handler); - - impl_.get_service().async_move_accept( - impl_.get_implementation(), ex, &peer_endpoint, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_move_accept(), handler, this, + ex, &peer_endpoint, + static_cast(0)); } /// Start an asynchronous accept. @@ -2357,22 +2288,14 @@ public: is_convertible::value >::type* = 0) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket::template rebind_executor< - typename ExecutionContext::executor_type>::other) type_check; + typedef typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other other_socket_type; - async_completion::other)> init(handler); - - impl_.get_service().async_move_accept(impl_.get_implementation(), + return async_initiate( + initiate_async_move_accept(), handler, this, context.get_executor(), &peer_endpoint, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + static_cast(0)); } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -2382,6 +2305,60 @@ private: basic_socket_acceptor& operator=( const basic_socket_acceptor&) ASIO_DELETED; + struct initiate_async_wait + { + template + void operator()(ASIO_MOVE_ARG(WaitHandler) handler, + basic_socket_acceptor* self, wait_type w) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), w, handler2.value, + self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_accept + { + template + void operator()(ASIO_MOVE_ARG(AcceptHandler) handler, + basic_socket_acceptor* self, basic_socket* peer, + endpoint_type* peer_endpoint) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a AcceptHandler. + ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_accept( + self->impl_.get_implementation(), *peer, peer_endpoint, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_move_accept + { + template + void operator()(ASIO_MOVE_ARG(MoveAcceptHandler) handler, + basic_socket_acceptor* self, const Executor1& peer_ex, + endpoint_type* peer_endpoint, Socket*) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a MoveAcceptHandler. + ASIO_MOVE_ACCEPT_HANDLER_CHECK( + MoveAcceptHandler, handler, Socket) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_move_accept( + self->impl_.get_implementation(), peer_ex, peer_endpoint, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + #if defined(ASIO_WINDOWS_RUNTIME) detail::io_object_impl< detail::null_socket_service, Executor> impl_; diff --git a/asio/include/asio/basic_stream_socket.hpp b/asio/include/asio/basic_stream_socket.hpp index 5600fc19..426017b8 100644 --- a/asio/include/asio/basic_stream_socket.hpp +++ b/asio/include/asio/basic_stream_socket.hpp @@ -20,6 +20,7 @@ #include "asio/async_result.hpp" #include "asio/basic_socket.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -468,18 +469,10 @@ public: async_send(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send(this->impl_.get_implementation(), - buffers, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous send. @@ -526,18 +519,9 @@ public: socket_base::message_flags flags, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send(this->impl_.get_implementation(), - buffers, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send(), handler, this, buffers, flags); } /// Receive some data on the socket. @@ -688,18 +672,10 @@ public: async_receive(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive(this->impl_.get_implementation(), - buffers, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive. @@ -748,18 +724,9 @@ public: socket_base::message_flags flags, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive(this->impl_.get_implementation(), - buffers, flags, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive(), handler, this, buffers, flags); } /// Write some data to the socket. @@ -864,18 +831,10 @@ public: async_write_some(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_send(this->impl_.get_implementation(), - buffers, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); } /// Read some data from the socket. @@ -983,19 +942,48 @@ public: async_read_some(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - this->impl_.get_service().async_receive(this->impl_.get_implementation(), - buffers, 0, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); } + +private: + struct initiate_async_send + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + basic_stream_socket* self, const ConstBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_send( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_receive + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + basic_stream_socket* self, const MutableBufferSequence& buffers, + socket_base::message_flags flags) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_receive( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; }; } // namespace asio diff --git a/asio/include/asio/basic_waitable_timer.hpp b/asio/include/asio/basic_waitable_timer.hpp index feca1403..5f450276 100644 --- a/asio/include/asio/basic_waitable_timer.hpp +++ b/asio/include/asio/basic_waitable_timer.hpp @@ -21,6 +21,7 @@ #include "asio/detail/deadline_timer_service.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" #include "asio/executor.hpp" @@ -695,17 +696,8 @@ public: void (asio::error_code)) async_wait(ASIO_MOVE_ARG(WaitHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WaitHandler. - ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_wait(impl_.get_implementation(), - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_wait(), handler, this); } private: @@ -714,6 +706,23 @@ private: basic_waitable_timer& operator=( const basic_waitable_timer&) ASIO_DELETED; + struct initiate_async_wait + { + template + void operator()(ASIO_MOVE_ARG(WaitHandler) handler, + basic_waitable_timer* self) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), handler2.value, + self->impl_.get_implementation_executor()); + } + }; + detail::io_object_impl< detail::deadline_timer_service< detail::chrono_time_traits >, diff --git a/asio/include/asio/detail/config.hpp b/asio/include/asio/detail/config.hpp index b29cf9c7..d8f9fd80 100644 --- a/asio/include/asio/detail/config.hpp +++ b/asio/include/asio/detail/config.hpp @@ -120,11 +120,14 @@ #endif // !defined(ASIO_HAS_MOVE) // If ASIO_MOVE_CAST isn't defined, and move support is available, define -// ASIO_MOVE_ARG and ASIO_MOVE_CAST to take advantage of rvalue -// references and perfect forwarding. +// * ASIO_MOVE_ARG, +// * ASIO_NONDEDUCED_MOVE_ARG, and +// * ASIO_MOVE_CAST +// to take advantage of rvalue references and perfect forwarding. #if defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST) # define ASIO_MOVE_ARG(type) type&& # define ASIO_MOVE_ARG2(type1, type2) type1, type2&& +# define ASIO_NONDEDUCED_MOVE_ARG(type) type& # define ASIO_MOVE_CAST(type) static_cast # define ASIO_MOVE_CAST2(type1, type2) static_cast #endif // defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST) @@ -150,6 +153,7 @@ # else # define ASIO_MOVE_ARG(type) type # endif +# define ASIO_NONDEDUCED_MOVE_ARG(type) const type& # define ASIO_MOVE_CAST(type) static_cast # define ASIO_MOVE_CAST2(type1, type2) static_cast #endif // !defined(ASIO_MOVE_CAST) diff --git a/asio/include/asio/detail/non_const_lvalue.hpp b/asio/include/asio/detail/non_const_lvalue.hpp new file mode 100644 index 00000000..6d9afc88 --- /dev/null +++ b/asio/include/asio/detail/non_const_lvalue.hpp @@ -0,0 +1,54 @@ +// +// detail/non_const_lvalue.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 ASIO_DETAIL_NON_CONST_LVALUE_HPP +#define ASIO_DETAIL_NON_CONST_LVALUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template +struct non_const_lvalue +{ +#if defined(ASIO_HAS_MOVE) + explicit non_const_lvalue(T& t) + : value(static_cast::type>::value, + typename decay::type&, T&&>::type>(t)) + { + } + + typename conditional::type>::value, + typename decay::type&, typename decay::type>::type value; +#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + explicit non_const_lvalue(const typename decay::type& t) + : value(t) + { + } + + typename decay::type value; +#endif // defined(ASIO_HAS_MOVE) +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_NON_CONST_LVALUE_HPP diff --git a/asio/include/asio/detail/work_dispatcher.hpp b/asio/include/asio/detail/work_dispatcher.hpp index 9e02e96d..243b8e48 100644 --- a/asio/include/asio/detail/work_dispatcher.hpp +++ b/asio/include/asio/detail/work_dispatcher.hpp @@ -29,9 +29,10 @@ template class work_dispatcher { public: - work_dispatcher(Handler& handler) + template + explicit work_dispatcher(ASIO_MOVE_ARG(CompletionHandler) handler) : work_((get_associated_executor)(handler)), - handler_(ASIO_MOVE_CAST(Handler)(handler)) + handler_(ASIO_MOVE_CAST(CompletionHandler)(handler)) { } diff --git a/asio/include/asio/impl/buffered_read_stream.hpp b/asio/include/asio/impl/buffered_read_stream.hpp index 898a3b18..41cd04fe 100644 --- a/asio/include/asio/impl/buffered_read_stream.hpp +++ b/asio/include/asio/impl/buffered_read_stream.hpp @@ -21,6 +21,7 @@ #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/push_options.hpp" @@ -137,6 +138,28 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_buffered_fill + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + buffered_stream_storage* storage, Stream* next_layer) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + std::size_t previous_size = storage->size(); + storage->resize(storage->capacity()); + next_layer->async_read_some( + buffer( + storage->data() + previous_size, + storage->size() - previous_size), + buffered_fill_handler::type>( + *storage, previous_size, handler2.value)); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -176,24 +199,9 @@ ASIO_INITFN_RESULT_TYPE(ReadHandler, buffered_read_stream::async_fill( ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - next_layer_.async_read_some( - buffer( - storage_.data() + previous_size, - storage_.size() - previous_size), - detail::buffered_fill_handler( - storage_, previous_size, init.completion_handler)); - - return init.result.get(); + return async_initiate( + detail::initiate_async_buffered_fill(), handler, &storage_, &next_layer_); } template @@ -326,6 +334,38 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_buffered_read_some + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + buffered_stream_storage* storage, Stream* next_layer, + const MutableBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + using asio::buffer_size; + non_const_lvalue handler2(handler); + if (buffer_size(buffers) == 0 || !storage->empty()) + { + next_layer->async_read_some(ASIO_MUTABLE_BUFFER(0, 0), + buffered_read_some_handler::type>( + *storage, buffers, handler2.value)); + } + else + { + initiate_async_buffered_fill()( + buffered_read_some_handler::type>( + *storage, buffers, handler2.value), + storage, next_layer); + } + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -374,31 +414,10 @@ buffered_read_stream::async_read_some( const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - using asio::buffer_size; - if (buffer_size(buffers) == 0 || !storage_.empty()) - { - next_layer_.async_read_some(ASIO_MUTABLE_BUFFER(0, 0), - detail::buffered_read_some_handler< - MutableBufferSequence, ASIO_HANDLER_TYPE( - ReadHandler, void (asio::error_code, std::size_t))>( - storage_, buffers, init.completion_handler)); - } - else - { - this->async_fill(detail::buffered_read_some_handler< - MutableBufferSequence, ASIO_HANDLER_TYPE( - ReadHandler, void (asio::error_code, std::size_t))>( - storage_, buffers, init.completion_handler)); - } - - return init.result.get(); + return async_initiate( + detail::initiate_async_buffered_read_some(), + handler, &storage_, &next_layer_, buffers); } template diff --git a/asio/include/asio/impl/buffered_write_stream.hpp b/asio/include/asio/impl/buffered_write_stream.hpp index 2036a1c5..9d6f8ffd 100644 --- a/asio/include/asio/impl/buffered_write_stream.hpp +++ b/asio/include/asio/impl/buffered_write_stream.hpp @@ -21,6 +21,7 @@ #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/push_options.hpp" @@ -123,6 +124,23 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_buffered_flush + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + buffered_stream_storage* storage, Stream* next_layer) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue handler2(handler); + async_write(*next_layer, buffer(storage->data(), storage->size()), + buffered_flush_handler::type>( + *storage, handler2.value)); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -162,19 +180,10 @@ ASIO_INITFN_RESULT_TYPE(WriteHandler, buffered_write_stream::async_flush( ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - async_write(next_layer_, buffer(storage_.data(), storage_.size()), - detail::buffered_flush_handler( - storage_, init.completion_handler)); - - return init.result.get(); + return async_initiate( + detail::initiate_async_buffered_flush(), + handler, &storage_, &next_layer_); } template @@ -313,6 +322,38 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_buffered_write_some + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + buffered_stream_storage* storage, Stream* next_layer, + const ConstBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + using asio::buffer_size; + non_const_lvalue handler2(handler); + if (buffer_size(buffers) == 0 || storage->size() < storage->capacity()) + { + next_layer->async_write_some(ASIO_CONST_BUFFER(0, 0), + buffered_write_some_handler::type>( + *storage, buffers, handler2.value)); + } + else + { + initiate_async_buffered_flush()( + buffered_write_some_handler::type>( + *storage, buffers, handler2.value), + storage, next_layer); + } + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -361,32 +402,10 @@ buffered_write_stream::async_write_some( const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - using asio::buffer_size; - if (buffer_size(buffers) == 0 - || storage_.size() < storage_.capacity()) - { - next_layer_.async_write_some(ASIO_CONST_BUFFER(0, 0), - detail::buffered_write_some_handler< - ConstBufferSequence, ASIO_HANDLER_TYPE( - WriteHandler, void (asio::error_code, std::size_t))>( - storage_, buffers, init.completion_handler)); - } - else - { - this->async_flush(detail::buffered_write_some_handler< - ConstBufferSequence, ASIO_HANDLER_TYPE( - WriteHandler, void (asio::error_code, std::size_t))>( - storage_, buffers, init.completion_handler)); - } - - return init.result.get(); + return async_initiate( + detail::initiate_async_buffered_write_some(), + handler, &storage_, &next_layer_, buffers); } template diff --git a/asio/include/asio/impl/connect.hpp b/asio/include/asio/impl/connect.hpp index 2380bb18..3ebe732b 100644 --- a/asio/include/asio/impl/connect.hpp +++ b/asio/include/asio/impl/connect.hpp @@ -23,6 +23,7 @@ #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" #include "asio/post.hpp" @@ -446,6 +447,27 @@ namespace detail function, this_handler->handler_); } + struct initiate_async_range_connect + { + template + void operator()(ASIO_MOVE_ARG(RangeConnectHandler) handler, + basic_socket* s, const EndpointSequence& endpoints, + const ConnectCondition& connect_condition) const + { + // If you get an error on the following line it means that your + // handler does not meet the documented type requirements for an + // RangeConnectHandler. + ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler, + handler, typename Protocol::endpoint) type_check; + + non_const_lvalue handler2(handler); + range_connect_op::type>(*s, endpoints, + connect_condition, handler2.value)(asio::error_code(), 1); + } + }; + template class iterator_connect_op : base_from_connect_condition @@ -593,6 +615,27 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_iterator_connect + { + template + void operator()(ASIO_MOVE_ARG(IteratorConnectHandler) handler, + basic_socket* s, Iterator begin, + Iterator end, const ConnectCondition& connect_condition) const + { + // If you get an error on the following line it means that your + // handler does not meet the documented type requirements for an + // IteratorConnectHandler. + ASIO_ITERATOR_CONNECT_HANDLER_CHECK( + IteratorConnectHandler, handler, Iterator) type_check; + + non_const_lvalue handler2(handler); + iterator_connect_op::type>(*s, begin, end, + connect_condition, handler2.value)(asio::error_code(), 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -689,23 +732,10 @@ async_connect(basic_socket& s, typename enable_if::value>::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a RangeConnectHandler. - ASIO_RANGE_CONNECT_HANDLER_CHECK( - RangeConnectHandler, handler, typename Protocol::endpoint) type_check; - - async_completion - init(handler); - - detail::range_connect_op(s, - endpoints, detail::default_connect_condition(), - init.completion_handler)(asio::error_code(), 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_range_connect(), handler, + &s, endpoints, detail::default_connect_condition()); } #if !defined(ASIO_NO_DEPRECATED) @@ -717,21 +747,10 @@ async_connect(basic_socket& s, Iterator begin, ASIO_MOVE_ARG(IteratorConnectHandler) handler, typename enable_if::value>::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a IteratorConnectHandler. - ASIO_ITERATOR_CONNECT_HANDLER_CHECK( - IteratorConnectHandler, handler, Iterator) type_check; - - async_completion init(handler); - - detail::iterator_connect_op(s, - begin, Iterator(), detail::default_connect_condition(), - init.completion_handler)(asio::error_code(), 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_iterator_connect(), handler, + &s, begin, Iterator(), detail::default_connect_condition()); } #endif // !defined(ASIO_NO_DEPRECATED) @@ -742,21 +761,10 @@ inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, async_connect(basic_socket& s, Iterator begin, Iterator end, ASIO_MOVE_ARG(IteratorConnectHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a IteratorConnectHandler. - ASIO_ITERATOR_CONNECT_HANDLER_CHECK( - IteratorConnectHandler, handler, Iterator) type_check; - - async_completion init(handler); - - detail::iterator_connect_op(s, - begin, end, detail::default_connect_condition(), - init.completion_handler)(asio::error_code(), 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_iterator_connect(), handler, + &s, begin, end, detail::default_connect_condition()); } template & s, typename enable_if::value>::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a RangeConnectHandler. - ASIO_RANGE_CONNECT_HANDLER_CHECK( - RangeConnectHandler, handler, typename Protocol::endpoint) type_check; - - async_completion - init(handler); - - detail::range_connect_op(s, - endpoints, connect_condition, init.completion_handler)( - asio::error_code(), 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_range_connect(), + handler, &s, endpoints, connect_condition); } #if !defined(ASIO_NO_DEPRECATED) @@ -797,21 +793,10 @@ async_connect(basic_socket& s, Iterator begin, ASIO_MOVE_ARG(IteratorConnectHandler) handler, typename enable_if::value>::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a IteratorConnectHandler. - ASIO_ITERATOR_CONNECT_HANDLER_CHECK( - IteratorConnectHandler, handler, Iterator) type_check; - - async_completion init(handler); - - detail::iterator_connect_op(s, - begin, Iterator(), connect_condition, init.completion_handler)( - asio::error_code(), 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_iterator_connect(), + handler, &s, begin, Iterator(), connect_condition); } #endif // !defined(ASIO_NO_DEPRECATED) @@ -823,21 +808,10 @@ async_connect(basic_socket& s, Iterator begin, Iterator end, ConnectCondition connect_condition, ASIO_MOVE_ARG(IteratorConnectHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a IteratorConnectHandler. - ASIO_ITERATOR_CONNECT_HANDLER_CHECK( - IteratorConnectHandler, handler, Iterator) type_check; - - async_completion init(handler); - - detail::iterator_connect_op(s, - begin, end, connect_condition, init.completion_handler)( - asio::error_code(), 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_iterator_connect(), + handler, &s, begin, end, connect_condition); } } // namespace asio diff --git a/asio/include/asio/impl/defer.hpp b/asio/include/asio/impl/defer.hpp index e8ecd942..bfcf56c7 100644 --- a/asio/include/asio/impl/defer.hpp +++ b/asio/include/asio/impl/defer.hpp @@ -23,24 +23,46 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +struct initiate_defer +{ + template + void operator()(ASIO_MOVE_ARG(CompletionHandler) handler) const + { + typedef typename decay::type DecayedHandler; + + typename associated_executor::type ex( + (get_associated_executor)(handler)); + + typename associated_allocator::type alloc( + (get_associated_allocator)(handler)); + + ex.defer(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc); + } + + template + void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, + ASIO_MOVE_ARG(Executor) ex) const + { + typedef typename decay::type DecayedHandler; + + typename associated_allocator::type alloc( + (get_associated_allocator)(handler)); + + ex.defer(detail::work_dispatcher( + ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); + } +}; + +} // namespace detail template ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer( ASIO_MOVE_ARG(CompletionToken) token) { - typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion init(token); - - typename associated_executor::type ex( - (get_associated_executor)(init.completion_handler)); - - typename associated_allocator::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.defer(ASIO_MOVE_CAST(handler)(init.completion_handler), alloc); - - return init.result.get(); + return async_initiate( + detail::initiate_defer(), token); } template @@ -48,16 +70,8 @@ ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer( const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token, typename enable_if::value>::type*) { - typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion init(token); - - typename associated_allocator::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.defer(detail::work_dispatcher(init.completion_handler), alloc); - - return init.result.get(); + return async_initiate( + detail::initiate_defer(), token, ex); } template diff --git a/asio/include/asio/impl/dispatch.hpp b/asio/include/asio/impl/dispatch.hpp index 6b2d7e1c..ee3d33f7 100644 --- a/asio/include/asio/impl/dispatch.hpp +++ b/asio/include/asio/impl/dispatch.hpp @@ -23,24 +23,46 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +struct initiate_dispatch +{ + template + void operator()(ASIO_MOVE_ARG(CompletionHandler) handler) const + { + typedef typename decay::type DecayedHandler; + + typename associated_executor::type ex( + (get_associated_executor)(handler)); + + typename associated_allocator::type alloc( + (get_associated_allocator)(handler)); + + ex.dispatch(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc); + } + + template + void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, + ASIO_MOVE_ARG(Executor) ex) const + { + typedef typename decay::type DecayedHandler; + + typename associated_allocator::type alloc( + (get_associated_allocator)(handler)); + + ex.dispatch(detail::work_dispatcher( + ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); + } +}; + +} // namespace detail template ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch( ASIO_MOVE_ARG(CompletionToken) token) { - typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion init(token); - - typename associated_executor::type ex( - (get_associated_executor)(init.completion_handler)); - - typename associated_allocator::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.dispatch(ASIO_MOVE_CAST(handler)(init.completion_handler), alloc); - - return init.result.get(); + return async_initiate( + detail::initiate_dispatch(), token); } template @@ -48,17 +70,8 @@ ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch( const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token, typename enable_if::value>::type*) { - typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion init(token); - - typename associated_allocator::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.dispatch(detail::work_dispatcher( - init.completion_handler), alloc); - - return init.result.get(); + return async_initiate( + detail::initiate_dispatch(), token, ex); } template diff --git a/asio/include/asio/impl/io_context.hpp b/asio/include/asio/impl/io_context.hpp index 7cd6664d..8d2f624c 100644 --- a/asio/include/asio/impl/io_context.hpp +++ b/asio/include/asio/impl/io_context.hpp @@ -19,6 +19,7 @@ #include "asio/detail/executor_op.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/recycling_allocator.hpp" #include "asio/detail/service_registry.hpp" #include "asio/detail/throw_error.hpp" @@ -127,72 +128,87 @@ inline void io_context::reset() restart(); } +struct io_context::initiate_dispatch +{ + template + void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler, + io_context* self) const + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a LegacyCompletionHandler. + ASIO_LEGACY_COMPLETION_HANDLER_CHECK( + LegacyCompletionHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + if (self->impl_.can_dispatch()) + { + detail::fenced_block b(detail::fenced_block::full); + asio_handler_invoke_helpers::invoke( + handler2.value, handler2.value); + } + else + { + // Allocate and construct an operation to wrap the handler. + typedef detail::completion_handler< + typename decay::type> op; + typename op::ptr p = { detail::addressof(handler2.value), + op::ptr::allocate(handler2.value), 0 }; + p.p = new (p.v) op(handler2.value); + + ASIO_HANDLER_CREATION((*self, *p.p, + "io_context", this, 0, "dispatch")); + + self->impl_.do_dispatch(p.p); + p.v = p.p = 0; + } + } +}; + template ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ()) io_context::dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a LegacyCompletionHandler. - ASIO_LEGACY_COMPLETION_HANDLER_CHECK( - LegacyCompletionHandler, handler) type_check; + return async_initiate( + initiate_dispatch(), handler, this); +} - async_completion init(handler); +struct io_context::initiate_post +{ + template + void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler, + io_context* self) const + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a LegacyCompletionHandler. + ASIO_LEGACY_COMPLETION_HANDLER_CHECK( + LegacyCompletionHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler2.value); - if (impl_.can_dispatch()) - { - detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke( - init.completion_handler, init.completion_handler); - } - else - { // Allocate and construct an operation to wrap the handler. typedef detail::completion_handler< - typename async_completion::completion_handler_type> op; - typename op::ptr p = { detail::addressof(init.completion_handler), - op::ptr::allocate(init.completion_handler), 0 }; - p.p = new (p.v) op(init.completion_handler); + typename decay::type> op; + typename op::ptr p = { detail::addressof(handler2.value), + op::ptr::allocate(handler2.value), 0 }; + p.p = new (p.v) op(handler2.value); - ASIO_HANDLER_CREATION((*this, *p.p, - "io_context", this, 0, "dispatch")); + ASIO_HANDLER_CREATION((*self, *p.p, + "io_context", this, 0, "post")); - impl_.do_dispatch(p.p); + self->impl_.post_immediate_completion(p.p, is_continuation); p.v = p.p = 0; } - - return init.result.get(); -} +}; template ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ()) io_context::post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a LegacyCompletionHandler. - ASIO_LEGACY_COMPLETION_HANDLER_CHECK( - LegacyCompletionHandler, handler) type_check; - - async_completion init(handler); - - bool is_continuation = - asio_handler_cont_helpers::is_continuation(init.completion_handler); - - // Allocate and construct an operation to wrap the handler. - typedef detail::completion_handler< - typename async_completion::completion_handler_type> op; - typename op::ptr p = { detail::addressof(init.completion_handler), - op::ptr::allocate(init.completion_handler), 0 }; - p.p = new (p.v) op(init.completion_handler); - - ASIO_HANDLER_CREATION((*this, *p.p, - "io_context", this, 0, "post")); - - impl_.post_immediate_completion(p.p, is_continuation); - p.v = p.p = 0; - - return init.result.get(); + return async_initiate( + initiate_post(), handler, this); } template diff --git a/asio/include/asio/impl/post.hpp b/asio/include/asio/impl/post.hpp index cc7913f4..04ab1184 100644 --- a/asio/include/asio/impl/post.hpp +++ b/asio/include/asio/impl/post.hpp @@ -23,24 +23,46 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +struct initiate_post +{ + template + void operator()(ASIO_MOVE_ARG(CompletionHandler) handler) const + { + typedef typename decay::type DecayedHandler; + + typename associated_executor::type ex( + (get_associated_executor)(handler)); + + typename associated_allocator::type alloc( + (get_associated_allocator)(handler)); + + ex.post(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc); + } + + template + void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, + ASIO_MOVE_ARG(Executor) ex) const + { + typedef typename decay::type DecayedHandler; + + typename associated_allocator::type alloc( + (get_associated_allocator)(handler)); + + ex.post(detail::work_dispatcher( + ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); + } +}; + +} // namespace detail template ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post( ASIO_MOVE_ARG(CompletionToken) token) { - typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion init(token); - - typename associated_executor::type ex( - (get_associated_executor)(init.completion_handler)); - - typename associated_allocator::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.post(ASIO_MOVE_CAST(handler)(init.completion_handler), alloc); - - return init.result.get(); + return async_initiate( + detail::initiate_post(), token); } template @@ -48,16 +70,8 @@ ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post( const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token, typename enable_if::value>::type*) { - typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion init(token); - - typename associated_allocator::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.post(detail::work_dispatcher(init.completion_handler), alloc); - - return init.result.get(); + return async_initiate( + detail::initiate_post(), token, ex); } template diff --git a/asio/include/asio/impl/read.hpp b/asio/include/asio/impl/read.hpp index 9b049369..e18c32a4 100644 --- a/asio/include/asio/impl/read.hpp +++ b/asio/include/asio/impl/read.hpp @@ -29,6 +29,7 @@ #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -361,6 +362,25 @@ namespace detail stream, buffers, completion_condition, handler)( asio::error_code(), 0, 1); } + + struct initiate_async_read_buffer_sequence + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + start_read_buffer_sequence_op(*s, buffers, + asio::buffer_sequence_begin(buffers), + completion_condition, handler2.value); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -416,18 +436,10 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, is_mutable_buffer_sequence::value >::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::start_read_buffer_sequence_op(s, buffers, - asio::buffer_sequence_begin(buffers), completion_condition, - init.completion_handler); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_buffer_sequence(), + handler, &s, buffers, completion_condition); } template ::value >::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::start_read_buffer_sequence_op(s, buffers, - asio::buffer_sequence_begin(buffers), transfer_all(), - init.completion_handler); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_buffer_sequence(), + handler, &s, buffers, transfer_all()); } namespace detail @@ -592,6 +596,27 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_dynbuf + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, ASIO_MOVE_ARG(DynamicBuffer) buffers, + CompletionCondition completion_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + read_dynbuf_op::type, + CompletionCondition, typename decay::type>( + *s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), + completion_condition, handler2.value)( + asio::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -666,18 +691,10 @@ async_read(AsyncReadStream& s, // not meet the documented type requirements for a ReadHandler. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - async_completion init(handler); - - detail::read_dynbuf_op::type, - CompletionCondition, ASIO_HANDLER_TYPE( - ReadHandler, void (asio::error_code, std::size_t))>( - s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), - completion_condition, init.completion_handler)( - asio::error_code(), 0, 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_dynbuf(), handler, &s, + ASIO_MOVE_CAST(DynamicBuffer)(buffers), completion_condition); } #if !defined(ASIO_NO_EXTENSIONS) diff --git a/asio/include/asio/impl/read_at.hpp b/asio/include/asio/impl/read_at.hpp index e12a1bc6..243da632 100644 --- a/asio/include/asio/impl/read_at.hpp +++ b/asio/include/asio/impl/read_at.hpp @@ -29,6 +29,7 @@ #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -313,6 +314,26 @@ namespace detail d, offset, buffers, completion_condition, handler)( asio::error_code(), 0, 1); } + + struct initiate_async_read_at_buffer_sequence + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + AsyncRandomAccessReadDevice* d, uint64_t offset, + const MutableBufferSequence& buffers, + CompletionCondition completion_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + start_read_at_buffer_sequence_op(*d, offset, buffers, + asio::buffer_sequence_begin(buffers), + completion_condition, handler2.value); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -368,18 +389,10 @@ async_read_at(AsyncRandomAccessReadDevice& d, CompletionCondition completion_condition, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::start_read_at_buffer_sequence_op(d, offset, buffers, - asio::buffer_sequence_begin(buffers), completion_condition, - init.completion_handler); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_at_buffer_sequence(), + handler, &d, offset, buffers, completion_condition); } template init(handler); - - detail::start_read_at_buffer_sequence_op(d, offset, buffers, - asio::buffer_sequence_begin(buffers), transfer_all(), - init.completion_handler); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_at_buffer_sequence(), + handler, &d, offset, buffers, transfer_all()); } #if !defined(ASIO_NO_EXTENSIONS) @@ -539,6 +544,27 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_at_streambuf + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + AsyncRandomAccessReadDevice* d, uint64_t offset, + basic_streambuf* b, + CompletionCondition completion_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + read_at_streambuf_op::type>( + *d, offset, *b, completion_condition, handler2.value)( + asio::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -590,20 +616,10 @@ async_read_at(AsyncRandomAccessReadDevice& d, CompletionCondition completion_condition, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::read_at_streambuf_op( - d, offset, b, completion_condition, init.completion_handler)( - asio::error_code(), 0, 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_at_streambuf(), + handler, &d, offset, &b, completion_condition); } template & b, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::read_at_streambuf_op( - d, offset, b, transfer_all(), init.completion_handler)( - asio::error_code(), 0, 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_at_streambuf(), + handler, &d, offset, &b, transfer_all()); } #endif // !defined(ASIO_NO_IOSTREAM) diff --git a/asio/include/asio/impl/read_until.hpp b/asio/include/asio/impl/read_until.hpp index a4e5e167..cde6152b 100644 --- a/asio/include/asio/impl/read_until.hpp +++ b/asio/include/asio/impl/read_until.hpp @@ -29,6 +29,7 @@ #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/limits.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/push_options.hpp" @@ -599,6 +600,26 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_until_delim + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, ASIO_MOVE_ARG(DynamicBuffer) buffers, + char delim) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + read_until_delim_op::type, typename decay::type>( + *s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), + delim, handler2.value)(asio::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -649,21 +670,10 @@ async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer) buffers, char delim, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::read_until_delim_op::type, - ASIO_HANDLER_TYPE(ReadHandler, - void (asio::error_code, std::size_t))>( - s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), - delim, init.completion_handler)(asio::error_code(), 0, 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_until_delim(), handler, + &s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim); } namespace detail @@ -852,6 +862,26 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_until_delim_string + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, ASIO_MOVE_ARG(DynamicBuffer) buffers, + const std::string& delim) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + read_until_delim_string_op::type, typename decay::type>( + *s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), + delim, handler2.value)(asio::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -903,22 +933,11 @@ async_read_until(AsyncReadStream& s, ASIO_STRING_VIEW_PARAM delim, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::read_until_delim_string_op::type, - ASIO_HANDLER_TYPE(ReadHandler, - void (asio::error_code, std::size_t))>( - s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), - static_cast(delim), - init.completion_handler)(asio::error_code(), 0, 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_until_delim_string(), + handler, &s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), + static_cast(delim)); } #if !defined(ASIO_NO_EXTENSIONS) @@ -1113,6 +1132,26 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_until_expr + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, ASIO_MOVE_ARG(DynamicBuffer) buffers, + const RegEx& expr) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + read_until_expr_op::type, + RegEx, typename decay::type>( + *s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), + expr, handler2.value)(asio::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -1164,21 +1203,10 @@ async_read_until(AsyncReadStream& s, const boost::regex& expr, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::read_until_expr_op::type, - boost::regex, ASIO_HANDLER_TYPE(ReadHandler, - void (asio::error_code, std::size_t))>( - s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), - expr, init.completion_handler)(asio::error_code(), 0, 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_until_expr(), handler, + &s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), expr); } #endif // defined(ASIO_HAS_BOOST_REGEX) @@ -1370,6 +1398,26 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_until_match + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, ASIO_MOVE_ARG(DynamicBuffer) buffers, + MatchCondition match_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue handler2(handler); + read_until_match_op::type, + MatchCondition, typename decay::type>( + *s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), + match_condition, handler2.value)(asio::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -1421,22 +1469,10 @@ async_read_until(AsyncReadStream& s, MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler, typename enable_if::value>::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion init(handler); - - detail::read_until_match_op::type, - MatchCondition, ASIO_HANDLER_TYPE(ReadHandler, - void (asio::error_code, std::size_t))>( - s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), - match_condition, init.completion_handler)( - asio::error_code(), 0, 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_read_until_match(), handler, + &s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), match_condition); } #if !defined(ASIO_NO_IOSTREAM) diff --git a/asio/include/asio/impl/write.hpp b/asio/include/asio/impl/write.hpp index 5003d3ae..8df0c4ff 100644 --- a/asio/include/asio/impl/write.hpp +++ b/asio/include/asio/impl/write.hpp @@ -28,6 +28,7 @@ #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/push_options.hpp" @@ -345,6 +346,24 @@ namespace detail asio::error_code(), 0, 1); } + struct initiate_async_write_buffer_sequence + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + AsyncWriteStream* s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue handler2(handler); + start_write_buffer_sequence_op(*s, buffers, + asio::buffer_sequence_begin(buffers), + completion_condition, handler2.value); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -400,18 +419,10 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, is_const_buffer_sequence::value >::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - detail::start_write_buffer_sequence_op(s, buffers, - asio::buffer_sequence_begin(buffers), completion_condition, - init.completion_handler); - - return init.result.get(); + return async_initiate( + detail::initiate_async_write_buffer_sequence(), + handler, &s, buffers, completion_condition); } template ::value >::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - detail::start_write_buffer_sequence_op(s, buffers, - asio::buffer_sequence_begin(buffers), transfer_all(), - init.completion_handler); - - return init.result.get(); + return async_initiate( + detail::initiate_async_write_buffer_sequence(), + handler, &s, buffers, transfer_all()); } namespace detail @@ -549,6 +552,27 @@ namespace detail asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_write_dynbuf + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + AsyncWriteStream* s, ASIO_MOVE_ARG(DynamicBuffer) buffers, + CompletionCondition completion_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue handler2(handler); + write_dynbuf_op::type, + CompletionCondition, typename decay::type>( + *s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), + completion_condition, handler2.value)( + asio::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -619,22 +643,10 @@ async_write(AsyncWriteStream& s, is_dynamic_buffer::type>::value >::type*) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - detail::write_dynbuf_op::type, - CompletionCondition, ASIO_HANDLER_TYPE( - WriteHandler, void (asio::error_code, std::size_t))>( - s, ASIO_MOVE_CAST(DynamicBuffer)(buffers), - completion_condition, init.completion_handler)( - asio::error_code(), 0, 1); - - return init.result.get(); + return async_initiate( + detail::initiate_async_write_dynbuf(), handler, &s, + ASIO_MOVE_CAST(DynamicBuffer)(buffers), completion_condition); } #if !defined(ASIO_NO_EXTENSIONS) diff --git a/asio/include/asio/impl/write_at.hpp b/asio/include/asio/impl/write_at.hpp index 4845df90..dd70d018 100644 --- a/asio/include/asio/impl/write_at.hpp +++ b/asio/include/asio/impl/write_at.hpp @@ -28,6 +28,7 @@ #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/push_options.hpp" @@ -298,6 +299,26 @@ namespace detail d, offset, buffers, completion_condition, handler)( asio::error_code(), 0, 1); } + + struct initiate_async_write_at_buffer_sequence + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + AsyncRandomAccessWriteDevice* d, uint64_t offset, + const ConstBufferSequence& buffers, + CompletionCondition completion_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue handler2(handler); + start_write_at_buffer_sequence_op(*d, offset, buffers, + asio::buffer_sequence_begin(buffers), + completion_condition, handler2.value); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -353,18 +374,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d, CompletionCondition completion_condition, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - detail::start_write_at_buffer_sequence_op(d, offset, buffers, - asio::buffer_sequence_begin(buffers), completion_condition, - init.completion_handler); - - return init.result.get(); + return async_initiate( + detail::initiate_async_write_at_buffer_sequence(), + handler, &d, offset, buffers, completion_condition); } template init(handler); - - detail::start_write_at_buffer_sequence_op(d, offset, buffers, - asio::buffer_sequence_begin(buffers), transfer_all(), - init.completion_handler); - - return init.result.get(); + return async_initiate( + detail::initiate_async_write_at_buffer_sequence(), + handler, &d, offset, buffers, transfer_all()); } #if !defined(ASIO_NO_EXTENSIONS) @@ -472,13 +477,25 @@ namespace detail function, this_handler->handler_); } - template - inline write_at_streambuf_op - make_write_at_streambuf_op( - asio::basic_streambuf& b, WriteHandler handler) + struct initiate_async_write_at_streambuf { - return write_at_streambuf_op(b, handler); - } + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + AsyncRandomAccessWriteDevice* d, uint64_t offset, + basic_streambuf* b, + CompletionCondition completion_condition) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue handler2(handler); + async_write_at(*d, offset, b->data(), completion_condition, + write_at_streambuf_op::type>( + *b, handler2.value)); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -524,19 +541,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d, CompletionCondition completion_condition, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - async_write_at(d, offset, b.data(), completion_condition, - detail::write_at_streambuf_op( - b, init.completion_handler)); - - return init.result.get(); + return async_initiate( + detail::initiate_async_write_at_streambuf(), + handler, &d, offset, &b, completion_condition); } template & b, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion init(handler); - - async_write_at(d, offset, b.data(), transfer_all(), - detail::write_at_streambuf_op( - b, init.completion_handler)); - - return init.result.get(); + return async_initiate( + detail::initiate_async_write_at_streambuf(), + handler, &d, offset, &b, transfer_all()); } #endif // !defined(ASIO_NO_IOSTREAM) diff --git a/asio/include/asio/io_context.hpp b/asio/include/asio/io_context.hpp index c4b8db77..f0a82e15 100644 --- a/asio/include/asio/io_context.hpp +++ b/asio/include/asio/io_context.hpp @@ -594,6 +594,11 @@ public: #endif // !defined(ASIO_NO_DEPRECATED) private: +#if !defined(ASIO_NO_DEPRECATED) + struct initiate_dispatch; + struct initiate_post; +#endif // !defined(ASIO_NO_DEPRECATED) + // Helper function to add the implementation. ASIO_DECL impl_type& add_impl(impl_type* impl); diff --git a/asio/include/asio/io_context_strand.hpp b/asio/include/asio/io_context_strand.hpp index 81196e8c..16c39d54 100644 --- a/asio/include/asio/io_context_strand.hpp +++ b/asio/include/asio/io_context_strand.hpp @@ -185,16 +185,8 @@ public: ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ()) dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a LegacyCompletionHandler. - ASIO_LEGACY_COMPLETION_HANDLER_CHECK( - LegacyCompletionHandler, handler) type_check; - - async_completion init(handler); - - service_.dispatch(impl_, init.completion_handler); - - return init.result.get(); + return async_initiate( + initiate_dispatch(), handler, this); } #endif // !defined(ASIO_NO_DEPRECATED) @@ -240,16 +232,8 @@ public: ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ()) post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a LegacyCompletionHandler. - ASIO_LEGACY_COMPLETION_HANDLER_CHECK( - LegacyCompletionHandler, handler) type_check; - - async_completion init(handler); - - service_.post(impl_, init.completion_handler); - - return init.result.get(); + return async_initiate( + initiate_post(), handler, this); } #endif // !defined(ASIO_NO_DEPRECATED) @@ -341,6 +325,42 @@ public: } private: +#if !defined(ASIO_NO_DEPRECATED) + struct initiate_dispatch + { + template + void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler, + strand* self) const + { + // If you get an error on the following line it means that your + // handler does not meet the documented type requirements for a + // LegacyCompletionHandler. + ASIO_LEGACY_COMPLETION_HANDLER_CHECK( + LegacyCompletionHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->service_.dispatch(self->impl_, handler2.value); + } + }; + + struct initiate_post + { + template + void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler, + strand* self) const + { + // If you get an error on the following line it means that your + // handler does not meet the documented type requirements for a + // LegacyCompletionHandler. + ASIO_LEGACY_COMPLETION_HANDLER_CHECK( + LegacyCompletionHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->service_.post(self->impl_, handler2.value); + } + }; +#endif // !defined(ASIO_NO_DEPRECATED) + asio::detail::strand_service& service_; mutable asio::detail::strand_service::implementation_type impl_; }; diff --git a/asio/include/asio/ip/basic_resolver.hpp b/asio/include/asio/ip/basic_resolver.hpp index 9209844b..0e4c3c40 100644 --- a/asio/include/asio/ip/basic_resolver.hpp +++ b/asio/include/asio/ip/basic_resolver.hpp @@ -20,6 +20,7 @@ #include "asio/async_result.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/string_view.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -613,18 +614,9 @@ public: async_resolve(const query& q, ASIO_MOVE_ARG(ResolveHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ResolveHandler. - ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, results_type) type_check; - - asio::async_completion init(handler); - - impl_.get_service().async_resolve(impl_.get_implementation(), q, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return asio::async_initiate( + initiate_async_resolve(), handler, this, q); } #endif // !defined(ASIO_NO_DEPRECATED) @@ -735,21 +727,12 @@ public: resolver_base::flags resolve_flags, ASIO_MOVE_ARG(ResolveHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ResolveHandler. - ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, results_type) type_check; - basic_resolver_query q(static_cast(host), static_cast(service), resolve_flags); - asio::async_completion init(handler); - - impl_.get_service().async_resolve(impl_.get_implementation(), q, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return asio::async_initiate( + initiate_async_resolve(), handler, this, q); } /// Asynchronously perform forward resolution of a query to a list of entries. @@ -865,22 +848,13 @@ public: resolver_base::flags resolve_flags, ASIO_MOVE_ARG(ResolveHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ResolveHandler. - ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, results_type) type_check; - basic_resolver_query q( protocol, static_cast(host), static_cast(service), resolve_flags); - asio::async_completion init(handler); - - impl_.get_service().async_resolve(impl_.get_implementation(), q, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return asio::async_initiate( + initiate_async_resolve(), handler, this, q); } /// Perform reverse resolution of an endpoint to a list of entries. @@ -955,18 +929,9 @@ public: async_resolve(const endpoint_type& e, ASIO_MOVE_ARG(ResolveHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ResolveHandler. - ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, results_type) type_check; - - asio::async_completion init(handler); - - impl_.get_service().async_resolve(impl_.get_implementation(), e, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return asio::async_initiate( + initiate_async_resolve(), handler, this, e); } private: @@ -974,6 +939,24 @@ private: basic_resolver(const basic_resolver&) ASIO_DELETED; basic_resolver& operator=(const basic_resolver&) ASIO_DELETED; + struct initiate_async_resolve + { + template + void operator()(ASIO_MOVE_ARG(ResolveHandler) handler, + basic_resolver* self, const Query& q) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ResolveHandler. + ASIO_RESOLVE_HANDLER_CHECK( + ResolveHandler, handler, results_type) type_check; + + asio::detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_resolve( + self->impl_.get_implementation(), q, handler2.value, + self->impl_.get_implementation_executor()); + } + }; + # if defined(ASIO_WINDOWS_RUNTIME) asio::detail::io_object_impl< asio::detail::winrt_resolver_service, diff --git a/asio/include/asio/posix/basic_descriptor.hpp b/asio/include/asio/posix/basic_descriptor.hpp index b31cf1a7..030bf5ec 100644 --- a/asio/include/asio/posix/basic_descriptor.hpp +++ b/asio/include/asio/posix/basic_descriptor.hpp @@ -23,6 +23,7 @@ #include "asio/async_result.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/reactive_descriptor_service.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -618,17 +619,8 @@ public: void (asio::error_code)) async_wait(wait_type w, ASIO_MOVE_ARG(WaitHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WaitHandler. - ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - - async_completion init(handler); - - impl_.get_service().async_wait(impl_.get_implementation(), w, - init.completion_handler, impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_wait(), handler, this, w); } protected: @@ -648,6 +640,23 @@ private: // Disallow copying and assignment. basic_descriptor(const basic_descriptor&) ASIO_DELETED; basic_descriptor& operator=(const basic_descriptor&) ASIO_DELETED; + + struct initiate_async_wait + { + template + void operator()(ASIO_MOVE_ARG(WaitHandler) handler, + basic_descriptor* self, wait_type w) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), w, handler2.value, + self->impl_.get_implementation_executor()); + } + }; }; } // namespace posix diff --git a/asio/include/asio/posix/basic_stream_descriptor.hpp b/asio/include/asio/posix/basic_stream_descriptor.hpp index 452d5ab6..3f2c2478 100644 --- a/asio/include/asio/posix/basic_stream_descriptor.hpp +++ b/asio/include/asio/posix/basic_stream_descriptor.hpp @@ -262,19 +262,9 @@ public: async_write_some(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - asio::async_completion init(handler); - - this->impl_.get_service().async_write_some( - this->impl_.get_implementation(), - buffers, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_write_some(), handler, this, buffers); } /// Read some data from the descriptor. @@ -382,20 +372,47 @@ public: async_read_some(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - asio::async_completion init(handler); - - this->impl_.get_service().async_read_some( - this->impl_.get_implementation(), - buffers, init.completion_handler, - this->impl_.get_implementation_executor()); - - return init.result.get(); + return async_initiate( + initiate_async_read_some(), handler, this, buffers); } + +private: + struct initiate_async_write_some + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + basic_stream_descriptor* self, + const ConstBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_write_some( + self->impl_.get_implementation(), buffers, handler2.value, + self->impl_.get_implementation_executor()); + } + }; + + struct initiate_async_read_some + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + basic_stream_descriptor* self, + const MutableBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue handler2(handler); + self->impl_.get_service().async_read_some( + self->impl_.get_implementation(), buffers, handler2.value, + self->impl_.get_implementation_executor()); + } + }; }; } // namespace posix diff --git a/asio/include/asio/ssl/stream.hpp b/asio/include/asio/ssl/stream.hpp index 010f822b..a938899f 100644 --- a/asio/include/asio/ssl/stream.hpp +++ b/asio/include/asio/ssl/stream.hpp @@ -20,6 +20,7 @@ #include "asio/async_result.hpp" #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/noncopyable.hpp" #include "asio/detail/type_traits.hpp" #include "asio/ssl/context.hpp" @@ -435,17 +436,9 @@ public: async_handshake(handshake_type type, ASIO_MOVE_ARG(HandshakeHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a HandshakeHandler. - ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check; - - asio::async_completion init(handler); - - detail::async_io(next_layer_, core_, - detail::handshake_op(type), init.completion_handler); - - return init.result.get(); + return async_initiate( + initiate_async_handshake(), handler, this, type); } /// Start an asynchronous SSL handshake. @@ -475,19 +468,9 @@ public: async_handshake(handshake_type type, const ConstBufferSequence& buffers, ASIO_MOVE_ARG(BufferedHandshakeHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a BufferedHandshakeHandler. - ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( - BufferedHandshakeHandler, handler) type_check; - - asio::async_completion init(handler); - - detail::async_io(next_layer_, core_, - detail::buffered_handshake_op(type, buffers), - init.completion_handler); - - return init.result.get(); + return async_initiate( + initiate_async_buffered_handshake(), handler, this, type, buffers); } /// Shut down SSL on the stream. @@ -534,17 +517,9 @@ public: void (asio::error_code)) async_shutdown(ASIO_MOVE_ARG(ShutdownHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ShutdownHandler. - ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, handler) type_check; - - asio::async_completion init(handler); - - detail::async_io(next_layer_, core_, detail::shutdown_op(), - init.completion_handler); - - return init.result.get(); + return async_initiate( + initiate_async_shutdown(), handler, this); } /// Write some data to the stream. @@ -625,18 +600,9 @@ public: async_write_some(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WriteHandler. - ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - asio::async_completion init(handler); - - detail::async_io(next_layer_, core_, - detail::write_op(buffers), - init.completion_handler); - - return init.result.get(); + return async_initiate( + initiate_async_write_some(), handler, this, buffers); } /// Read some data from the stream. @@ -717,21 +683,97 @@ public: async_read_some(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a ReadHandler. - ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - asio::async_completion init(handler); - - detail::async_io(next_layer_, core_, - detail::read_op(buffers), - init.completion_handler); - - return init.result.get(); + return async_initiate( + initiate_async_read_some(), handler, this, buffers); } private: + struct initiate_async_handshake + { + template + void operator()(ASIO_MOVE_ARG(HandshakeHandler) handler, + stream* self, handshake_type type) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a HandshakeHandler. + ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check; + + asio::detail::non_const_lvalue handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::handshake_op(type), handler2.value); + } + }; + + struct initiate_async_buffered_handshake + { + template + void operator()(ASIO_MOVE_ARG(BufferedHandshakeHandler) handler, + stream* self, handshake_type type, + const ConstBufferSequence& buffers) const + { + // If you get an error on the following line it means that your + // handler does not meet the documented type requirements for a + // BufferedHandshakeHandler. + ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( + BufferedHandshakeHandler, handler) type_check; + + asio::detail::non_const_lvalue< + BufferedHandshakeHandler> handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::buffered_handshake_op(type, buffers), + handler2.value); + } + }; + + struct initiate_async_shutdown + { + template + void operator()(ASIO_MOVE_ARG(ShutdownHandler) handler, + stream* self) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ShutdownHandler. + ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check; + + asio::detail::non_const_lvalue handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::shutdown_op(), handler2.value); + } + }; + + struct initiate_async_write_some + { + template + void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + stream* self, const ConstBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + asio::detail::non_const_lvalue handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::write_op(buffers), handler2.value); + } + }; + + struct initiate_async_read_some + { + template + void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + stream* self, const MutableBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + asio::detail::non_const_lvalue handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::read_op(buffers), handler2.value); + } + }; + Stream next_layer_; detail::stream_core core_; }; diff --git a/asio/src/doc/reference.dox b/asio/src/doc/reference.dox index fe1cb205..d5190590 100644 --- a/asio/src/doc/reference.dox +++ b/asio/src/doc/reference.dox @@ -197,6 +197,7 @@ PREDEFINED = GENERATING_DOCUMENTATION \ ASIO_EOF_ERROR(e)=implementation_defined \ ASIO_OS_ERROR(e1,e2)=implementation_defined \ ASIO_MOVE_ARG(a)=a&& \ + ASIO_NONDEDUCED_MOVE_ARG(a)=a& \ ASIO_DECL= \ ASIO_CONSTEXPR=constexpr \ ASIO_NOEXCEPT=noexcept \ diff --git a/asio/src/doc/reference.xsl b/asio/src/doc/reference.xsl index 70f51376..7e07baeb 100644 --- a/asio/src/doc/reference.xsl +++ b/asio/src/doc/reference.xsl @@ -103,7 +103,8 @@ not(contains(compoundname, '_handler')) and not(contains(compoundname, 'std_allocator_void')) and not(contains(compoundname, 'thread_function')) and - not(contains(compoundname, 'context_impl'))"> + not(contains(compoundname, 'context_impl')) and + not(contains(compoundname, 'initiate_'))"> @@ -112,10 +113,12 @@ not(contains(ancestor::*/compoundname, '::detail')) and not(contains(ancestor::*/compoundname, '::service::key')) and not(contains(ancestor::*/compoundname, '_helper')) and + not(contains(ancestor::*/compoundname, 'initiate_')) and not(contains(name, '_helper')) and not(contains(name, 'std_allocator_void')) and not(contains(name, 'thread_function')) and - not(contains(name, 'io_context_impl'))"> + not(contains(name, 'io_context_impl')) and + not(contains(name, 'initiate_'))"> @@ -850,7 +853,7 @@ [[Name][Description]] + innerclass[@prot='public' and not(contains(., '_handler')) and not(contains(., 'thread_function')) and not(contains(., 'initiate_'))]" mode="class-table"> [