diff options
Diffstat (limited to 'boost/asio')
491 files changed, 14959 insertions, 14811 deletions
diff --git a/boost/asio/associated_allocator.hpp b/boost/asio/associated_allocator.hpp index bcf1eca3ae..c70852b534 100644 --- a/boost/asio/associated_allocator.hpp +++ b/boost/asio/associated_allocator.hpp @@ -2,7 +2,7 @@ // associated_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/associated_executor.hpp b/boost/asio/associated_executor.hpp index c31800f394..a44190b5fd 100644 --- a/boost/asio/associated_executor.hpp +++ b/boost/asio/associated_executor.hpp @@ -2,7 +2,7 @@ // associated_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/async_result.hpp b/boost/asio/async_result.hpp index a2aafce134..4f3bb1ec09 100644 --- a/boost/asio/async_result.hpp +++ b/boost/asio/async_result.hpp @@ -2,7 +2,7 @@ // async_result.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,7 +17,7 @@ #include <boost/asio/detail/config.hpp> #include <boost/asio/detail/type_traits.hpp> -#include <boost/asio/handler_type.hpp> +#include <boost/asio/detail/variadic_templates.hpp> #include <boost/asio/detail/push_options.hpp> @@ -42,30 +42,15 @@ namespace asio { * The primary template assumes that the CompletionToken is the completion * handler. */ -#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) template <typename CompletionToken, typename Signature> -#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) -template <typename CompletionToken, typename Signature = void> -#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) class async_result { public: -#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) /// The concrete completion handler type for the specific signature. typedef CompletionToken completion_handler_type; /// The return type of the initiating function. typedef void return_type; -#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - // For backward compatibility, determine the concrete completion handler type - // by using the legacy handler_type trait. - typedef typename handler_type<CompletionToken, Signature>::type - completion_handler_type; - - // For backward compatibility, determine the initiating function return type - // using the legacy single-parameter version of async_result. - typedef typename async_result<completion_handler_type>::type return_type; -#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) /// Construct an async result from a given handler. /** @@ -74,11 +59,6 @@ public: * then returned from the initiating function. */ explicit async_result(completion_handler_type& h) -#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - // No data members to initialise. -#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - : legacy_result_(h) -#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) { (void)h; } @@ -86,55 +66,59 @@ public: /// Obtain the value to be returned from the initiating function. return_type get() { -#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - // Nothing to do. -#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - return legacy_result_.get(); -#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) } -private: - async_result(const async_result&) BOOST_ASIO_DELETED; - async_result& operator=(const async_result&) BOOST_ASIO_DELETED; - -#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - // No data members. -#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - async_result<completion_handler_type> legacy_result_; -#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) -}; - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - -/// (Deprecated: Use two-parameter version of async_result.) An interface for -/// customising the behaviour of an initiating function. -/** - * This template may be specialised for user-defined handler types. - */ -template <typename Handler> -class async_result<Handler> -{ -public: - /// The return type of the initiating function. - typedef void type; +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) \ + || defined(GENERATING_DOCUMENTATION) - /// Construct an async result from a given handler. - /** - * When using a specalised async_result, the constructor has an opportunity - * to initialise some state associated with the handler, which is then - * returned from the initiating function. - */ - explicit async_result(Handler&) + /// Initiate the asynchronous operation that will produce the result, and + /// obtain the value to be returned from the initiating function. + template <typename Initiation, typename RawCompletionToken, typename... Args> + static return_type initiate( + BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, + BOOST_ASIO_MOVE_ARG(Args)... args) { + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( + BOOST_ASIO_MOVE_CAST(RawCompletionToken)(token), + BOOST_ASIO_MOVE_CAST(Args)(args)...); } - /// Obtain the value to be returned from the initiating function. - type get() +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + // || defined(GENERATING_DOCUMENTATION) + + template <typename Initiation, typename RawCompletionToken> + static return_type initiate( + BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_MOVE_ARG(RawCompletionToken) token) { + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( + BOOST_ASIO_MOVE_CAST(RawCompletionToken)(token)); } -}; -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) +#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \ + template <typename Initiation, typename RawCompletionToken, \ + BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + static return_type initiate( \ + BOOST_ASIO_MOVE_ARG(Initiation) initiation, \ + BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \ + BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( \ + BOOST_ASIO_MOVE_CAST(RawCompletionToken)(token), \ + BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF) +#undef BOOST_ASIO_PRIVATE_INITIATE_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + // || defined(GENERATING_DOCUMENTATION) + +private: + async_result(const async_result&) BOOST_ASIO_DELETED; + async_result& operator=(const async_result&) BOOST_ASIO_DELETED; +}; /// Helper template to deduce the handler type from a CompletionToken, capture /// a local copy of the handler, and then create an async_result for the @@ -195,11 +179,40 @@ struct async_result_helper { }; -} // namespace detail -} // namespace asio -} // namespace boost +struct async_result_memfns_base +{ + void initiate(); +}; -#include <boost/asio/detail/pop_options.hpp> +template <typename T> +struct async_result_memfns_derived + : T, async_result_memfns_base +{ +}; + +template <typename T, T> +struct async_result_memfns_check +{ +}; + +template <typename> +char (&async_result_initiate_memfn_helper(...))[2]; + +template <typename T> +char async_result_initiate_memfn_helper( + async_result_memfns_check< + void (async_result_memfns_base::*)(), + &async_result_memfns_derived<T>::initiate>*); + +template <typename CompletionToken, typename Signature> +struct async_result_has_initiate_memfn + : integral_constant<bool, sizeof(async_result_initiate_memfn_helper< + async_result<typename decay<CompletionToken>::type, Signature> + >(0)) != 1> +{ +}; + +} // namespace detail #if defined(GENERATING_DOCUMENTATION) # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \ @@ -220,4 +233,126 @@ struct async_result_helper typename ::boost::asio::decay<ct>::type, sig>::completion_handler_type #endif +#if defined(GENERATING_DOCUMENTATION) + +template <typename CompletionToken, typename Signature, + typename Initiation, typename... Args> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) +async_initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken), + BOOST_ASIO_MOVE_ARG(Args)... args); + +#elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename CompletionToken, typename Signature, + typename Initiation, typename... Args> +inline typename enable_if< + detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, + BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type +async_initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_MOVE_ARG(Args)... args) +{ + return async_result<typename decay<CompletionToken>::type, + Signature>::initiate(BOOST_ASIO_MOVE_CAST(Initiation)(initiation), + BOOST_ASIO_MOVE_CAST(CompletionToken)(token), + BOOST_ASIO_MOVE_CAST(Args)(args)...); +} + +template <typename CompletionToken, typename Signature, + typename Initiation, typename... Args> +inline typename enable_if< + !detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, + BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type +async_initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_MOVE_ARG(Args)... args) +{ + async_completion<CompletionToken, Signature> completion(token); + + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( + BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(CompletionToken, + Signature))(completion.completion_handler), + BOOST_ASIO_MOVE_CAST(Args)(args)...); + + return completion.result.get(); +} + +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename CompletionToken, typename Signature, typename Initiation> +inline typename enable_if< + detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, + BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type +async_initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) +{ + return async_result<typename decay<CompletionToken>::type, + Signature>::initiate(BOOST_ASIO_MOVE_CAST(Initiation)(initiation), + BOOST_ASIO_MOVE_CAST(CompletionToken)(token)); +} + +template <typename CompletionToken, typename Signature, typename Initiation> +inline typename enable_if< + !detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, + BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type +async_initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) +{ + async_completion<CompletionToken, Signature> completion(token); + + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( + BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(CompletionToken, + Signature))(completion.completion_handler)); + + return completion.result.get(); +} + +#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \ + template <typename CompletionToken, typename Signature, \ + typename Initiation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + inline typename enable_if< \ + detail::async_result_has_initiate_memfn< \ + CompletionToken, Signature>::value, \ + BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \ + async_initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation, \ + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ + BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + return async_result<typename decay<CompletionToken>::type, \ + Signature>::initiate(BOOST_ASIO_MOVE_CAST(Initiation)(initiation), \ + BOOST_ASIO_MOVE_CAST(CompletionToken)(token), \ + BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + \ + template <typename CompletionToken, typename Signature, \ + typename Initiation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + inline typename enable_if< \ + !detail::async_result_has_initiate_memfn< \ + CompletionToken, Signature>::value, \ + BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \ + async_initiate(BOOST_ASIO_MOVE_ARG(Initiation) initiation, \ + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ + BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + async_completion<CompletionToken, Signature> completion(token); \ + \ + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( \ + BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(CompletionToken, \ + Signature))(completion.completion_handler), \ + BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ + \ + return completion.result.get(); \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF) +#undef BOOST_ASIO_PRIVATE_INITIATE_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + #endif // BOOST_ASIO_ASYNC_RESULT_HPP diff --git a/boost/asio/awaitable.hpp b/boost/asio/awaitable.hpp new file mode 100644 index 0000000000..83f8647cb1 --- /dev/null +++ b/boost/asio/awaitable.hpp @@ -0,0 +1,125 @@ +// +// awaitable.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_AWAITABLE_HPP +#define BOOST_ASIO_AWAITABLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) + +#include <experimental/coroutine> +#include <boost/asio/executor.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +using std::experimental::coroutine_handle; +using std::experimental::suspend_always; + +template <typename> class awaitable_thread; +template <typename, typename> class awaitable_frame; + +} // namespace detail + +/// The return type of a coroutine or asynchronous operation. +template <typename T, typename Executor = executor> +class awaitable +{ +public: + /// The type of the awaited value. + typedef T value_type; + + /// The executor type that will be used for the coroutine. + typedef Executor executor_type; + + /// Default constructor. + constexpr awaitable() noexcept + : frame_(nullptr) + { + } + + /// Move constructor. + awaitable(awaitable&& other) noexcept + : frame_(std::exchange(other.frame_, nullptr)) + { + } + + /// Destructor + ~awaitable() + { + if (frame_) + frame_->destroy(); + } + + /// Checks if the awaitable refers to a future result. + bool valid() const noexcept + { + return !!frame_; + } + +#if !defined(GENERATING_DOCUMENTATION) + + // Support for co_await keyword. + bool await_ready() const noexcept + { + return false; + } + + // Support for co_await keyword. + template <class U> + void await_suspend( + detail::coroutine_handle<detail::awaitable_frame<U, Executor>> h) + { + frame_->push_frame(&h.promise()); + } + + // Support for co_await keyword. + T await_resume() + { + return frame_->get(); + } + +#endif // !defined(GENERATING_DOCUMENTATION) + +private: + template <typename> friend class detail::awaitable_thread; + template <typename, typename> friend class detail::awaitable_frame; + + // Not copy constructible or copy assignable. + awaitable(const awaitable&) = delete; + awaitable& operator=(const awaitable&) = delete; + + // Construct the awaitable from a coroutine's frame object. + explicit awaitable(detail::awaitable_frame<T, Executor>* a) + : frame_(a) + { + } + + detail::awaitable_frame<T, Executor>* frame_; +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/impl/awaitable.hpp> + +#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_AWAITABLE_HPP diff --git a/boost/asio/basic_datagram_socket.hpp b/boost/asio/basic_datagram_socket.hpp index b512b75dde..b058f78c4c 100644 --- a/boost/asio/basic_datagram_socket.hpp +++ b/boost/asio/basic_datagram_socket.hpp @@ -2,7 +2,7 @@ // basic_datagram_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -19,19 +19,25 @@ #include <cstddef> #include <boost/asio/basic_socket.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/error.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/datagram_socket_service.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { +#if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Protocol, typename Executor = executor> +class basic_datagram_socket; + +#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL) + /// Provides datagram-oriented socket functionality. /** * The basic_datagram_socket class template provides asynchronous and blocking @@ -41,18 +47,28 @@ namespace asio { * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= datagram_socket_service<Protocol>)> +template <typename Protocol, typename Executor> class basic_datagram_socket - : public basic_socket<Protocol BOOST_ASIO_SVC_TARG> + : public basic_socket<Protocol, Executor> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_datagram_socket<Protocol, Executor1> other; + }; + /// The native representation of a socket. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type; #else - typedef typename basic_socket< - Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type; + typedef typename basic_socket<Protocol, + Executor>::native_handle_type native_handle_type; #endif /// The protocol type. @@ -66,12 +82,29 @@ public: * This constructor creates a datagram socket without opening it. The open() * function must be called before data can be sent or received on the socket. * - * @param io_context The io_context object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_datagram_socket(const executor_type& ex) + : basic_socket<Protocol, Executor>(ex) + { + } + + /// Construct a basic_datagram_socket without opening it. + /** + * This constructor creates a datagram socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. */ - explicit basic_datagram_socket(boost::asio::io_context& io_context) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context) + template <typename ExecutionContext> + explicit basic_datagram_socket(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context) { } @@ -79,17 +112,37 @@ public: /** * This constructor creates and opens a datagram socket. * - * @param io_context The io_context object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(const executor_type& ex, const protocol_type& protocol) + : basic_socket<Protocol, Executor>(ex, protocol) + { + } + + /// Construct and open a basic_datagram_socket. + /** + * This constructor creates and opens a datagram socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. * * @throws boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_context& io_context, - const protocol_type& protocol) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol) + template <typename ExecutionContext> + basic_datagram_socket(ExecutionContext& context, + const protocol_type& protocol, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, protocol) { } @@ -100,18 +153,42 @@ public: * to the specified endpoint on the local machine. The protocol used is the * protocol associated with the given endpoint. * - * @param io_context The io_context object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the datagram + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(const executor_type& ex, const endpoint_type& endpoint) + : basic_socket<Protocol, Executor>(ex, endpoint) + { + } + + /// Construct a basic_datagram_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a datagram socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. * * @param endpoint An endpoint on the local machine to which the datagram * socket will be bound. * * @throws boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_context& io_context, - const endpoint_type& endpoint) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint) + template <typename ExecutionContext> + basic_datagram_socket(ExecutionContext& context, + const endpoint_type& endpoint, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, endpoint) { } @@ -120,9 +197,8 @@ public: * This constructor creates a datagram socket object to hold an existing * native socket. * - * @param io_context The io_context object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. * @@ -130,10 +206,34 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_context& io_context, + basic_datagram_socket(const executor_type& ex, const protocol_type& protocol, const native_handle_type& native_socket) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>( - io_context, protocol, native_socket) + : basic_socket<Protocol, Executor>(ex, protocol, native_socket) + { + } + + /// Construct a basic_datagram_socket on an existing native socket. + /** + * This constructor creates a datagram socket object to hold an existing + * native socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_datagram_socket(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_socket, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, protocol, native_socket) { } @@ -146,10 +246,11 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_datagram_socket(io_context&) constructor. + * constructed using the @c basic_datagram_socket(const executor_type&) + * constructor. */ basic_datagram_socket(basic_datagram_socket&& other) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other)) + : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -162,11 +263,12 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_datagram_socket(io_context&) constructor. + * constructed using the @c basic_datagram_socket(const executor_type&) + * constructor. */ basic_datagram_socket& operator=(basic_datagram_socket&& other) { - basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other)); + basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } @@ -179,13 +281,16 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_datagram_socket(io_context&) constructor. + * constructed using the @c basic_datagram_socket(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - basic_datagram_socket( - basic_datagram_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other, - typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other)) + template <typename Protocol1, typename Executor1> + basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other, + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -199,14 +304,17 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_datagram_socket(io_context&) constructor. + * constructed using the @c basic_datagram_socket(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - typename enable_if<is_convertible<Protocol1, Protocol>::value, - basic_datagram_socket>::type& operator=( - basic_datagram_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other) + template <typename Protocol1, typename Executor1> + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value, + basic_datagram_socket& + >::type operator=(basic_datagram_socket<Protocol1, Executor1>&& other) { - basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other)); + basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -246,8 +354,8 @@ public: std::size_t send(const ConstBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().send( - this->get_implementation(), buffers, 0, ec); + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); boost::asio::detail::throw_error(ec, "send"); return s; } @@ -274,8 +382,8 @@ public: socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().send( - this->get_implementation(), buffers, flags, ec); + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); boost::asio::detail::throw_error(ec, "send"); return s; } @@ -301,8 +409,8 @@ public: std::size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().send( - this->get_implementation(), buffers, flags, ec); + return this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); } /// Start an asynchronous send on a connected socket. @@ -323,9 +431,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected datagram @@ -346,22 +454,10 @@ public: async_send(const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send(this->get_implementation(), - buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send(this->get_implementation(), - buffers, 0, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous send on a connected socket. @@ -384,9 +480,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected datagram @@ -399,22 +495,9 @@ public: socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send(this->get_implementation(), - buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send(this->get_implementation(), - buffers, flags, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send(), handler, this, buffers, flags); } /// Send a datagram to the specified endpoint. @@ -447,8 +530,8 @@ public: const endpoint_type& destination) { boost::system::error_code ec; - std::size_t s = this->get_service().send_to( - this->get_implementation(), buffers, destination, 0, ec); + std::size_t s = this->impl_.get_service().send_to( + this->impl_.get_implementation(), buffers, destination, 0, ec); boost::asio::detail::throw_error(ec, "send_to"); return s; } @@ -474,8 +557,8 @@ public: const endpoint_type& destination, socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().send_to( - this->get_implementation(), buffers, destination, flags, ec); + std::size_t s = this->impl_.get_service().send_to( + this->impl_.get_implementation(), buffers, destination, flags, ec); boost::asio::detail::throw_error(ec, "send_to"); return s; } @@ -501,7 +584,7 @@ public: const endpoint_type& destination, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().send_to(this->get_implementation(), + return this->impl_.get_service().send_to(this->impl_.get_implementation(), buffers, destination, flags, ec); } @@ -526,9 +609,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To send a single data buffer use the @ref buffer function as follows: @@ -549,24 +632,10 @@ public: const endpoint_type& destination, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send_to( - this->get_implementation(), buffers, destination, 0, - BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send_to( - this->get_implementation(), buffers, destination, 0, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send_to(), handler, this, buffers, + destination, socket_base::message_flags(0)); } /// Start an asynchronous send. @@ -592,9 +661,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename ConstBufferSequence, typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, @@ -603,24 +672,9 @@ public: const endpoint_type& destination, socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send_to( - this->get_implementation(), buffers, destination, flags, - BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send_to( - this->get_implementation(), buffers, destination, flags, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send_to(), handler, this, buffers, destination, flags); } /// Receive some data on a connected socket. @@ -651,8 +705,8 @@ public: std::size_t receive(const MutableBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, 0, ec); + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); boost::asio::detail::throw_error(ec, "receive"); return s; } @@ -680,8 +734,8 @@ public: socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, flags, ec); + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); boost::asio::detail::throw_error(ec, "receive"); return s; } @@ -708,8 +762,8 @@ public: std::size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().receive( - this->get_implementation(), buffers, flags, ec); + return this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); } /// Start an asynchronous receive on a connected socket. @@ -730,9 +784,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected @@ -754,22 +808,10 @@ public: async_receive(const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive(this->get_implementation(), - buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive(this->get_implementation(), - buffers, 0, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive on a connected socket. @@ -792,9 +834,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected @@ -807,22 +849,9 @@ public: socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive(this->get_implementation(), - buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive(this->get_implementation(), - buffers, flags, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive(), handler, this, buffers, flags); } /// Receive a datagram with the endpoint of the sender. @@ -856,8 +885,8 @@ public: endpoint_type& sender_endpoint) { boost::system::error_code ec; - std::size_t s = this->get_service().receive_from( - this->get_implementation(), buffers, sender_endpoint, 0, ec); + std::size_t s = this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec); boost::asio::detail::throw_error(ec, "receive_from"); return s; } @@ -883,8 +912,8 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().receive_from( - this->get_implementation(), buffers, sender_endpoint, flags, ec); + std::size_t s = this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); boost::asio::detail::throw_error(ec, "receive_from"); return s; } @@ -910,8 +939,8 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().receive_from(this->get_implementation(), - buffers, sender_endpoint, flags, ec); + return this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); } /// Start an asynchronous receive. @@ -937,9 +966,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To receive into a single data buffer use the @ref buffer function as @@ -957,24 +986,10 @@ public: endpoint_type& sender_endpoint, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive_from( - this->get_implementation(), buffers, sender_endpoint, 0, - BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive_from( - this->get_implementation(), buffers, sender_endpoint, 0, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive_from(), handler, this, buffers, + &sender_endpoint, socket_base::message_flags(0)); } /// Start an asynchronous receive. @@ -1002,9 +1017,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename MutableBufferSequence, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, @@ -1013,25 +1028,85 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive_from(), handler, + this, buffers, &sender_endpoint, flags); + } -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive_from( - this->get_implementation(), buffers, sender_endpoint, flags, - BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); +private: + struct initiate_async_send + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - this->get_service().async_receive_from( - this->get_implementation(), buffers, sender_endpoint, flags, - init.completion_handler); + detail::non_const_lvalue<WriteHandler> handler2(handler); + self->impl_.get_service().async_send( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - } + struct initiate_async_send_to + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> 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 <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> 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/boost/asio/basic_deadline_timer.hpp b/boost/asio/basic_deadline_timer.hpp index 56a265bfbc..75f0fcd8bc 100644 --- a/boost/asio/basic_deadline_timer.hpp +++ b/boost/asio/basic_deadline_timer.hpp @@ -2,7 +2,7 @@ // basic_deadline_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,19 +21,16 @@ || defined(GENERATING_DOCUMENTATION) #include <cstddef> -#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/detail/deadline_timer_service.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> #include <boost/asio/time_traits.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/deadline_timer_service.hpp> -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/detail/deadline_timer_service.hpp> -# define BOOST_ASIO_SVC_T detail::deadline_timer_service<TimeTraits> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -58,7 +55,7 @@ namespace asio { * Performing a blocking wait: * @code * // Construct a timer without setting an expiry time. - * boost::asio::deadline_timer timer(io_context); + * boost::asio::deadline_timer timer(my_context); * * // Set an expiry time relative to now. * timer.expires_from_now(boost::posix_time::seconds(5)); @@ -81,7 +78,7 @@ namespace asio { * ... * * // Construct a timer with an absolute expiry time. - * boost::asio::deadline_timer timer(io_context, + * boost::asio::deadline_timer timer(my_context, * boost::posix_time::time_from_string("2005-12-07 23:59:59.000")); * * // Start an asynchronous wait. @@ -128,14 +125,13 @@ namespace asio { * it contains the value boost::asio::error::operation_aborted. */ template <typename Time, - typename TimeTraits = boost::asio::time_traits<Time> - BOOST_ASIO_SVC_TPARAM_DEF2(= deadline_timer_service<Time, TimeTraits>)> + typename TimeTraits = boost::asio::time_traits<Time>, + typename Executor = executor> class basic_deadline_timer - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T> { public: /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; + typedef Executor executor_type; /// The time traits type. typedef TimeTraits traits_type; @@ -152,11 +148,30 @@ public: * expires_at() or expires_from_now() functions must be called to set an * expiry time before the timer can be waited on. * - * @param io_context The io_context object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. + * @param ex The I/O executor that the timer will use, by default, to + * dispatch handlers for any asynchronous operations performed on the timer. + */ + explicit basic_deadline_timer(const executor_type& ex) + : impl_(ex) + { + } + + /// Constructor. + /** + * This constructor creates a timer without setting an expiry time. The + * expires_at() or expires_from_now() functions must be called to set an + * expiry time before the timer can be waited on. + * + * @param context An execution context which provides the I/O executor that + * the timer will use, by default, to dispatch handlers for any asynchronous + * operations performed on the timer. */ - explicit basic_deadline_timer(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + template <typename ExecutionContext> + explicit basic_deadline_timer(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { } @@ -164,18 +179,40 @@ public: /** * This constructor creates a timer and sets the expiry time. * - * @param io_context The io_context object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. + * @param ex The I/O executor that the timer will use, by default, to + * dispatch handlers for any asynchronous operations performed on the timer. * * @param expiry_time The expiry time to be used for the timer, expressed * as an absolute time. */ - basic_deadline_timer(boost::asio::io_context& io_context, - const time_type& expiry_time) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + basic_deadline_timer(const executor_type& ex, const time_type& expiry_time) + : impl_(ex) { boost::system::error_code ec; - this->get_service().expires_at(this->get_implementation(), expiry_time, ec); + impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_at"); + } + + /// Constructor to set a particular expiry time as an absolute time. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param context An execution context which provides the I/O executor that + * the timer will use, by default, to dispatch handlers for any asynchronous + * operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, expressed + * as an absolute time. + */ + template <typename ExecutionContext> + basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_at"); } @@ -183,19 +220,44 @@ public: /** * This constructor creates a timer and sets the expiry time. * - * @param io_context The io_context object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. + * @param ex The I/O executor that the timer will use, by default, to + * dispatch handlers for any asynchronous operations performed on the timer. * * @param expiry_time The expiry time to be used for the timer, relative to * now. */ - basic_deadline_timer(boost::asio::io_context& io_context, + basic_deadline_timer(const executor_type& ex, const duration_type& expiry_time) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + : impl_(ex) { boost::system::error_code ec; - this->get_service().expires_from_now( - this->get_implementation(), expiry_time, ec); + impl_.get_service().expires_from_now( + impl_.get_implementation(), expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_from_now"); + } + + /// Constructor to set a particular expiry time relative to now. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param context An execution context which provides the I/O executor that + * the timer will use, by default, to dispatch handlers for any asynchronous + * operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, relative to + * now. + */ + template <typename ExecutionContext> + basic_deadline_timer(ExecutionContext& context, + const duration_type& expiry_time, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().expires_from_now( + impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_from_now"); } @@ -208,10 +270,11 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_deadline_timer(io_context&) constructor. + * constructed using the @c basic_deadline_timer(const executor_type&) + * constructor. */ basic_deadline_timer(basic_deadline_timer&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) + : impl_(std::move(other.impl_)) { } @@ -224,11 +287,12 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_deadline_timer(io_context&) constructor. + * constructed using the @c basic_deadline_timer(const executor_type&) + * constructor. */ basic_deadline_timer& operator=(basic_deadline_timer&& other) { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); + impl_ = std::move(other.impl_); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -242,45 +306,11 @@ public: { } -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - // These functions are provided by basic_io_object<>. -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Get the executor associated with the object. executor_type get_executor() BOOST_ASIO_NOEXCEPT { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); + return impl_.get_executor(); } -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) /// Cancel any asynchronous operations that are waiting on the timer. /** @@ -307,7 +337,7 @@ public: std::size_t cancel() { boost::system::error_code ec; - std::size_t s = this->get_service().cancel(this->get_implementation(), ec); + std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel"); return s; } @@ -336,7 +366,7 @@ public: */ std::size_t cancel(boost::system::error_code& ec) { - return this->get_service().cancel(this->get_implementation(), ec); + return impl_.get_service().cancel(impl_.get_implementation(), ec); } /// Cancels one asynchronous operation that is waiting on the timer. @@ -366,8 +396,8 @@ public: std::size_t cancel_one() { boost::system::error_code ec; - std::size_t s = this->get_service().cancel_one( - this->get_implementation(), ec); + std::size_t s = impl_.get_service().cancel_one( + impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel_one"); return s; } @@ -398,7 +428,7 @@ public: */ std::size_t cancel_one(boost::system::error_code& ec) { - return this->get_service().cancel_one(this->get_implementation(), ec); + return impl_.get_service().cancel_one(impl_.get_implementation(), ec); } /// Get the timer's expiry time as an absolute time. @@ -408,7 +438,7 @@ public: */ time_type expires_at() const { - return this->get_service().expires_at(this->get_implementation()); + return impl_.get_service().expires_at(impl_.get_implementation()); } /// Set the timer's expiry time as an absolute time. @@ -436,8 +466,8 @@ public: std::size_t expires_at(const time_type& expiry_time) { boost::system::error_code ec; - std::size_t s = this->get_service().expires_at( - this->get_implementation(), expiry_time, ec); + std::size_t s = impl_.get_service().expires_at( + impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_at"); return s; } @@ -467,8 +497,8 @@ public: std::size_t expires_at(const time_type& expiry_time, boost::system::error_code& ec) { - return this->get_service().expires_at( - this->get_implementation(), expiry_time, ec); + return impl_.get_service().expires_at( + impl_.get_implementation(), expiry_time, ec); } /// Get the timer's expiry time relative to now. @@ -478,7 +508,7 @@ public: */ duration_type expires_from_now() const { - return this->get_service().expires_from_now(this->get_implementation()); + return impl_.get_service().expires_from_now(impl_.get_implementation()); } /// Set the timer's expiry time relative to now. @@ -506,8 +536,8 @@ public: std::size_t expires_from_now(const duration_type& expiry_time) { boost::system::error_code ec; - std::size_t s = this->get_service().expires_from_now( - this->get_implementation(), expiry_time, ec); + std::size_t s = impl_.get_service().expires_from_now( + impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_from_now"); return s; } @@ -537,8 +567,8 @@ public: std::size_t expires_from_now(const duration_type& expiry_time, boost::system::error_code& ec) { - return this->get_service().expires_from_now( - this->get_implementation(), expiry_time, ec); + return impl_.get_service().expires_from_now( + impl_.get_implementation(), expiry_time, ec); } /// Perform a blocking wait on the timer. @@ -551,7 +581,7 @@ public: void wait() { boost::system::error_code ec; - this->get_service().wait(this->get_implementation(), ec); + impl_.get_service().wait(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "wait"); } @@ -564,7 +594,7 @@ public: */ void wait(boost::system::error_code& ec) { - this->get_service().wait(this->get_implementation(), ec); + impl_.get_service().wait(impl_.get_implementation(), ec); } /// Start an asynchronous wait on the timer. @@ -587,32 +617,44 @@ public: * const boost::system::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename WaitHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, void (boost::system::error_code)) async_wait(BOOST_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. - BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_wait(this->get_implementation(), - BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_wait(this->get_implementation(), - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WaitHandler, void (boost::system::error_code)>( + initiate_async_wait(), handler, this); } + +private: + // Disallow copying and assignment. + basic_deadline_timer(const basic_deadline_timer&) BOOST_ASIO_DELETED; + basic_deadline_timer& operator=( + const basic_deadline_timer&) BOOST_ASIO_DELETED; + + struct initiate_async_wait + { + template <typename WaitHandler> + void operator()(BOOST_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. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue<WaitHandler> 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<TimeTraits>, Executor> impl_; }; } // namespace asio @@ -620,10 +662,6 @@ public: #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# undef BOOST_ASIO_SVC_T -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) // || defined(GENERATING_DOCUMENTATION) diff --git a/boost/asio/basic_io_object.hpp b/boost/asio/basic_io_object.hpp index c0c2c714eb..a9f44d1f04 100644 --- a/boost/asio/basic_io_object.hpp +++ b/boost/asio/basic_io_object.hpp @@ -2,7 +2,7 @@ // basic_io_object.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/basic_raw_socket.hpp b/boost/asio/basic_raw_socket.hpp index b24d079659..cc45d372b5 100644 --- a/boost/asio/basic_raw_socket.hpp +++ b/boost/asio/basic_raw_socket.hpp @@ -2,7 +2,7 @@ // basic_raw_socket.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -19,19 +19,25 @@ #include <cstddef> #include <boost/asio/basic_socket.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/error.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/raw_socket_service.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { +#if !defined(BOOST_ASIO_BASIC_RAW_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_RAW_SOCKET_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Protocol, typename Executor = executor> +class basic_raw_socket; + +#endif // !defined(BOOST_ASIO_BASIC_RAW_SOCKET_FWD_DECL) + /// Provides raw-oriented socket functionality. /** * The basic_raw_socket class template provides asynchronous and blocking @@ -41,18 +47,28 @@ namespace asio { * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= raw_socket_service<Protocol>)> +template <typename Protocol, typename Executor> class basic_raw_socket - : public basic_socket<Protocol BOOST_ASIO_SVC_TARG> + : public basic_socket<Protocol, Executor> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_raw_socket<Protocol, Executor1> other; + }; + /// The native representation of a socket. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type; #else - typedef typename basic_socket< - Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type; + typedef typename basic_socket<Protocol, + Executor>::native_handle_type native_handle_type; #endif /// The protocol type. @@ -66,12 +82,29 @@ public: * This constructor creates a raw socket without opening it. The open() * function must be called before data can be sent or received on the socket. * - * @param io_context The io_context object that the raw socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. */ - explicit basic_raw_socket(boost::asio::io_context& io_context) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context) + explicit basic_raw_socket(const executor_type& ex) + : basic_socket<Protocol, Executor>(ex) + { + } + + /// Construct a basic_raw_socket without opening it. + /** + * This constructor creates a raw socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + */ + template <typename ExecutionContext> + explicit basic_raw_socket(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context) { } @@ -79,17 +112,36 @@ public: /** * This constructor creates and opens a raw socket. * - * @param io_context The io_context object that the raw socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. * * @throws boost::system::system_error Thrown on failure. */ - basic_raw_socket(boost::asio::io_context& io_context, - const protocol_type& protocol) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol) + basic_raw_socket(const executor_type& ex, const protocol_type& protocol) + : basic_socket<Protocol, Executor>(ex, protocol) + { + } + + /// Construct and open a basic_raw_socket. + /** + * This constructor creates and opens a raw socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_raw_socket(ExecutionContext& context, const protocol_type& protocol, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, protocol) { } @@ -100,18 +152,41 @@ public: * to the specified endpoint on the local machine. The protocol used is the * protocol associated with the given endpoint. * - * @param io_context The io_context object that the raw socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the raw + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(const executor_type& ex, const endpoint_type& endpoint) + : basic_socket<Protocol, Executor>(ex, endpoint) + { + } + + /// Construct a basic_raw_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a raw socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. * * @param endpoint An endpoint on the local machine to which the raw * socket will be bound. * * @throws boost::system::system_error Thrown on failure. */ - basic_raw_socket(boost::asio::io_context& io_context, - const endpoint_type& endpoint) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint) + template <typename ExecutionContext> + basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, endpoint) { } @@ -120,9 +195,8 @@ public: * This constructor creates a raw socket object to hold an existing * native socket. * - * @param io_context The io_context object that the raw socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. * @@ -130,10 +204,34 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_raw_socket(boost::asio::io_context& io_context, + basic_raw_socket(const executor_type& ex, const protocol_type& protocol, const native_handle_type& native_socket) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>( - io_context, protocol, native_socket) + : basic_socket<Protocol, Executor>(ex, protocol, native_socket) + { + } + + /// Construct a basic_raw_socket on an existing native socket. + /** + * This constructor creates a raw socket object to hold an existing + * native socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_raw_socket(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_socket, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, protocol, native_socket) { } @@ -146,10 +244,11 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_raw_socket(io_context&) constructor. + * constructed using the @c basic_raw_socket(const executor_type&) + * constructor. */ basic_raw_socket(basic_raw_socket&& other) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other)) + : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -161,28 +260,34 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_raw_socket(io_context&) constructor. + * constructed using the @c basic_raw_socket(const executor_type&) + * constructor. */ basic_raw_socket& operator=(basic_raw_socket&& other) { - basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other)); + basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } - /// Move-construct a basic_raw_socket from a socket of another protocol type. + /// Move-construct a basic_raw_socket from a socket of another protocol + /// type. /** * This constructor moves a raw socket from one object to another. * - * @param other The other basic_raw_socket object from which the move will - * occur. + * @param other The other basic_raw_socket object from which the move + * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_raw_socket(io_context&) constructor. + * constructed using the @c basic_raw_socket(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - basic_raw_socket(basic_raw_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other, - typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other)) + template <typename Protocol1, typename Executor1> + basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other, + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -194,14 +299,17 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_raw_socket(io_context&) constructor. + * constructed using the @c basic_raw_socket(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - typename enable_if<is_convertible<Protocol1, Protocol>::value, - basic_raw_socket>::type& operator=( - basic_raw_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other) + template <typename Protocol1, typename Executor1> + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value, + basic_raw_socket& + >::type operator=(basic_raw_socket<Protocol1, Executor1>&& other) { - basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other)); + basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -240,8 +348,8 @@ public: std::size_t send(const ConstBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().send( - this->get_implementation(), buffers, 0, ec); + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); boost::asio::detail::throw_error(ec, "send"); return s; } @@ -267,8 +375,8 @@ public: socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().send( - this->get_implementation(), buffers, flags, ec); + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); boost::asio::detail::throw_error(ec, "send"); return s; } @@ -293,8 +401,8 @@ public: std::size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().send( - this->get_implementation(), buffers, flags, ec); + return this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); } /// Start an asynchronous send on a connected socket. @@ -315,9 +423,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected raw @@ -338,22 +446,10 @@ public: async_send(const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send(this->get_implementation(), - buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send(this->get_implementation(), - buffers, 0, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous send on a connected socket. @@ -376,9 +472,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected raw @@ -391,22 +487,9 @@ public: socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send(this->get_implementation(), - buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send(this->get_implementation(), - buffers, flags, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send(), handler, this, buffers, flags); } /// Send raw data to the specified endpoint. @@ -439,8 +522,8 @@ public: const endpoint_type& destination) { boost::system::error_code ec; - std::size_t s = this->get_service().send_to( - this->get_implementation(), buffers, destination, 0, ec); + std::size_t s = this->impl_.get_service().send_to( + this->impl_.get_implementation(), buffers, destination, 0, ec); boost::asio::detail::throw_error(ec, "send_to"); return s; } @@ -466,8 +549,8 @@ public: const endpoint_type& destination, socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().send_to( - this->get_implementation(), buffers, destination, flags, ec); + std::size_t s = this->impl_.get_service().send_to( + this->impl_.get_implementation(), buffers, destination, flags, ec); boost::asio::detail::throw_error(ec, "send_to"); return s; } @@ -493,7 +576,7 @@ public: const endpoint_type& destination, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().send_to(this->get_implementation(), + return this->impl_.get_service().send_to(this->impl_.get_implementation(), buffers, destination, flags, ec); } @@ -518,9 +601,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To send a single data buffer use the @ref buffer function as follows: @@ -541,22 +624,10 @@ public: const endpoint_type& destination, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send_to(this->get_implementation(), - buffers, destination, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send_to(this->get_implementation(), - buffers, destination, 0, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send_to(), handler, this, buffers, + destination, socket_base::message_flags(0)); } /// Start an asynchronous send. @@ -582,9 +653,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename ConstBufferSequence, typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, @@ -593,24 +664,9 @@ public: const endpoint_type& destination, socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send_to( - this->get_implementation(), buffers, destination, flags, - BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send_to( - this->get_implementation(), buffers, destination, flags, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send_to(), handler, this, buffers, destination, flags); } /// Receive some data on a connected socket. @@ -641,8 +697,8 @@ public: std::size_t receive(const MutableBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, 0, ec); + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); boost::asio::detail::throw_error(ec, "receive"); return s; } @@ -670,8 +726,8 @@ public: socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, flags, ec); + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); boost::asio::detail::throw_error(ec, "receive"); return s; } @@ -698,8 +754,8 @@ public: std::size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().receive( - this->get_implementation(), buffers, flags, ec); + return this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); } /// Start an asynchronous receive on a connected socket. @@ -720,9 +776,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected @@ -744,22 +800,10 @@ public: async_receive(const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive(this->get_implementation(), - buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive(this->get_implementation(), - buffers, 0, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive on a connected socket. @@ -782,9 +826,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected @@ -797,22 +841,9 @@ public: socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive(this->get_implementation(), - buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive(this->get_implementation(), - buffers, flags, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive(), handler, this, buffers, flags); } /// Receive raw data with the endpoint of the sender. @@ -846,8 +877,8 @@ public: endpoint_type& sender_endpoint) { boost::system::error_code ec; - std::size_t s = this->get_service().receive_from( - this->get_implementation(), buffers, sender_endpoint, 0, ec); + std::size_t s = this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec); boost::asio::detail::throw_error(ec, "receive_from"); return s; } @@ -873,8 +904,8 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().receive_from( - this->get_implementation(), buffers, sender_endpoint, flags, ec); + std::size_t s = this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); boost::asio::detail::throw_error(ec, "receive_from"); return s; } @@ -900,8 +931,8 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().receive_from(this->get_implementation(), - buffers, sender_endpoint, flags, ec); + return this->impl_.get_service().receive_from( + this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec); } /// Start an asynchronous receive. @@ -927,9 +958,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To receive into a single data buffer use the @ref buffer function as @@ -947,24 +978,10 @@ public: endpoint_type& sender_endpoint, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive_from( - this->get_implementation(), buffers, sender_endpoint, 0, - BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive_from( - this->get_implementation(), buffers, sender_endpoint, 0, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive_from(), handler, this, buffers, + &sender_endpoint, socket_base::message_flags(0)); } /// Start an asynchronous receive. @@ -992,9 +1009,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename MutableBufferSequence, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, @@ -1003,25 +1020,85 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive_from(), handler, + this, buffers, &sender_endpoint, flags); + } + +private: + struct initiate_async_send + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive_from( - this->get_implementation(), buffers, sender_endpoint, flags, - BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); + detail::non_const_lvalue<WriteHandler> handler2(handler); + self->impl_.get_service().async_send( + self->impl_.get_implementation(), buffers, flags, + handler2.value, self->impl_.get_implementation_executor()); + } + }; - this->get_service().async_receive_from( - this->get_implementation(), buffers, sender_endpoint, flags, - init.completion_handler); + struct initiate_async_send_to + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - } + detail::non_const_lvalue<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> 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 <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> 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/boost/asio/basic_seq_packet_socket.hpp b/boost/asio/basic_seq_packet_socket.hpp index cc98656df3..7c3903ea59 100644 --- a/boost/asio/basic_seq_packet_socket.hpp +++ b/boost/asio/basic_seq_packet_socket.hpp @@ -2,7 +2,7 @@ // basic_seq_packet_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -22,15 +22,20 @@ #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/seq_packet_socket_service.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { +#if !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Protocol, typename Executor = executor> +class basic_seq_packet_socket; + +#endif // !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL) + /// Provides sequenced packet socket functionality. /** * The basic_seq_packet_socket class template provides asynchronous and blocking @@ -40,18 +45,28 @@ namespace asio { * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= seq_packet_socket_service<Protocol>)> +template <typename Protocol, typename Executor> class basic_seq_packet_socket - : public basic_socket<Protocol BOOST_ASIO_SVC_TARG> + : public basic_socket<Protocol, Executor> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_seq_packet_socket<Protocol, Executor1> other; + }; + /// The native representation of a socket. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type; #else - typedef typename basic_socket< - Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type; + typedef typename basic_socket<Protocol, + Executor>::native_handle_type native_handle_type; #endif /// The protocol type. @@ -66,12 +81,30 @@ public: * socket needs to be opened and then connected or accepted before data can * be sent or received on it. * - * @param io_context The io_context object that the sequenced packet socket - * will use to dispatch handlers for any asynchronous operations performed on - * the socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_seq_packet_socket(const executor_type& ex) + : basic_socket<Protocol, Executor>(ex) + { + } + + /// Construct a basic_seq_packet_socket without opening it. + /** + * This constructor creates a sequenced packet socket without opening it. The + * socket needs to be opened and then connected or accepted before data can + * be sent or received on it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. */ - explicit basic_seq_packet_socket(boost::asio::io_context& io_context) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context) + template <typename ExecutionContext> + explicit basic_seq_packet_socket(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context) { } @@ -81,17 +114,40 @@ public: * needs to be connected or accepted before data can be sent or received on * it. * - * @param io_context The io_context object that the sequenced packet socket - * will use to dispatch handlers for any asynchronous operations performed on - * the socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. * * @throws boost::system::system_error Thrown on failure. */ - basic_seq_packet_socket(boost::asio::io_context& io_context, + basic_seq_packet_socket(const executor_type& ex, const protocol_type& protocol) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol) + : basic_socket<Protocol, Executor>(ex, protocol) + { + } + + /// Construct and open a basic_seq_packet_socket. + /** + * This constructor creates and opens a sequenced_packet socket. The socket + * needs to be connected or accepted before data can be sent or received on + * it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_seq_packet_socket(ExecutionContext& context, + const protocol_type& protocol, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, protocol) { } @@ -102,18 +158,43 @@ public: * it bound to the specified endpoint on the local machine. The protocol used * is the protocol associated with the given endpoint. * - * @param io_context The io_context object that the sequenced packet socket - * will use to dispatch handlers for any asynchronous operations performed on - * the socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. * * @param endpoint An endpoint on the local machine to which the sequenced * packet socket will be bound. * * @throws boost::system::system_error Thrown on failure. */ - basic_seq_packet_socket(boost::asio::io_context& io_context, + basic_seq_packet_socket(const executor_type& ex, const endpoint_type& endpoint) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint) + : basic_socket<Protocol, Executor>(ex, endpoint) + { + } + + /// Construct a basic_seq_packet_socket, opening it and binding it to the + /// given local endpoint. + /** + * This constructor creates a sequenced packet socket and automatically opens + * it bound to the specified endpoint on the local machine. The protocol used + * is the protocol associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the sequenced + * packet socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_seq_packet_socket(ExecutionContext& context, + const endpoint_type& endpoint, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, endpoint) { } @@ -122,9 +203,8 @@ public: * This constructor creates a sequenced packet socket object to hold an * existing native socket. * - * @param io_context The io_context object that the sequenced packet socket - * will use to dispatch handlers for any asynchronous operations performed on - * the socket. + * @param ex The I/O executor that the socket will use, by default, to + * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. * @@ -132,10 +212,34 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_seq_packet_socket(boost::asio::io_context& io_context, + basic_seq_packet_socket(const executor_type& ex, const protocol_type& protocol, const native_handle_type& native_socket) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>( - io_context, protocol, native_socket) + : basic_socket<Protocol, Executor>(ex, protocol, native_socket) + { + } + + /// Construct a basic_seq_packet_socket on an existing native socket. + /** + * This constructor creates a sequenced packet socket object to hold an + * existing native socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_seq_packet_socket(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_socket, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, protocol, native_socket) { } @@ -149,10 +253,11 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_seq_packet_socket(io_context&) constructor. + * constructed using the @c basic_seq_packet_socket(const executor_type&) + * constructor. */ basic_seq_packet_socket(basic_seq_packet_socket&& other) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other)) + : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -165,11 +270,12 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_seq_packet_socket(io_context&) constructor. + * constructed using the @c basic_seq_packet_socket(const executor_type&) + * constructor. */ basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other) { - basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other)); + basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } @@ -183,13 +289,16 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_seq_packet_socket(io_context&) constructor. + * constructed using the @c basic_seq_packet_socket(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - basic_seq_packet_socket( - basic_seq_packet_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other, - typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other)) + template <typename Protocol1, typename Executor1> + basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other, + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -203,14 +312,17 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_seq_packet_socket(io_context&) constructor. + * constructed using the @c basic_seq_packet_socket(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - typename enable_if<is_convertible<Protocol1, Protocol>::value, - basic_seq_packet_socket>::type& operator=( - basic_seq_packet_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other) + template <typename Protocol1, typename Executor1> + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value, + basic_seq_packet_socket& + >::type operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other) { - basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other)); + basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -252,8 +364,8 @@ public: socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().send( - this->get_implementation(), buffers, flags, ec); + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); boost::asio::detail::throw_error(ec, "send"); return s; } @@ -280,8 +392,8 @@ public: std::size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().send( - this->get_implementation(), buffers, flags, ec); + return this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); } /// Start an asynchronous send. @@ -304,9 +416,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To send a single data buffer use the @ref buffer function as follows: @@ -324,22 +436,9 @@ public: socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send(this->get_implementation(), - buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send(this->get_implementation(), - buffers, flags, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send(), handler, this, buffers, flags); } /// Receive some data on the socket. @@ -376,13 +475,8 @@ public: socket_base::message_flags& out_flags) { boost::system::error_code ec; -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, 0, out_flags, ec); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - std::size_t s = this->get_service().receive_with_flags( - this->get_implementation(), buffers, 0, out_flags, ec); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + std::size_t s = this->impl_.get_service().receive_with_flags( + this->impl_.get_implementation(), buffers, 0, out_flags, ec); boost::asio::detail::throw_error(ec, "receive"); return s; } @@ -428,13 +522,8 @@ public: socket_base::message_flags& out_flags) { boost::system::error_code ec; -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, in_flags, out_flags, ec); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - std::size_t s = this->get_service().receive_with_flags( - this->get_implementation(), buffers, in_flags, out_flags, ec); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + std::size_t s = this->impl_.get_service().receive_with_flags( + this->impl_.get_implementation(), buffers, in_flags, out_flags, ec); boost::asio::detail::throw_error(ec, "receive"); return s; } @@ -467,13 +556,8 @@ public: socket_base::message_flags in_flags, socket_base::message_flags& out_flags, boost::system::error_code& ec) { -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().receive(this->get_implementation(), - buffers, in_flags, out_flags, ec); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().receive_with_flags(this->get_implementation(), - buffers, in_flags, out_flags, ec); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return this->impl_.get_service().receive_with_flags( + this->impl_.get_implementation(), buffers, in_flags, out_flags, ec); } /// Start an asynchronous receive. @@ -500,9 +584,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To receive into a single data buffer use the @ref buffer function as @@ -521,24 +605,10 @@ public: socket_base::message_flags& out_flags, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive( - this->get_implementation(), buffers, 0, out_flags, - BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive_with_flags( - this->get_implementation(), buffers, 0, out_flags, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive_with_flags(), handler, this, + buffers, socket_base::message_flags(0), &out_flags); } /// Start an asynchronous receive. @@ -567,9 +637,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To receive into a single data buffer use the @ref buffer function as @@ -591,25 +661,49 @@ public: socket_base::message_flags& out_flags, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive( - this->get_implementation(), buffers, in_flags, out_flags, - BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive_with_flags( - this->get_implementation(), buffers, in_flags, out_flags, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive_with_flags(), handler, + this, buffers, in_flags, &out_flags); } + +private: + struct initiate_async_send + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> 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/boost/asio/basic_serial_port.hpp b/boost/asio/basic_serial_port.hpp index 2f6c8cf887..88a195a46a 100644 --- a/boost/asio/basic_serial_port.hpp +++ b/boost/asio/basic_serial_port.hpp @@ -2,7 +2,7 @@ // basic_serial_port.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -18,18 +18,29 @@ #include <boost/asio/detail/config.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ || defined(GENERATING_DOCUMENTATION) #include <string> -#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/async_result.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/detail/type_traits.hpp> #include <boost/asio/error.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> #include <boost/asio/serial_port_base.hpp> -#include <boost/asio/serial_port_service.hpp> +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_serial_port_service.hpp> +#else +# include <boost/asio/detail/reactive_serial_port_service.hpp> +#endif + +#if defined(BOOST_ASIO_HAS_MOVE) +# include <utility> +#endif // defined(BOOST_ASIO_HAS_MOVE) #include <boost/asio/detail/push_options.hpp> @@ -38,34 +49,63 @@ namespace asio { /// Provides serial port functionality. /** - * The basic_serial_port class template provides functionality that is common - * to all serial ports. + * The basic_serial_port class provides a wrapper over serial port + * functionality. * * @par Thread Safety * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename SerialPortService = serial_port_service> +template <typename Executor = executor> class basic_serial_port - : public basic_io_object<SerialPortService>, - public serial_port_base + : public serial_port_base { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + /// The native representation of a serial port. - typedef typename SerialPortService::native_handle_type native_handle_type; +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#elif defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_serial_port_service::native_handle_type + native_handle_type; +#else + typedef detail::reactive_serial_port_service::native_handle_type + native_handle_type; +#endif + + /// A basic_basic_serial_port is always the lowest layer. + typedef basic_serial_port lowest_layer_type; - /// A basic_serial_port is always the lowest layer. - typedef basic_serial_port<SerialPortService> lowest_layer_type; + /// Construct a basic_serial_port without opening it. + /** + * This constructor creates a serial port without opening it. + * + * @param ex The I/O executor that the serial port will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * serial port. + */ + explicit basic_serial_port(const executor_type& ex) + : impl_(ex) + { + } /// Construct a basic_serial_port without opening it. /** * This constructor creates a serial port without opening it. * - * @param io_context The io_context object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. + * @param context An execution context which provides the I/O executor that + * the serial port will use, by default, to dispatch handlers for any + * asynchronous operations performed on the serial port. */ - explicit basic_serial_port(boost::asio::io_context& io_context) - : basic_io_object<SerialPortService>(io_context) + template <typename ExecutionContext> + explicit basic_serial_port(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value, + basic_serial_port + >::type* = 0) + : impl_(context) { } @@ -74,18 +114,18 @@ public: * This constructor creates and opens a serial port for the specified device * name. * - * @param io_context The io_context object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. + * @param ex The I/O executor that the serial port will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * serial port. * * @param device The platform-specific device name for this serial * port. */ - explicit basic_serial_port(boost::asio::io_context& io_context, - const char* device) - : basic_io_object<SerialPortService>(io_context) + basic_serial_port(const executor_type& ex, const char* device) + : impl_(ex) { boost::system::error_code ec; - this->get_service().open(this->get_implementation(), device, ec); + impl_.get_service().open(impl_.get_implementation(), device, ec); boost::asio::detail::throw_error(ec, "open"); } @@ -94,18 +134,66 @@ public: * This constructor creates and opens a serial port for the specified device * name. * - * @param io_context The io_context object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. + * @param context An execution context which provides the I/O executor that + * the serial port will use, by default, to dispatch handlers for any + * asynchronous operations performed on the serial port. * * @param device The platform-specific device name for this serial * port. */ - explicit basic_serial_port(boost::asio::io_context& io_context, - const std::string& device) - : basic_io_object<SerialPortService>(io_context) + template <typename ExecutionContext> + basic_serial_port(ExecutionContext& context, const char* device, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { boost::system::error_code ec; - this->get_service().open(this->get_implementation(), device, ec); + impl_.get_service().open(impl_.get_implementation(), device, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param ex The I/O executor that the serial port will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * serial port. + * + * @param device The platform-specific device name for this serial + * port. + */ + basic_serial_port(const executor_type& ex, const std::string& device) + : impl_(ex) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), device, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param context An execution context which provides the I/O executor that + * the serial port will use, by default, to dispatch handlers for any + * asynchronous operations performed on the serial port. + * + * @param device The platform-specific device name for this serial + * port. + */ + template <typename ExecutionContext> + basic_serial_port(ExecutionContext& context, const std::string& device, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), device, ec); boost::asio::detail::throw_error(ec, "open"); } @@ -114,19 +202,47 @@ public: * This constructor creates a serial port object to hold an existing native * serial port. * - * @param io_context The io_context object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. + * @param ex The I/O executor that the serial port will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * serial port. * * @param native_serial_port A native serial port. * * @throws boost::system::system_error Thrown on failure. */ - basic_serial_port(boost::asio::io_context& io_context, + basic_serial_port(const executor_type& ex, const native_handle_type& native_serial_port) - : basic_io_object<SerialPortService>(io_context) + : impl_(ex) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + native_serial_port, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_serial_port on an existing native serial port. + /** + * This constructor creates a serial port object to hold an existing native + * serial port. + * + * @param context An execution context which provides the I/O executor that + * the serial port will use, by default, to dispatch handlers for any + * asynchronous operations performed on the serial port. + * + * @param native_serial_port A native serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_serial_port(ExecutionContext& context, + const native_handle_type& native_serial_port, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), native_serial_port, ec); boost::asio::detail::throw_error(ec, "assign"); } @@ -140,11 +256,11 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_serial_port(io_context&) constructor. + * constructed using the @c basic_serial_port(const executor_type&) + * constructor. */ basic_serial_port(basic_serial_port&& other) - : basic_io_object<SerialPortService>( - BOOST_ASIO_MOVE_CAST(basic_serial_port)(other)) + : impl_(std::move(other.impl_)) { } @@ -156,16 +272,32 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_serial_port(io_context&) constructor. + * constructed using the @c basic_serial_port(const executor_type&) + * constructor. */ basic_serial_port& operator=(basic_serial_port&& other) { - basic_io_object<SerialPortService>::operator=( - BOOST_ASIO_MOVE_CAST(basic_serial_port)(other)); + impl_ = std::move(other.impl_); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Destroys the serial port. + /** + * This function destroys the serial port, cancelling any outstanding + * asynchronous wait operations associated with the serial port as if by + * calling @c cancel. + */ + ~basic_serial_port() + { + } + + /// Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return impl_.get_executor(); + } + /// Get a reference to the lowest layer. /** * This function returns a reference to the lowest layer in a stack of @@ -205,7 +337,7 @@ public: void open(const std::string& device) { boost::system::error_code ec; - this->get_service().open(this->get_implementation(), device, ec); + impl_.get_service().open(impl_.get_implementation(), device, ec); boost::asio::detail::throw_error(ec, "open"); } @@ -221,7 +353,7 @@ public: BOOST_ASIO_SYNC_OP_VOID open(const std::string& device, boost::system::error_code& ec) { - this->get_service().open(this->get_implementation(), device, ec); + impl_.get_service().open(impl_.get_implementation(), device, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -236,7 +368,7 @@ public: void assign(const native_handle_type& native_serial_port) { boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), native_serial_port, ec); boost::asio::detail::throw_error(ec, "assign"); } @@ -252,7 +384,7 @@ public: BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port, boost::system::error_code& ec) { - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), native_serial_port, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -260,7 +392,7 @@ public: /// Determine whether the serial port is open. bool is_open() const { - return this->get_service().is_open(this->get_implementation()); + return impl_.get_service().is_open(impl_.get_implementation()); } /// Close the serial port. @@ -274,7 +406,7 @@ public: void close() { boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "close"); } @@ -288,7 +420,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) { - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -300,7 +432,7 @@ public: */ native_handle_type native_handle() { - return this->get_service().native_handle(this->get_implementation()); + return impl_.get_service().native_handle(impl_.get_implementation()); } /// Cancel all asynchronous operations associated with the serial port. @@ -314,7 +446,7 @@ public: void cancel() { boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel"); } @@ -328,7 +460,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) { - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -342,7 +474,7 @@ public: void send_break() { boost::system::error_code ec; - this->get_service().send_break(this->get_implementation(), ec); + impl_.get_service().send_break(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "send_break"); } @@ -355,7 +487,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID send_break(boost::system::error_code& ec) { - this->get_service().send_break(this->get_implementation(), ec); + impl_.get_service().send_break(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -378,7 +510,7 @@ public: void set_option(const SettableSerialPortOption& option) { boost::system::error_code ec; - this->get_service().set_option(this->get_implementation(), option, ec); + impl_.get_service().set_option(impl_.get_implementation(), option, ec); boost::asio::detail::throw_error(ec, "set_option"); } @@ -401,7 +533,7 @@ public: BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option, boost::system::error_code& ec) { - this->get_service().set_option(this->get_implementation(), option, ec); + impl_.get_service().set_option(impl_.get_implementation(), option, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -425,7 +557,7 @@ public: void get_option(GettableSerialPortOption& option) { boost::system::error_code ec; - this->get_service().get_option(this->get_implementation(), option, ec); + impl_.get_service().get_option(impl_.get_implementation(), option, ec); boost::asio::detail::throw_error(ec, "get_option"); } @@ -449,7 +581,7 @@ public: BOOST_ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option, boost::system::error_code& ec) { - this->get_service().get_option(this->get_implementation(), option, ec); + impl_.get_service().get_option(impl_.get_implementation(), option, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -474,7 +606,7 @@ public: * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code - * serial_port.write_some(boost::asio::buffer(data, size)); + * basic_serial_port.write_some(boost::asio::buffer(data, size)); * @endcode * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or @@ -484,8 +616,8 @@ public: std::size_t write_some(const ConstBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().write_some( - this->get_implementation(), buffers, ec); + std::size_t s = impl_.get_service().write_some( + impl_.get_implementation(), buffers, ec); boost::asio::detail::throw_error(ec, "write_some"); return s; } @@ -510,8 +642,8 @@ public: std::size_t write_some(const ConstBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().write_some( - this->get_implementation(), buffers, ec); + return impl_.get_service().write_some( + impl_.get_implementation(), buffers, ec); } /// Start an asynchronous write. @@ -532,9 +664,9 @@ public: * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all @@ -543,7 +675,8 @@ public: * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code - * serial_port.async_write_some(boost::asio::buffer(data, size), handler); + * basic_serial_port.async_write_some( + * boost::asio::buffer(data, size), handler); * @endcode * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or @@ -555,12 +688,9 @@ public: async_write_some(const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - return this->get_service().async_write_some(this->get_implementation(), - buffers, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_write_some(), handler, this, buffers); } /// Read some data from the serial port. @@ -585,7 +715,7 @@ public: * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code - * serial_port.read_some(boost::asio::buffer(data, size)); + * basic_serial_port.read_some(boost::asio::buffer(data, size)); * @endcode * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or @@ -595,8 +725,8 @@ public: std::size_t read_some(const MutableBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().read_some( - this->get_implementation(), buffers, ec); + std::size_t s = impl_.get_service().read_some( + impl_.get_implementation(), buffers, ec); boost::asio::detail::throw_error(ec, "read_some"); return s; } @@ -622,8 +752,8 @@ public: std::size_t read_some(const MutableBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().read_some( - this->get_implementation(), buffers, ec); + return impl_.get_service().read_some( + impl_.get_implementation(), buffers, ec); } /// Start an asynchronous read. @@ -644,9 +774,9 @@ public: * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the @@ -656,7 +786,8 @@ public: * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code - * serial_port.async_read_some(boost::asio::buffer(data, size), handler); + * basic_serial_port.async_read_some( + * boost::asio::buffer(data, size), handler); * @endcode * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or @@ -668,13 +799,55 @@ public: async_read_some(const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - return this->get_service().async_read_some(this->get_implementation(), - buffers, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_read_some(), handler, this, buffers); } + +private: + // Disallow copying and assignment. + basic_serial_port(const basic_serial_port&) BOOST_ASIO_DELETED; + basic_serial_port& operator=(const basic_serial_port&) BOOST_ASIO_DELETED; + + struct initiate_async_write_some + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> handler2(handler); + self->impl_.get_service().async_read_some( + self->impl_.get_implementation(), buffers, handler2.value, + self->impl_.get_implementation_executor()); + } + }; + +#if defined(BOOST_ASIO_HAS_IOCP) + detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_; +#else + detail::io_object_impl<detail::reactive_serial_port_service, Executor> impl_; +#endif }; } // namespace asio @@ -685,6 +858,4 @@ public: #endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) // || defined(GENERATING_DOCUMENTATION) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP diff --git a/boost/asio/basic_signal_set.hpp b/boost/asio/basic_signal_set.hpp index 8ca5dfa1d9..175b4f4832 100644 --- a/boost/asio/basic_signal_set.hpp +++ b/boost/asio/basic_signal_set.hpp @@ -2,7 +2,7 @@ // basic_signal_set.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,25 +17,24 @@ #include <boost/asio/detail/config.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/async_result.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> +#include <boost/asio/detail/signal_set_service.hpp> #include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/detail/type_traits.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/signal_set_service.hpp> - -#include <boost/asio/detail/push_options.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> namespace boost { namespace asio { /// Provides signal functionality. /** - * The basic_signal_set class template provides the ability to perform an - * asynchronous wait for one or more signals to occur. - * - * Most applications will use the boost::asio::signal_set typedef. + * The basic_signal_set class provides the ability to perform an asynchronous + * wait for one or more signals to occur. * * @par Thread Safety * @e Distinct @e objects: Safe.@n @@ -57,7 +56,7 @@ namespace asio { * ... * * // Construct a signal set registered for process termination. - * boost::asio::signal_set signals(io_context, SIGINT, SIGTERM); + * boost::asio::signal_set signals(my_context, SIGINT, SIGTERM); * * // Start an asynchronous wait for one of the signals to occur. * signals.async_wait(handler); @@ -92,20 +91,40 @@ namespace asio { * that any signals registered using signal_set objects are unblocked in at * least one thread. */ -template <typename SignalSetService = signal_set_service> +template <typename Executor = executor> class basic_signal_set - : public basic_io_object<SignalSetService> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Construct a signal set without adding any signals. + /** + * This constructor creates a signal set without registering for any signals. + * + * @param ex The I/O executor that the signal set will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * signal set. + */ + explicit basic_signal_set(const executor_type& ex) + : impl_(ex) + { + } + /// Construct a signal set without adding any signals. /** * This constructor creates a signal set without registering for any signals. * - * @param io_context The io_context object that the signal set will use to - * dispatch handlers for any asynchronous operations performed on the set. + * @param context An execution context which provides the I/O executor that + * the signal set will use, by default, to dispatch handlers for any + * asynchronous operations performed on the signal set. */ - explicit basic_signal_set(boost::asio::io_context& io_context) - : basic_io_object<SignalSetService>(io_context) + template <typename ExecutionContext> + explicit basic_signal_set(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { } @@ -113,20 +132,47 @@ public: /** * This constructor creates a signal set and registers for one signal. * - * @param io_context The io_context object that the signal set will use to - * dispatch handlers for any asynchronous operations performed on the set. + * @param ex The I/O executor that the signal set will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * signal set. * * @param signal_number_1 The signal number to be added. * * @note This constructor is equivalent to performing: - * @code boost::asio::signal_set signals(io_context); + * @code boost::asio::signal_set signals(ex); * signals.add(signal_number_1); @endcode */ - basic_signal_set(boost::asio::io_context& io_context, int signal_number_1) - : basic_io_object<SignalSetService>(io_context) + basic_signal_set(const executor_type& ex, int signal_number_1) + : impl_(ex) { boost::system::error_code ec; - this->get_service().add(this->get_implementation(), signal_number_1, ec); + impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); + boost::asio::detail::throw_error(ec, "add"); + } + + /// Construct a signal set and add one signal. + /** + * This constructor creates a signal set and registers for one signal. + * + * @param context An execution context which provides the I/O executor that + * the signal set will use, by default, to dispatch handlers for any + * asynchronous operations performed on the signal set. + * + * @param signal_number_1 The signal number to be added. + * + * @note This constructor is equivalent to performing: + * @code boost::asio::signal_set signals(context); + * signals.add(signal_number_1); @endcode + */ + template <typename ExecutionContext> + basic_signal_set(ExecutionContext& context, int signal_number_1, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); boost::asio::detail::throw_error(ec, "add"); } @@ -134,26 +180,59 @@ public: /** * This constructor creates a signal set and registers for two signals. * - * @param io_context The io_context object that the signal set will use to - * dispatch handlers for any asynchronous operations performed on the set. + * @param ex The I/O executor that the signal set will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * signal set. * * @param signal_number_1 The first signal number to be added. * * @param signal_number_2 The second signal number to be added. * * @note This constructor is equivalent to performing: - * @code boost::asio::signal_set signals(io_context); + * @code boost::asio::signal_set signals(ex); * signals.add(signal_number_1); * signals.add(signal_number_2); @endcode */ - basic_signal_set(boost::asio::io_context& io_context, int signal_number_1, + basic_signal_set(const executor_type& ex, int signal_number_1, int signal_number_2) - : basic_io_object<SignalSetService>(io_context) + : impl_(ex) + { + boost::system::error_code ec; + impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); + boost::asio::detail::throw_error(ec, "add"); + impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec); + boost::asio::detail::throw_error(ec, "add"); + } + + /// Construct a signal set and add two signals. + /** + * This constructor creates a signal set and registers for two signals. + * + * @param context An execution context which provides the I/O executor that + * the signal set will use, by default, to dispatch handlers for any + * asynchronous operations performed on the signal set. + * + * @param signal_number_1 The first signal number to be added. + * + * @param signal_number_2 The second signal number to be added. + * + * @note This constructor is equivalent to performing: + * @code boost::asio::signal_set signals(context); + * signals.add(signal_number_1); + * signals.add(signal_number_2); @endcode + */ + template <typename ExecutionContext> + basic_signal_set(ExecutionContext& context, int signal_number_1, + int signal_number_2, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { boost::system::error_code ec; - this->get_service().add(this->get_implementation(), signal_number_1, ec); + impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); boost::asio::detail::throw_error(ec, "add"); - this->get_service().add(this->get_implementation(), signal_number_2, ec); + impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec); boost::asio::detail::throw_error(ec, "add"); } @@ -161,8 +240,9 @@ public: /** * This constructor creates a signal set and registers for three signals. * - * @param io_context The io_context object that the signal set will use to - * dispatch handlers for any asynchronous operations performed on the set. + * @param ex The I/O executor that the signal set will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * signal set. * * @param signal_number_1 The first signal number to be added. * @@ -171,24 +251,77 @@ public: * @param signal_number_3 The third signal number to be added. * * @note This constructor is equivalent to performing: - * @code boost::asio::signal_set signals(io_context); + * @code boost::asio::signal_set signals(ex); * signals.add(signal_number_1); * signals.add(signal_number_2); * signals.add(signal_number_3); @endcode */ - basic_signal_set(boost::asio::io_context& io_context, int signal_number_1, + basic_signal_set(const executor_type& ex, int signal_number_1, int signal_number_2, int signal_number_3) - : basic_io_object<SignalSetService>(io_context) + : impl_(ex) { boost::system::error_code ec; - this->get_service().add(this->get_implementation(), signal_number_1, ec); + impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); boost::asio::detail::throw_error(ec, "add"); - this->get_service().add(this->get_implementation(), signal_number_2, ec); + impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec); boost::asio::detail::throw_error(ec, "add"); - this->get_service().add(this->get_implementation(), signal_number_3, ec); + impl_.get_service().add(impl_.get_implementation(), signal_number_3, ec); boost::asio::detail::throw_error(ec, "add"); } + /// Construct a signal set and add three signals. + /** + * This constructor creates a signal set and registers for three signals. + * + * @param context An execution context which provides the I/O executor that + * the signal set will use, by default, to dispatch handlers for any + * asynchronous operations performed on the signal set. + * + * @param signal_number_1 The first signal number to be added. + * + * @param signal_number_2 The second signal number to be added. + * + * @param signal_number_3 The third signal number to be added. + * + * @note This constructor is equivalent to performing: + * @code boost::asio::signal_set signals(context); + * signals.add(signal_number_1); + * signals.add(signal_number_2); + * signals.add(signal_number_3); @endcode + */ + template <typename ExecutionContext> + basic_signal_set(ExecutionContext& context, int signal_number_1, + int signal_number_2, int signal_number_3, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec); + boost::asio::detail::throw_error(ec, "add"); + impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec); + boost::asio::detail::throw_error(ec, "add"); + impl_.get_service().add(impl_.get_implementation(), signal_number_3, ec); + boost::asio::detail::throw_error(ec, "add"); + } + + /// Destroys the signal set. + /** + * This function destroys the signal set, cancelling any outstanding + * asynchronous wait operations associated with the signal set as if by + * calling @c cancel. + */ + ~basic_signal_set() + { + } + + /// Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return impl_.get_executor(); + } + /// Add a signal to a signal_set. /** * This function adds the specified signal to the set. It has no effect if the @@ -201,7 +334,7 @@ public: void add(int signal_number) { boost::system::error_code ec; - this->get_service().add(this->get_implementation(), signal_number, ec); + impl_.get_service().add(impl_.get_implementation(), signal_number, ec); boost::asio::detail::throw_error(ec, "add"); } @@ -214,9 +347,10 @@ public: * * @param ec Set to indicate what error occurred, if any. */ - BOOST_ASIO_SYNC_OP_VOID add(int signal_number, boost::system::error_code& ec) + BOOST_ASIO_SYNC_OP_VOID add(int signal_number, + boost::system::error_code& ec) { - this->get_service().add(this->get_implementation(), signal_number, ec); + impl_.get_service().add(impl_.get_implementation(), signal_number, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -235,7 +369,7 @@ public: void remove(int signal_number) { boost::system::error_code ec; - this->get_service().remove(this->get_implementation(), signal_number, ec); + impl_.get_service().remove(impl_.get_implementation(), signal_number, ec); boost::asio::detail::throw_error(ec, "remove"); } @@ -254,7 +388,7 @@ public: BOOST_ASIO_SYNC_OP_VOID remove(int signal_number, boost::system::error_code& ec) { - this->get_service().remove(this->get_implementation(), signal_number, ec); + impl_.get_service().remove(impl_.get_implementation(), signal_number, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -270,7 +404,7 @@ public: void clear() { boost::system::error_code ec; - this->get_service().clear(this->get_implementation(), ec); + impl_.get_service().clear(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "clear"); } @@ -285,7 +419,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID clear(boost::system::error_code& ec) { - this->get_service().clear(this->get_implementation(), ec); + impl_.get_service().clear(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -313,7 +447,7 @@ public: void cancel() { boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel"); } @@ -340,7 +474,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) { - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -365,29 +499,45 @@ public: * int signal_number // Indicates which signal occurred. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename SignalHandler> BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler, void (boost::system::error_code, int)) async_wait(BOOST_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. - BOOST_ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check; - - return this->get_service().async_wait(this->get_implementation(), - BOOST_ASIO_MOVE_CAST(SignalHandler)(handler)); + return async_initiate<SignalHandler, void (boost::system::error_code, int)>( + initiate_async_wait(), handler, this); } + +private: + // Disallow copying and assignment. + basic_signal_set(const basic_signal_set&) BOOST_ASIO_DELETED; + basic_signal_set& operator=(const basic_signal_set&) BOOST_ASIO_DELETED; + + struct initiate_async_wait + { + template <typename SignalHandler> + void operator()(BOOST_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. + BOOST_ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check; + + detail::non_const_lvalue<SignalHandler> handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), handler2.value, + self->impl_.get_implementation_executor()); + } + }; + + detail::io_object_impl<detail::signal_set_service, Executor> impl_; }; } // namespace asio } // namespace boost -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_BASIC_SIGNAL_SET_HPP diff --git a/boost/asio/basic_socket.hpp b/boost/asio/basic_socket.hpp index ed22cd2b79..4f15f58a5c 100644 --- a/boost/asio/basic_socket.hpp +++ b/boost/asio/basic_socket.hpp @@ -2,7 +2,7 @@ // basic_socket.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,36 +17,43 @@ #include <boost/asio/detail/config.hpp> #include <boost/asio/async_result.hpp> -#include <boost/asio/basic_io_object.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/error.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> #include <boost/asio/post.hpp> #include <boost/asio/socket_base.hpp> +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include <boost/asio/detail/null_socket_service.hpp> +#elif defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_socket_service.hpp> +#else +# include <boost/asio/detail/reactive_socket_service.hpp> +#endif + #if defined(BOOST_ASIO_HAS_MOVE) # include <utility> #endif // defined(BOOST_ASIO_HAS_MOVE) -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/winrt_ssocket_service.hpp> -# define BOOST_ASIO_SVC_T detail::winrt_ssocket_service<Protocol> -# elif defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_socket_service.hpp> -# define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol> -# else -# include <boost/asio/detail/reactive_socket_service.hpp> -# define BOOST_ASIO_SVC_T detail::reactive_socket_service<Protocol> -# endif -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { +#if !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_SOCKET_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Protocol, typename Executor = executor> +class basic_socket; + +#endif // !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL) + /// Provides socket functionality. /** * The basic_socket class template provides functionality that is common to both @@ -56,20 +63,34 @@ namespace asio { * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM> +template <typename Protocol, typename Executor> class basic_socket - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>, - public socket_base + : public socket_base { public: /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_socket<Protocol, Executor1> other; + }; /// The native representation of a socket. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type; +#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef typename detail::null_socket_service< + Protocol>::native_handle_type native_handle_type; +#elif defined(BOOST_ASIO_HAS_IOCP) + typedef typename detail::win_iocp_socket_service< + Protocol>::native_handle_type native_handle_type; #else - typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type; + typedef typename detail::reactive_socket_service< + Protocol>::native_handle_type native_handle_type; #endif /// The protocol type. @@ -80,18 +101,35 @@ public: #if !defined(BOOST_ASIO_NO_EXTENSIONS) /// A basic_socket is always the lowest layer. - typedef basic_socket<Protocol BOOST_ASIO_SVC_TARG> lowest_layer_type; + typedef basic_socket<Protocol, Executor> lowest_layer_type; #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) /// Construct a basic_socket without opening it. /** * This constructor creates a socket without opening it. * - * @param io_context The io_context object that the socket will use to + * @param ex The I/O executor that the socket will use, by default, to * dispatch handlers for any asynchronous operations performed on the socket. */ - explicit basic_socket(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + explicit basic_socket(const executor_type& ex) + : impl_(ex) + { + } + + /// Construct a basic_socket without opening it. + /** + * This constructor creates a socket without opening it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + */ + template <typename ExecutionContext> + explicit basic_socket(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { } @@ -99,19 +137,42 @@ public: /** * This constructor creates and opens a socket. * - * @param io_context The io_context object that the socket will use to + * @param ex The I/O executor that the socket will use, by default, to * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. * * @throws boost::system::system_error Thrown on failure. */ - basic_socket(boost::asio::io_context& io_context, - const protocol_type& protocol) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + basic_socket(const executor_type& ex, const protocol_type& protocol) + : impl_(ex) { boost::system::error_code ec; - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_socket. + /** + * This constructor creates and opens a socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_socket(ExecutionContext& context, const protocol_type& protocol, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); boost::asio::detail::throw_error(ec, "open"); } @@ -122,7 +183,7 @@ public: * specified endpoint on the local machine. The protocol used is the protocol * associated with the given endpoint. * - * @param io_context The io_context object that the socket will use to + * @param ex The I/O executor that the socket will use, by default, to * dispatch handlers for any asynchronous operations performed on the socket. * * @param endpoint An endpoint on the local machine to which the socket will @@ -130,15 +191,45 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_socket(boost::asio::io_context& io_context, - const endpoint_type& endpoint) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + basic_socket(const executor_type& ex, const endpoint_type& endpoint) + : impl_(ex) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Construct a basic_socket, opening it and binding it to the given local + /// endpoint. + /** + * This constructor creates a socket and automatically opens it bound to the + * specified endpoint on the local machine. The protocol used is the protocol + * associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_socket(ExecutionContext& context, const endpoint_type& endpoint, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { boost::system::error_code ec; const protocol_type protocol = endpoint.protocol(); - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); boost::asio::detail::throw_error(ec, "open"); - this->get_service().bind(this->get_implementation(), endpoint, ec); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); boost::asio::detail::throw_error(ec, "bind"); } @@ -146,7 +237,7 @@ public: /** * This constructor creates a socket object to hold an existing native socket. * - * @param io_context The io_context object that the socket will use to + * @param ex The I/O executor that the socket will use, by default, to * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. @@ -155,12 +246,40 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_socket(boost::asio::io_context& io_context, - const protocol_type& protocol, const native_handle_type& native_socket) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + basic_socket(const executor_type& ex, const protocol_type& protocol, + const native_handle_type& native_socket) + : impl_(ex) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_socket on an existing native socket. + /** + * This constructor creates a socket object to hold an existing native socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_socket(ExecutionContext& context, const protocol_type& protocol, + const native_handle_type& native_socket, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), protocol, native_socket, ec); boost::asio::detail::throw_error(ec, "assign"); } @@ -174,10 +293,10 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_socket(io_context&) constructor. + * constructed using the @c basic_socket(const executor_type&) constructor. */ basic_socket(basic_socket&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) + : impl_(std::move(other.impl_)) { } @@ -189,16 +308,16 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_socket(io_context&) constructor. + * constructed using the @c basic_socket(const executor_type&) constructor. */ basic_socket& operator=(basic_socket&& other) { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); + impl_ = std::move(other.impl_); return *this; } // All sockets have access to each other's implementations. - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> + template <typename Protocol1, typename Executor1> friend class basic_socket; /// Move-construct a basic_socket from a socket of another protocol type. @@ -209,13 +328,15 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_socket(io_context&) constructor. + * constructed using the @c basic_socket(const executor_type&) constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - basic_socket(basic_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other, - typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) - : basic_io_object<BOOST_ASIO_SVC_T>( - other.get_service(), other.get_implementation()) + template <typename Protocol1, typename Executor1> + basic_socket(basic_socket<Protocol1, Executor1>&& other, + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value + >::type* = 0) + : impl_(std::move(other.impl_)) { } @@ -227,58 +348,26 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_socket(io_context&) constructor. + * constructed using the @c basic_socket(const executor_type&) constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - typename enable_if<is_convertible<Protocol1, Protocol>::value, - basic_socket>::type& operator=( - basic_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other) + template <typename Protocol1, typename Executor1> + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value, + basic_socket& + >::type operator=(basic_socket<Protocol1, Executor1> && other) { basic_socket tmp(std::move(other)); - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp)); + impl_ = std::move(tmp.impl_); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - // These functions are provided by basic_io_object<>. -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Get the executor associated with the object. executor_type get_executor() BOOST_ASIO_NOEXCEPT { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); + return impl_.get_executor(); } -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) #if !defined(BOOST_ASIO_NO_EXTENSIONS) /// Get a reference to the lowest layer. @@ -320,14 +409,14 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * socket.open(boost::asio::ip::tcp::v4()); * @endcode */ void open(const protocol_type& protocol = protocol_type()) { boost::system::error_code ec; - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); boost::asio::detail::throw_error(ec, "open"); } @@ -341,7 +430,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * boost::system::error_code ec; * socket.open(boost::asio::ip::tcp::v4(), ec); * if (ec) @@ -353,7 +442,7 @@ public: BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, boost::system::error_code& ec) { - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -371,7 +460,7 @@ public: const native_handle_type& native_socket) { boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), protocol, native_socket, ec); boost::asio::detail::throw_error(ec, "assign"); } @@ -389,7 +478,7 @@ public: BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, const native_handle_type& native_socket, boost::system::error_code& ec) { - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), protocol, native_socket, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -397,7 +486,7 @@ public: /// Determine whether the socket is open. bool is_open() const { - return this->get_service().is_open(this->get_implementation()); + return impl_.get_service().is_open(impl_.get_implementation()); } /// Close the socket. @@ -415,7 +504,7 @@ public: void close() { boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "close"); } @@ -430,7 +519,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::system::error_code ec; * socket.close(ec); @@ -445,7 +534,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) { - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -471,8 +560,8 @@ public: native_handle_type release() { boost::system::error_code ec; - native_handle_type s = this->get_service().release( - this->get_implementation(), ec); + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "release"); return s; } @@ -498,7 +587,7 @@ public: #endif native_handle_type release(boost::system::error_code& ec) { - return this->get_service().release(this->get_implementation(), ec); + return impl_.get_service().release(impl_.get_implementation(), ec); } /// Get the native socket representation. @@ -509,7 +598,7 @@ public: */ native_handle_type native_handle() { - return this->get_service().native_handle(this->get_implementation()); + return impl_.get_service().native_handle(impl_.get_implementation()); } /// Cancel all asynchronous operations associated with the socket. @@ -556,7 +645,7 @@ public: void cancel() { boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel"); } @@ -603,7 +692,7 @@ public: #endif BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) { - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -620,7 +709,7 @@ public: bool at_mark() const { boost::system::error_code ec; - bool b = this->get_service().at_mark(this->get_implementation(), ec); + bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "at_mark"); return b; } @@ -637,7 +726,7 @@ public: */ bool at_mark(boost::system::error_code& ec) const { - return this->get_service().at_mark(this->get_implementation(), ec); + return impl_.get_service().at_mark(impl_.get_implementation(), ec); } /// Determine the number of bytes available for reading. @@ -653,8 +742,8 @@ public: std::size_t available() const { boost::system::error_code ec; - std::size_t s = this->get_service().available( - this->get_implementation(), ec); + std::size_t s = impl_.get_service().available( + impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "available"); return s; } @@ -671,7 +760,7 @@ public: */ std::size_t available(boost::system::error_code& ec) const { - return this->get_service().available(this->get_implementation(), ec); + return impl_.get_service().available(impl_.get_implementation(), ec); } /// Bind the socket to the given local endpoint. @@ -686,7 +775,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * socket.open(boost::asio::ip::tcp::v4()); * socket.bind(boost::asio::ip::tcp::endpoint( * boost::asio::ip::tcp::v4(), 12345)); @@ -695,7 +784,7 @@ public: void bind(const endpoint_type& endpoint) { boost::system::error_code ec; - this->get_service().bind(this->get_implementation(), endpoint, ec); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); boost::asio::detail::throw_error(ec, "bind"); } @@ -711,7 +800,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * socket.open(boost::asio::ip::tcp::v4()); * boost::system::error_code ec; * socket.bind(boost::asio::ip::tcp::endpoint( @@ -725,7 +814,7 @@ public: BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, boost::system::error_code& ec) { - this->get_service().bind(this->get_implementation(), endpoint, ec); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -746,7 +835,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * boost::asio::ip::tcp::endpoint endpoint( * boost::asio::ip::address::from_string("1.2.3.4"), 12345); * socket.connect(endpoint); @@ -757,11 +846,11 @@ public: boost::system::error_code ec; if (!is_open()) { - this->get_service().open(this->get_implementation(), + impl_.get_service().open(impl_.get_implementation(), peer_endpoint.protocol(), ec); boost::asio::detail::throw_error(ec, "connect"); } - this->get_service().connect(this->get_implementation(), peer_endpoint, ec); + impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); boost::asio::detail::throw_error(ec, "connect"); } @@ -782,7 +871,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * boost::asio::ip::tcp::endpoint endpoint( * boost::asio::ip::address::from_string("1.2.3.4"), 12345); * boost::system::error_code ec; @@ -798,7 +887,7 @@ public: { if (!is_open()) { - this->get_service().open(this->get_implementation(), + impl_.get_service().open(impl_.get_implementation(), peer_endpoint.protocol(), ec); if (ec) { @@ -806,7 +895,7 @@ public: } } - this->get_service().connect(this->get_implementation(), peer_endpoint, ec); + impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -829,9 +918,9 @@ public: * const boost::system::error_code& error // Result of operation * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -845,7 +934,7 @@ public: * * ... * - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * boost::asio::ip::tcp::endpoint endpoint( * boost::asio::ip::address::from_string("1.2.3.4"), 12345); * socket.async_connect(endpoint, connect_handler); @@ -857,42 +946,15 @@ public: async_connect(const endpoint_type& peer_endpoint, BOOST_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. - BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; - + boost::system::error_code open_ec; if (!is_open()) { - boost::system::error_code ec; const protocol_type protocol = peer_endpoint.protocol(); - this->get_service().open(this->get_implementation(), protocol, ec); - if (ec) - { - async_completion<ConnectHandler, - void (boost::system::error_code)> init(handler); - - boost::asio::post(this->get_executor(), - boost::asio::detail::bind_handler( - BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE( - ConnectHandler, void (boost::system::error_code)))( - init.completion_handler), ec)); - - return init.result.get(); - } + impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); } -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_connect(this->get_implementation(), - peer_endpoint, BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ConnectHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_connect( - this->get_implementation(), peer_endpoint, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ConnectHandler, void (boost::system::error_code)>( + initiate_async_connect(), handler, this, peer_endpoint, open_ec); } /// Set an option on the socket. @@ -923,7 +985,7 @@ public: * @par Example * Setting the IPPROTO_TCP/TCP_NODELAY option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::no_delay option(true); * socket.set_option(option); @@ -933,7 +995,7 @@ public: void set_option(const SettableSocketOption& option) { boost::system::error_code ec; - this->get_service().set_option(this->get_implementation(), option, ec); + impl_.get_service().set_option(impl_.get_implementation(), option, ec); boost::asio::detail::throw_error(ec, "set_option"); } @@ -965,7 +1027,7 @@ public: * @par Example * Setting the IPPROTO_TCP/TCP_NODELAY option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::no_delay option(true); * boost::system::error_code ec; @@ -980,7 +1042,7 @@ public: BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, boost::system::error_code& ec) { - this->get_service().set_option(this->get_implementation(), option, ec); + impl_.get_service().set_option(impl_.get_implementation(), option, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1012,7 +1074,7 @@ public: * @par Example * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::socket::keep_alive option; * socket.get_option(option); @@ -1023,7 +1085,7 @@ public: void get_option(GettableSocketOption& option) const { boost::system::error_code ec; - this->get_service().get_option(this->get_implementation(), option, ec); + impl_.get_service().get_option(impl_.get_implementation(), option, ec); boost::asio::detail::throw_error(ec, "get_option"); } @@ -1055,7 +1117,7 @@ public: * @par Example * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::socket::keep_alive option; * boost::system::error_code ec; @@ -1071,7 +1133,7 @@ public: BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, boost::system::error_code& ec) const { - this->get_service().get_option(this->get_implementation(), option, ec); + impl_.get_service().get_option(impl_.get_implementation(), option, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1090,7 +1152,7 @@ public: * @par Example * Getting the number of bytes ready to read: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::socket::bytes_readable command; * socket.io_control(command); @@ -1101,7 +1163,7 @@ public: void io_control(IoControlCommand& command) { boost::system::error_code ec; - this->get_service().io_control(this->get_implementation(), command, ec); + impl_.get_service().io_control(impl_.get_implementation(), command, ec); boost::asio::detail::throw_error(ec, "io_control"); } @@ -1120,7 +1182,7 @@ public: * @par Example * Getting the number of bytes ready to read: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::socket::bytes_readable command; * boost::system::error_code ec; @@ -1136,7 +1198,7 @@ public: BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, boost::system::error_code& ec) { - this->get_service().io_control(this->get_implementation(), command, ec); + impl_.get_service().io_control(impl_.get_implementation(), command, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1153,7 +1215,7 @@ public: */ bool non_blocking() const { - return this->get_service().non_blocking(this->get_implementation()); + return impl_.get_service().non_blocking(impl_.get_implementation()); } /// Sets the non-blocking mode of the socket. @@ -1172,7 +1234,7 @@ public: void non_blocking(bool mode) { boost::system::error_code ec; - this->get_service().non_blocking(this->get_implementation(), mode, ec); + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); boost::asio::detail::throw_error(ec, "non_blocking"); } @@ -1192,7 +1254,7 @@ public: BOOST_ASIO_SYNC_OP_VOID non_blocking( bool mode, boost::system::error_code& ec) { - this->get_service().non_blocking(this->get_implementation(), mode, ec); + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1282,7 +1344,7 @@ public: */ bool native_non_blocking() const { - return this->get_service().native_non_blocking(this->get_implementation()); + return impl_.get_service().native_non_blocking(impl_.get_implementation()); } /// Sets the non-blocking mode of the native socket implementation. @@ -1373,8 +1435,8 @@ public: void native_non_blocking(bool mode) { boost::system::error_code ec; - this->get_service().native_non_blocking( - this->get_implementation(), mode, ec); + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); boost::asio::detail::throw_error(ec, "native_non_blocking"); } @@ -1466,8 +1528,8 @@ public: BOOST_ASIO_SYNC_OP_VOID native_non_blocking( bool mode, boost::system::error_code& ec) { - this->get_service().native_non_blocking( - this->get_implementation(), mode, ec); + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1481,7 +1543,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); * @endcode @@ -1489,8 +1551,8 @@ public: endpoint_type local_endpoint() const { boost::system::error_code ec; - endpoint_type ep = this->get_service().local_endpoint( - this->get_implementation(), ec); + endpoint_type ep = impl_.get_service().local_endpoint( + impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "local_endpoint"); return ep; } @@ -1506,7 +1568,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::system::error_code ec; * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); @@ -1518,7 +1580,7 @@ public: */ endpoint_type local_endpoint(boost::system::error_code& ec) const { - return this->get_service().local_endpoint(this->get_implementation(), ec); + return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); } /// Get the remote endpoint of the socket. @@ -1531,7 +1593,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); * @endcode @@ -1539,8 +1601,8 @@ public: endpoint_type remote_endpoint() const { boost::system::error_code ec; - endpoint_type ep = this->get_service().remote_endpoint( - this->get_implementation(), ec); + endpoint_type ep = impl_.get_service().remote_endpoint( + impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "remote_endpoint"); return ep; } @@ -1556,7 +1618,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::system::error_code ec; * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); @@ -1568,7 +1630,7 @@ public: */ endpoint_type remote_endpoint(boost::system::error_code& ec) const { - return this->get_service().remote_endpoint(this->get_implementation(), ec); + return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec); } /// Disable sends or receives on the socket. @@ -1583,7 +1645,7 @@ public: * @par Example * Shutting down the send side of the socket: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); * @endcode @@ -1591,7 +1653,7 @@ public: void shutdown(shutdown_type what) { boost::system::error_code ec; - this->get_service().shutdown(this->get_implementation(), what, ec); + impl_.get_service().shutdown(impl_.get_implementation(), what, ec); boost::asio::detail::throw_error(ec, "shutdown"); } @@ -1607,7 +1669,7 @@ public: * @par Example * Shutting down the send side of the socket: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::system::error_code ec; * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); @@ -1620,7 +1682,7 @@ public: BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, boost::system::error_code& ec) { - this->get_service().shutdown(this->get_implementation(), what, ec); + impl_.get_service().shutdown(impl_.get_implementation(), what, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1635,7 +1697,7 @@ public: * @par Example * Waiting for a socket to become readable. * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * socket.wait(boost::asio::ip::tcp::socket::wait_read); * @endcode @@ -1643,7 +1705,7 @@ public: void wait(wait_type w) { boost::system::error_code ec; - this->get_service().wait(this->get_implementation(), w, ec); + impl_.get_service().wait(impl_.get_implementation(), w, ec); boost::asio::detail::throw_error(ec, "wait"); } @@ -1660,7 +1722,7 @@ public: * @par Example * Waiting for a socket to become readable. * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::system::error_code ec; * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); @@ -1668,7 +1730,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) { - this->get_service().wait(this->get_implementation(), w, ec); + impl_.get_service().wait(impl_.get_implementation(), w, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1687,9 +1749,9 @@ public: * const boost::system::error_code& error // Result of operation * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -1703,7 +1765,7 @@ public: * * ... * - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); * @endcode @@ -1713,22 +1775,8 @@ public: void (boost::system::error_code)) async_wait(wait_type w, BOOST_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. - BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_wait(this->get_implementation(), - w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_wait(this->get_implementation(), - w, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WaitHandler, void (boost::system::error_code)>( + initiate_async_wait(), handler, this, w); } protected: @@ -1741,10 +1789,65 @@ protected: { } +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + detail::io_object_impl< + detail::null_socket_service<Protocol>, Executor> impl_; +#elif defined(BOOST_ASIO_HAS_IOCP) + detail::io_object_impl< + detail::win_iocp_socket_service<Protocol>, Executor> impl_; +#else + detail::io_object_impl< + detail::reactive_socket_service<Protocol>, Executor> impl_; +#endif + private: // Disallow copying and assignment. basic_socket(const basic_socket&) BOOST_ASIO_DELETED; basic_socket& operator=(const basic_socket&) BOOST_ASIO_DELETED; + + struct initiate_async_connect + { + template <typename ConnectHandler> + void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler, + basic_socket* self, const endpoint_type& peer_endpoint, + const boost::system::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. + BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; + + if (open_ec) + { + boost::asio::post(self->impl_.get_executor(), + boost::asio::detail::bind_handler( + BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); + } + else + { + detail::non_const_lvalue<ConnectHandler> 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 <typename WaitHandler> + void operator()(BOOST_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. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue<WaitHandler> handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), w, handler2.value, + self->impl_.get_implementation_executor()); + } + }; }; } // namespace asio @@ -1752,8 +1855,4 @@ private: #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# undef BOOST_ASIO_SVC_T -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_BASIC_SOCKET_HPP diff --git a/boost/asio/basic_socket_acceptor.hpp b/boost/asio/basic_socket_acceptor.hpp index 8afdfd3009..12613b8260 100644 --- a/boost/asio/basic_socket_acceptor.hpp +++ b/boost/asio/basic_socket_acceptor.hpp @@ -2,7 +2,7 @@ // basic_socket_acceptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -16,38 +16,43 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> -#include <boost/asio/basic_io_object.hpp> #include <boost/asio/basic_socket.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/error.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> #include <boost/asio/socket_base.hpp> +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include <boost/asio/detail/null_socket_service.hpp> +#elif defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_socket_service.hpp> +#else +# include <boost/asio/detail/reactive_socket_service.hpp> +#endif + #if defined(BOOST_ASIO_HAS_MOVE) # include <utility> #endif // defined(BOOST_ASIO_HAS_MOVE) -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/socket_acceptor_service.hpp> -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/null_socket_service.hpp> -# define BOOST_ASIO_SVC_T detail::null_socket_service<Protocol> -# elif defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_socket_service.hpp> -# define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol> -# else -# include <boost/asio/detail/reactive_socket_service.hpp> -# define BOOST_ASIO_SVC_T detail::reactive_socket_service<Protocol> -# endif -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { +#if !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL) +#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Protocol, typename Executor = executor> +class basic_socket_acceptor; + +#endif // !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL) + /// Provides the ability to accept new connections. /** * The basic_socket_acceptor class template is used for accepting new socket @@ -60,7 +65,7 @@ namespace asio { * @par Example * Opening a socket acceptor with the SO_REUSEADDR option enabled: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); * acceptor.open(endpoint.protocol()); * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); @@ -68,21 +73,26 @@ namespace asio { * acceptor.listen(); * @endcode */ -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= socket_acceptor_service<Protocol>)> +template <typename Protocol, typename Executor> class basic_socket_acceptor - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>, - public socket_base + : public socket_base { public: /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; + typedef Executor executor_type; /// The native representation of an acceptor. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type; +#elif defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef typename detail::null_socket_service< + Protocol>::native_handle_type native_handle_type; +#elif defined(BOOST_ASIO_HAS_IOCP) + typedef typename detail::win_iocp_socket_service< + Protocol>::native_handle_type native_handle_type; #else - typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type; + typedef typename detail::reactive_socket_service< + Protocol>::native_handle_type native_handle_type; #endif /// The protocol type. @@ -97,12 +107,31 @@ public: * connections. The open() function must be called before the acceptor can * accept new socket connections. * - * @param io_context The io_context object that the acceptor will use to + * @param ex The I/O executor that the acceptor will use, by default, to * dispatch handlers for any asynchronous operations performed on the * acceptor. */ - explicit basic_socket_acceptor(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + explicit basic_socket_acceptor(const executor_type& ex) + : impl_(ex) + { + } + + /// Construct an acceptor without opening it. + /** + * This constructor creates an acceptor without opening it to listen for new + * connections. The open() function must be called before the acceptor can + * accept new socket connections. + * + * @param context An execution context which provides the I/O executor that + * the acceptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the acceptor. + */ + template <typename ExecutionContext> + explicit basic_socket_acceptor(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { } @@ -110,7 +139,7 @@ public: /** * This constructor creates an acceptor and automatically opens it. * - * @param io_context The io_context object that the acceptor will use to + * @param ex The I/O executor that the acceptor will use, by default, to * dispatch handlers for any asynchronous operations performed on the * acceptor. * @@ -118,12 +147,36 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_socket_acceptor(boost::asio::io_context& io_context, - const protocol_type& protocol) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol) + : impl_(ex) + { + boost::system::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct an open acceptor. + /** + * This constructor creates an acceptor and automatically opens it. + * + * @param context An execution context which provides the I/O executor that + * the acceptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_socket_acceptor(ExecutionContext& context, + const protocol_type& protocol, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { boost::system::error_code ec; - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); boost::asio::detail::throw_error(ec, "open"); } @@ -132,7 +185,7 @@ public: * This constructor creates an acceptor and automatically opens it to listen * for new connections on the specified endpoint. * - * @param io_context The io_context object that the acceptor will use to + * @param ex The I/O executor that the acceptor will use, by default, to * dispatch handlers for any asynchronous operations performed on the * acceptor. * @@ -146,31 +199,83 @@ public: * * @note This constructor is equivalent to the following code: * @code - * basic_socket_acceptor<Protocol> acceptor(io_context); + * basic_socket_acceptor<Protocol> acceptor(my_context); * acceptor.open(endpoint.protocol()); * if (reuse_addr) * acceptor.set_option(socket_base::reuse_address(true)); * acceptor.bind(endpoint); - * acceptor.listen(listen_backlog); + * acceptor.listen(); * @endcode */ - basic_socket_acceptor(boost::asio::io_context& io_context, + basic_socket_acceptor(const executor_type& ex, const endpoint_type& endpoint, bool reuse_addr = true) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + : impl_(ex) { boost::system::error_code ec; const protocol_type protocol = endpoint.protocol(); - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); boost::asio::detail::throw_error(ec, "open"); if (reuse_addr) { - this->get_service().set_option(this->get_implementation(), + impl_.get_service().set_option(impl_.get_implementation(), socket_base::reuse_address(true), ec); boost::asio::detail::throw_error(ec, "set_option"); } - this->get_service().bind(this->get_implementation(), endpoint, ec); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); boost::asio::detail::throw_error(ec, "bind"); - this->get_service().listen(this->get_implementation(), + impl_.get_service().listen(impl_.get_implementation(), + socket_base::max_listen_connections, ec); + boost::asio::detail::throw_error(ec, "listen"); + } + + /// Construct an acceptor opened on the given endpoint. + /** + * This constructor creates an acceptor and automatically opens it to listen + * for new connections on the specified endpoint. + * + * @param context An execution context which provides the I/O executor that + * the acceptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the acceptor. + * + * @param endpoint An endpoint on the local machine on which the acceptor + * will listen for new connections. + * + * @param reuse_addr Whether the constructor should set the socket option + * socket_base::reuse_address. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This constructor is equivalent to the following code: + * @code + * basic_socket_acceptor<Protocol> acceptor(my_context); + * acceptor.open(endpoint.protocol()); + * if (reuse_addr) + * acceptor.set_option(socket_base::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(); + * @endcode + */ + template <typename ExecutionContext> + basic_socket_acceptor(ExecutionContext& context, + const endpoint_type& endpoint, bool reuse_addr = true, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + if (reuse_addr) + { + impl_.get_service().set_option(impl_.get_implementation(), + socket_base::reuse_address(true), ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + impl_.get_service().listen(impl_.get_implementation(), socket_base::max_listen_connections, ec); boost::asio::detail::throw_error(ec, "listen"); } @@ -180,7 +285,7 @@ public: * This constructor creates an acceptor object to hold an existing native * acceptor. * - * @param io_context The io_context object that the acceptor will use to + * @param ex The I/O executor that the acceptor will use, by default, to * dispatch handlers for any asynchronous operations performed on the * acceptor. * @@ -190,12 +295,41 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_socket_acceptor(boost::asio::io_context& io_context, + basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol, const native_handle_type& native_acceptor) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + : impl_(ex) { boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_acceptor, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_socket_acceptor on an existing native acceptor. + /** + * This constructor creates an acceptor object to hold an existing native + * acceptor. + * + * @param context An execution context which provides the I/O executor that + * the acceptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_socket_acceptor(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_acceptor, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), protocol, native_acceptor, ec); boost::asio::detail::throw_error(ec, "assign"); } @@ -209,10 +343,11 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_socket_acceptor(io_context&) constructor. + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. */ basic_socket_acceptor(basic_socket_acceptor&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) + : impl_(std::move(other.impl_)) { } @@ -224,16 +359,17 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_socket_acceptor(io_context&) constructor. + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. */ basic_socket_acceptor& operator=(basic_socket_acceptor&& other) { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); + impl_ = std::move(other.impl_); return *this; } // All socket acceptors have access to each other's implementations. - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> + template <typename Protocol1, typename Executor1> friend class basic_socket_acceptor; /// Move-construct a basic_socket_acceptor from an acceptor of another @@ -245,14 +381,16 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_socket(io_context&) constructor. + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - basic_socket_acceptor( - basic_socket_acceptor<Protocol1 BOOST_ASIO_SVC_TARG1>&& other, - typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) - : basic_io_object<BOOST_ASIO_SVC_T>( - other.get_service(), other.get_implementation()) + template <typename Protocol1, typename Executor1> + basic_socket_acceptor(basic_socket_acceptor<Protocol1, Executor1>&& other, + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value + >::type* = 0) + : impl_(std::move(other.impl_)) { } @@ -265,15 +403,18 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_socket(io_context&) constructor. + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - typename enable_if<is_convertible<Protocol1, Protocol>::value, - basic_socket_acceptor>::type& operator=( - basic_socket_acceptor<Protocol1 BOOST_ASIO_SVC_TARG1>&& other) + template <typename Protocol1, typename Executor1> + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value, + basic_socket_acceptor& + >::type operator=(basic_socket_acceptor<Protocol1, Executor1>&& other) { basic_socket_acceptor tmp(std::move(other)); - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp)); + impl_ = std::move(tmp.impl_); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -288,45 +429,11 @@ public: { } -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - // These functions are provided by basic_io_object<>. -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Get the executor associated with the object. executor_type get_executor() BOOST_ASIO_NOEXCEPT { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); + return impl_.get_executor(); } -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) /// Open the acceptor using the specified protocol. /** @@ -339,14 +446,14 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * acceptor.open(boost::asio::ip::tcp::v4()); * @endcode */ void open(const protocol_type& protocol = protocol_type()) { boost::system::error_code ec; - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); boost::asio::detail::throw_error(ec, "open"); } @@ -361,7 +468,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * boost::system::error_code ec; * acceptor.open(boost::asio::ip::tcp::v4(), ec); * if (ec) @@ -373,7 +480,7 @@ public: BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, boost::system::error_code& ec) { - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -391,7 +498,7 @@ public: const native_handle_type& native_acceptor) { boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), protocol, native_acceptor, ec); boost::asio::detail::throw_error(ec, "assign"); } @@ -409,7 +516,7 @@ public: BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, const native_handle_type& native_acceptor, boost::system::error_code& ec) { - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), protocol, native_acceptor, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -417,7 +524,7 @@ public: /// Determine whether the acceptor is open. bool is_open() const { - return this->get_service().is_open(this->get_implementation()); + return impl_.get_service().is_open(impl_.get_implementation()); } /// Bind the acceptor to the given local endpoint. @@ -432,7 +539,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); * acceptor.open(endpoint.protocol()); * acceptor.bind(endpoint); @@ -441,7 +548,7 @@ public: void bind(const endpoint_type& endpoint) { boost::system::error_code ec; - this->get_service().bind(this->get_implementation(), endpoint, ec); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); boost::asio::detail::throw_error(ec, "bind"); } @@ -457,7 +564,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); * acceptor.open(endpoint.protocol()); * boost::system::error_code ec; @@ -471,7 +578,7 @@ public: BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, boost::system::error_code& ec) { - this->get_service().bind(this->get_implementation(), endpoint, ec); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -488,7 +595,7 @@ public: void listen(int backlog = socket_base::max_listen_connections) { boost::system::error_code ec; - this->get_service().listen(this->get_implementation(), backlog, ec); + impl_.get_service().listen(impl_.get_implementation(), backlog, ec); boost::asio::detail::throw_error(ec, "listen"); } @@ -504,7 +611,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::system::error_code ec; * acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); @@ -516,7 +623,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID listen(int backlog, boost::system::error_code& ec) { - this->get_service().listen(this->get_implementation(), backlog, ec); + impl_.get_service().listen(impl_.get_implementation(), backlog, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -533,7 +640,7 @@ public: void close() { boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "close"); } @@ -549,7 +656,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::system::error_code ec; * acceptor.close(ec); @@ -561,7 +668,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) { - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -587,8 +694,8 @@ public: native_handle_type release() { boost::system::error_code ec; - native_handle_type s = this->get_service().release( - this->get_implementation(), ec); + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "release"); return s; } @@ -614,7 +721,7 @@ public: #endif native_handle_type release(boost::system::error_code& ec) { - return this->get_service().release(this->get_implementation(), ec); + return impl_.get_service().release(impl_.get_implementation(), ec); } /// Get the native acceptor representation. @@ -625,7 +732,7 @@ public: */ native_handle_type native_handle() { - return this->get_service().native_handle(this->get_implementation()); + return impl_.get_service().native_handle(impl_.get_implementation()); } /// Cancel all asynchronous operations associated with the acceptor. @@ -639,7 +746,7 @@ public: void cancel() { boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel"); } @@ -653,7 +760,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) { - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -672,7 +779,7 @@ public: * @par Example * Setting the SOL_SOCKET/SO_REUSEADDR option: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::acceptor::reuse_address option(true); * acceptor.set_option(option); @@ -682,7 +789,7 @@ public: void set_option(const SettableSocketOption& option) { boost::system::error_code ec; - this->get_service().set_option(this->get_implementation(), option, ec); + impl_.get_service().set_option(impl_.get_implementation(), option, ec); boost::asio::detail::throw_error(ec, "set_option"); } @@ -701,7 +808,7 @@ public: * @par Example * Setting the SOL_SOCKET/SO_REUSEADDR option: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::acceptor::reuse_address option(true); * boost::system::error_code ec; @@ -716,7 +823,7 @@ public: BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, boost::system::error_code& ec) { - this->get_service().set_option(this->get_implementation(), option, ec); + impl_.get_service().set_option(impl_.get_implementation(), option, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -735,7 +842,7 @@ public: * @par Example * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::acceptor::reuse_address option; * acceptor.get_option(option); @@ -746,7 +853,7 @@ public: void get_option(GettableSocketOption& option) const { boost::system::error_code ec; - this->get_service().get_option(this->get_implementation(), option, ec); + impl_.get_service().get_option(impl_.get_implementation(), option, ec); boost::asio::detail::throw_error(ec, "get_option"); } @@ -765,7 +872,7 @@ public: * @par Example * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::acceptor::reuse_address option; * boost::system::error_code ec; @@ -781,7 +888,7 @@ public: BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, boost::system::error_code& ec) const { - this->get_service().get_option(this->get_implementation(), option, ec); + impl_.get_service().get_option(impl_.get_implementation(), option, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -799,7 +906,7 @@ public: * @par Example * Getting the number of bytes ready to read: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); * socket.io_control(command); @@ -809,7 +916,7 @@ public: void io_control(IoControlCommand& command) { boost::system::error_code ec; - this->get_service().io_control(this->get_implementation(), command, ec); + impl_.get_service().io_control(impl_.get_implementation(), command, ec); boost::asio::detail::throw_error(ec, "io_control"); } @@ -827,7 +934,7 @@ public: * @par Example * Getting the number of bytes ready to read: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); * boost::system::error_code ec; @@ -842,7 +949,7 @@ public: BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, boost::system::error_code& ec) { - this->get_service().io_control(this->get_implementation(), command, ec); + impl_.get_service().io_control(impl_.get_implementation(), command, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -859,7 +966,7 @@ public: */ bool non_blocking() const { - return this->get_service().non_blocking(this->get_implementation()); + return impl_.get_service().non_blocking(impl_.get_implementation()); } /// Sets the non-blocking mode of the acceptor. @@ -878,7 +985,7 @@ public: void non_blocking(bool mode) { boost::system::error_code ec; - this->get_service().non_blocking(this->get_implementation(), mode, ec); + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); boost::asio::detail::throw_error(ec, "non_blocking"); } @@ -898,7 +1005,7 @@ public: BOOST_ASIO_SYNC_OP_VOID non_blocking( bool mode, boost::system::error_code& ec) { - this->get_service().non_blocking(this->get_implementation(), mode, ec); + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -918,7 +1025,7 @@ public: */ bool native_non_blocking() const { - return this->get_service().native_non_blocking(this->get_implementation()); + return impl_.get_service().native_non_blocking(impl_.get_implementation()); } /// Sets the non-blocking mode of the native acceptor implementation. @@ -939,8 +1046,8 @@ public: void native_non_blocking(bool mode) { boost::system::error_code ec; - this->get_service().native_non_blocking( - this->get_implementation(), mode, ec); + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); boost::asio::detail::throw_error(ec, "native_non_blocking"); } @@ -962,8 +1069,8 @@ public: BOOST_ASIO_SYNC_OP_VOID native_non_blocking( bool mode, boost::system::error_code& ec) { - this->get_service().native_non_blocking( - this->get_implementation(), mode, ec); + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -977,7 +1084,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); * @endcode @@ -985,8 +1092,8 @@ public: endpoint_type local_endpoint() const { boost::system::error_code ec; - endpoint_type ep = this->get_service().local_endpoint( - this->get_implementation(), ec); + endpoint_type ep = impl_.get_service().local_endpoint( + impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "local_endpoint"); return ep; } @@ -1003,7 +1110,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::system::error_code ec; * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); @@ -1015,7 +1122,7 @@ public: */ endpoint_type local_endpoint(boost::system::error_code& ec) const { - return this->get_service().local_endpoint(this->get_implementation(), ec); + return impl_.get_service().local_endpoint(impl_.get_implementation(), ec); } /// Wait for the acceptor to become ready to read, ready to write, or to have @@ -1029,7 +1136,7 @@ public: * @par Example * Waiting for an acceptor to become readable. * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read); * @endcode @@ -1037,7 +1144,7 @@ public: void wait(wait_type w) { boost::system::error_code ec; - this->get_service().wait(this->get_implementation(), w, ec); + impl_.get_service().wait(impl_.get_implementation(), w, ec); boost::asio::detail::throw_error(ec, "wait"); } @@ -1054,7 +1161,7 @@ public: * @par Example * Waiting for an acceptor to become readable. * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::system::error_code ec; * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read, ec); @@ -1062,7 +1169,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) { - this->get_service().wait(this->get_implementation(), w, ec); + impl_.get_service().wait(impl_.get_implementation(), w, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1081,9 +1188,9 @@ public: * const boost::system::error_code& error // Result of operation * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -1097,7 +1204,7 @@ public: * * ... * - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * acceptor.async_wait( * boost::asio::ip::tcp::acceptor::wait_read, @@ -1109,22 +1216,8 @@ public: void (boost::system::error_code)) async_wait(wait_type w, BOOST_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. - BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_wait(this->get_implementation(), - w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_wait(this->get_implementation(), - w, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WaitHandler, void (boost::system::error_code)>( + initiate_async_wait(), handler, this, w); } #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -1140,24 +1233,20 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * acceptor.accept(socket); * @endcode */ -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1, typename SocketService> - void accept(basic_socket<Protocol1, SocketService>& peer, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1> - void accept(basic_socket<Protocol1>& peer, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + template <typename Protocol1, typename Executor1> + void accept(basic_socket<Protocol1, Executor1>& peer, + typename enable_if< + is_convertible<Protocol, Protocol1>::value + >::type* = 0) { boost::system::error_code ec; - this->get_service().accept(this->get_implementation(), + impl_.get_service().accept(impl_.get_implementation(), peer, static_cast<endpoint_type*>(0), ec); boost::asio::detail::throw_error(ec, "accept"); } @@ -1174,9 +1263,9 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * boost::system::error_code ec; * acceptor.accept(socket, ec); * if (ec) @@ -1185,20 +1274,14 @@ public: * } * @endcode */ -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1, typename SocketService> + template <typename Protocol1, typename Executor1> BOOST_ASIO_SYNC_OP_VOID accept( - basic_socket<Protocol1, SocketService>& peer, - boost::system::error_code& ec, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1> - BOOST_ASIO_SYNC_OP_VOID accept( - basic_socket<Protocol1>& peer, boost::system::error_code& ec, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + basic_socket<Protocol1, Executor1>& peer, boost::system::error_code& ec, + typename enable_if< + is_convertible<Protocol, Protocol1>::value + >::type* = 0) { - this->get_service().accept(this->get_implementation(), + impl_.get_service().accept(impl_.get_implementation(), peer, static_cast<endpoint_type*>(0), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1219,9 +1302,9 @@ public: * const boost::system::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -1235,45 +1318,24 @@ public: * * ... * - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * acceptor.async_accept(socket, accept_handler); * @endcode */ -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1, typename SocketService, typename AcceptHandler> + template <typename Protocol1, typename Executor1, typename AcceptHandler> BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, void (boost::system::error_code)) - async_accept(basic_socket<Protocol1, SocketService>& peer, + async_accept(basic_socket<Protocol1, Executor1>& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1, typename AcceptHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, - void (boost::system::error_code)) - async_accept(basic_socket<Protocol1>& peer, - BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + typename enable_if< + is_convertible<Protocol, Protocol1>::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. - BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept(this->get_implementation(), - peer, static_cast<endpoint_type*>(0), - BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<AcceptHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_accept(this->get_implementation(), - peer, static_cast<endpoint_type*>(0), init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<AcceptHandler, void (boost::system::error_code)>( + initiate_async_accept(), handler, this, + &peer, static_cast<endpoint_type*>(0)); } /// Accept a new connection and obtain the endpoint of the peer @@ -1292,23 +1354,19 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * boost::asio::ip::tcp::endpoint endpoint; * acceptor.accept(socket, endpoint); * @endcode */ -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename SocketService> - void accept(basic_socket<protocol_type, SocketService>& peer, + template <typename Executor1> + void accept(basic_socket<protocol_type, Executor1>& peer, endpoint_type& peer_endpoint) -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - void accept(basic_socket<protocol_type>& peer, endpoint_type& peer_endpoint) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) { boost::system::error_code ec; - this->get_service().accept(this->get_implementation(), + impl_.get_service().accept(impl_.get_implementation(), peer, &peer_endpoint, ec); boost::asio::detail::throw_error(ec, "accept"); } @@ -1329,9 +1387,9 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * boost::asio::ip::tcp::endpoint endpoint; * boost::system::error_code ec; * acceptor.accept(socket, endpoint, ec); @@ -1341,18 +1399,12 @@ public: * } * @endcode */ -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename SocketService> - BOOST_ASIO_SYNC_OP_VOID accept( - basic_socket<protocol_type, SocketService>& peer, - endpoint_type& peer_endpoint, boost::system::error_code& ec) -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - BOOST_ASIO_SYNC_OP_VOID accept(basic_socket<protocol_type>& peer, + template <typename Executor1> + BOOST_ASIO_SYNC_OP_VOID accept(basic_socket<protocol_type, Executor1>& peer, endpoint_type& peer_endpoint, boost::system::error_code& ec) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) { - this->get_service().accept( - this->get_implementation(), peer, &peer_endpoint, ec); + impl_.get_service().accept( + impl_.get_implementation(), peer, &peer_endpoint, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1378,40 +1430,18 @@ public: * const boost::system::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename SocketService, typename AcceptHandler> + template <typename Executor1, typename AcceptHandler> BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, void (boost::system::error_code)) - async_accept(basic_socket<protocol_type, SocketService>& peer, + async_accept(basic_socket<protocol_type, Executor1>& peer, endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler) -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - template <typename AcceptHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, - void (boost::system::error_code)) - async_accept(basic_socket<protocol_type>& peer, - endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a AcceptHandler. - BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept(this->get_implementation(), peer, - &peer_endpoint, BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<AcceptHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_accept(this->get_implementation(), - peer, &peer_endpoint, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<AcceptHandler, void (boost::system::error_code)>( + initiate_async_accept(), handler, this, &peer, &peer_endpoint); } #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -1431,7 +1461,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::socket socket(acceptor.accept()); * @endcode @@ -1439,9 +1469,8 @@ public: typename Protocol::socket accept() { boost::system::error_code ec; - typename Protocol::socket peer( - this->get_service().accept( - this->get_implementation(), 0, 0, ec)); + typename Protocol::socket peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); boost::asio::detail::throw_error(ec, "accept"); return peer; } @@ -1462,7 +1491,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::socket socket(acceptor.accept(ec)); * if (ec) @@ -1473,7 +1502,9 @@ public: */ typename Protocol::socket accept(boost::system::error_code& ec) { - return this->get_service().accept(this->get_implementation(), 0, 0, ec); + typename Protocol::socket peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + return peer; } /// Start an asynchronous accept. @@ -1492,9 +1523,9 @@ public: * typename Protocol::socket peer // On success, the newly accepted socket. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -1509,7 +1540,7 @@ public: * * ... * - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * acceptor.async_accept(accept_handler); * @endcode @@ -1519,27 +1550,49 @@ public: void (boost::system::error_code, typename Protocol::socket)) async_accept(BOOST_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. - BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept( - this->get_implementation(), static_cast<boost::asio::io_context*>(0), - static_cast<endpoint_type*>(0), - BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<MoveAcceptHandler, - void (boost::system::error_code, - typename Protocol::socket)> init(handler); - - this->get_service().async_accept( - this->get_implementation(), static_cast<boost::asio::io_context*>(0), - static_cast<endpoint_type*>(0), init.completion_handler); + return async_initiate<MoveAcceptHandler, + void (boost::system::error_code, typename Protocol::socket)>( + initiate_async_move_accept(), handler, this, + impl_.get_executor(), static_cast<endpoint_type*>(0), + static_cast<typename Protocol::socket*>(0)); + } - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ex The I/O executor object to be used for the newly + * accepted socket. + * + * @returns A socket object representing the newly accepted connection. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(acceptor.accept()); + * @endcode + */ + template <typename Executor1> + typename Protocol::socket::template rebind_executor<Executor1>::other + accept(const Executor1& ex, + typename enable_if< + is_executor<Executor1>::value + >::type* = 0) + { + boost::system::error_code ec; + typename Protocol::socket::template + rebind_executor<Executor1>::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + boost::asio::detail::throw_error(ec, "accept"); + return peer; } /// Accept a new connection. @@ -1551,8 +1604,8 @@ public: * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. * - * @param io_context The io_context object to be used for the newly accepted - * socket. + * @param context The I/O execution context object to be used for the newly + * accepted socket. * * @returns A socket object representing the newly accepted connection. * @@ -1560,17 +1613,23 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::socket socket(acceptor.accept()); * @endcode */ - typename Protocol::socket accept(boost::asio::io_context& io_context) + template <typename ExecutionContext> + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) { boost::system::error_code ec; - typename Protocol::socket peer( - this->get_service().accept(this->get_implementation(), - &io_context, static_cast<endpoint_type*>(0), ec)); + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); boost::asio::detail::throw_error(ec, "accept"); return peer; } @@ -1584,7 +1643,7 @@ public: * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. * - * @param io_context The io_context object to be used for the newly accepted + * @param ex The I/O executor object to be used for the newly accepted * socket. * * @param ec Set to indicate what error occurred, if any. @@ -1594,20 +1653,68 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... - * boost::asio::ip::tcp::socket socket(acceptor.accept(io_context2, ec)); + * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); * if (ec) * { * // An error occurred. * } * @endcode */ - typename Protocol::socket accept( - boost::asio::io_context& io_context, boost::system::error_code& ec) + template <typename Executor1> + typename Protocol::socket::template rebind_executor<Executor1>::other + accept(const Executor1& ex, boost::system::error_code& ec, + typename enable_if< + is_executor<Executor1>::value + >::type* = 0) { - return this->get_service().accept(this->get_implementation(), - &io_context, static_cast<endpoint_type*>(0), ec); + typename Protocol::socket::template + rebind_executor<Executor1>::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns On success, a socket object representing the newly accepted + * connection. On error, a socket object where is_open() is false. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename ExecutionContext> + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, boost::system::error_code& ec, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + { + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + return peer; } /// Start an asynchronous accept. @@ -1618,7 +1725,7 @@ public: * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. * - * @param io_context The io_context object to be used for the newly accepted + * @param ex The I/O executor object to be used for the newly accepted * socket. * * @param handler The handler to be called when the accept operation @@ -1626,12 +1733,13 @@ public: * signature of the handler must be: * @code void handler( * const boost::system::error_code& error, // Result of operation. - * typename Protocol::socket peer // On success, the newly accepted socket. + * typename Protocol::socket::template rebind_executor< + * Executor1>::other peer // On success, the newly accepted socket. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -1646,36 +1754,94 @@ public: * * ... * - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... - * acceptor.async_accept(io_context2, accept_handler); + * acceptor.async_accept(my_context2, accept_handler); * @endcode */ - template <typename MoveAcceptHandler> + template <typename Executor1, typename MoveAcceptHandler> BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, - void (boost::system::error_code, typename Protocol::socket)) - async_accept(boost::asio::io_context& io_context, - BOOST_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. - BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept(this->get_implementation(), - &io_context, static_cast<endpoint_type*>(0), - BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<MoveAcceptHandler, void (boost::system::error_code, - typename Protocol::socket)> init(handler); - - this->get_service().async_accept(this->get_implementation(), - &io_context, static_cast<endpoint_type*>(0), init.completion_handler); + typename Protocol::socket::template rebind_executor< + Executor1>::other)) + async_accept(const Executor1& ex, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + typename enable_if< + is_executor<Executor1>::value + >::type* = 0) + { + typedef typename Protocol::socket::template rebind_executor< + Executor1>::other other_socket_type; + + return async_initiate<MoveAcceptHandler, + void (boost::system::error_code, other_socket_type)>( + initiate_async_move_accept(), handler, this, + ex, static_cast<endpoint_type*>(0), + static_cast<other_socket_type*>(0)); + } - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection. The + * function call always returns immediately. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * typename Protocol::socket::template rebind_executor< + * typename ExecutionContext::executor_type>::other peer + * // On success, the newly accepted socket. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error, + * boost::asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * acceptor.async_accept(my_context2, accept_handler); + * @endcode + */ + template <typename ExecutionContext, typename MoveAcceptHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (boost::system::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)) + async_accept(ExecutionContext& context, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + { + typedef typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other other_socket_type; + + return async_initiate<MoveAcceptHandler, + void (boost::system::error_code, other_socket_type)>( + initiate_async_move_accept(), handler, this, + context.get_executor(), static_cast<endpoint_type*>(0), + static_cast<other_socket_type*>(0)); } /// Accept a new connection. @@ -1696,7 +1862,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint; * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint)); @@ -1705,9 +1871,9 @@ public: typename Protocol::socket accept(endpoint_type& peer_endpoint) { boost::system::error_code ec; - typename Protocol::socket peer( - this->get_service().accept(this->get_implementation(), - static_cast<boost::asio::io_context*>(0), &peer_endpoint, ec)); + typename Protocol::socket peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); boost::asio::detail::throw_error(ec, "accept"); return peer; } @@ -1731,7 +1897,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint; * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec)); @@ -1744,8 +1910,10 @@ public: typename Protocol::socket accept( endpoint_type& peer_endpoint, boost::system::error_code& ec) { - return this->get_service().accept(this->get_implementation(), - static_cast<boost::asio::io_context*>(0), &peer_endpoint, ec); + typename Protocol::socket peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + return peer; } /// Start an asynchronous accept. @@ -1769,9 +1937,9 @@ public: * typename Protocol::socket peer // On success, the newly accepted socket. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -1786,7 +1954,7 @@ public: * * ... * - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint; * acceptor.async_accept(endpoint, accept_handler); @@ -1798,26 +1966,11 @@ public: async_accept(endpoint_type& peer_endpoint, BOOST_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. - BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept(this->get_implementation(), - static_cast<boost::asio::io_context*>(0), &peer_endpoint, - BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<MoveAcceptHandler, - void (boost::system::error_code, - typename Protocol::socket)> init(handler); - - this->get_service().async_accept(this->get_implementation(), - static_cast<boost::asio::io_context*>(0), &peer_endpoint, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<MoveAcceptHandler, + void (boost::system::error_code, typename Protocol::socket)>( + initiate_async_move_accept(), handler, this, + impl_.get_executor(), &peer_endpoint, + static_cast<typename Protocol::socket*>(0)); } /// Accept a new connection. @@ -1829,7 +1982,7 @@ public: * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. * - * @param io_context The io_context object to be used for the newly accepted + * @param ex The I/O executor object to be used for the newly accepted * socket. * * @param peer_endpoint An endpoint object into which the endpoint of the @@ -1841,20 +1994,25 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint; * boost::asio::ip::tcp::socket socket( - * acceptor.accept(io_context2, endpoint)); + * acceptor.accept(my_context2, endpoint)); * @endcode */ - typename Protocol::socket accept( - boost::asio::io_context& io_context, endpoint_type& peer_endpoint) + template <typename Executor1> + typename Protocol::socket::template rebind_executor<Executor1>::other + accept(const Executor1& ex, endpoint_type& peer_endpoint, + typename enable_if< + is_executor<Executor1>::value + >::type* = 0) { boost::system::error_code ec; - typename Protocol::socket peer( - this->get_service().accept(this->get_implementation(), - &io_context, &peer_endpoint, ec)); + typename Protocol::socket::template + rebind_executor<Executor1>::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); boost::asio::detail::throw_error(ec, "accept"); return peer; } @@ -1868,7 +2026,52 @@ public: * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. * - * @param io_context The io_context object to be used for the newly accepted + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. + * + * @returns A socket object representing the newly accepted connection. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * boost::asio::ip::tcp::socket socket( + * acceptor.accept(my_context2, endpoint)); + * @endcode + */ + template <typename ExecutionContext> + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, endpoint_type& peer_endpoint, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + { + boost::system::error_code ec; + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "accept"); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param ex The I/O executor object to be used for the newly accepted * socket. * * @param peer_endpoint An endpoint object into which the endpoint of the @@ -1881,22 +2084,79 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint; * boost::asio::ip::tcp::socket socket( - * acceptor.accept(io_context2, endpoint, ec)); + * acceptor.accept(my_context2, endpoint, ec)); * if (ec) * { * // An error occurred. * } * @endcode */ - typename Protocol::socket accept(boost::asio::io_context& io_context, - endpoint_type& peer_endpoint, boost::system::error_code& ec) + template <typename Executor1> + typename Protocol::socket::template rebind_executor<Executor1>::other + accept(const executor_type& ex, + endpoint_type& peer_endpoint, boost::system::error_code& ec, + typename enable_if< + is_executor<Executor1>::value + >::type* = 0) { - return this->get_service().accept(this->get_implementation(), - &io_context, &peer_endpoint, ec); + typename Protocol::socket::template + rebind_executor<Executor1>::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + return peer; + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer. The function + * call will block until a new connection has been accepted successfully or + * an error occurs. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns On success, a socket object representing the newly accepted + * connection. On error, a socket object where is_open() is false. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * boost::asio::ip::tcp::socket socket( + * acceptor.accept(my_context2, endpoint, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename ExecutionContext> + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, + endpoint_type& peer_endpoint, boost::system::error_code& ec, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + { + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + return peer; } /// Start an asynchronous accept. @@ -1907,7 +2167,7 @@ public: * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. * - * @param io_context The io_context object to be used for the newly accepted + * @param ex The I/O executor object to be used for the newly accepted * socket. * * @param peer_endpoint An endpoint object into which the endpoint of the @@ -1920,12 +2180,13 @@ public: * signature of the handler must be: * @code void handler( * const boost::system::error_code& error, // Result of operation. - * typename Protocol::socket peer // On success, the newly accepted socket. + * typename Protocol::socket::template rebind_executor< + * Executor1>::other peer // On success, the newly accepted socket. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -1940,40 +2201,175 @@ public: * * ... * - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::ip::tcp::endpoint endpoint; - * acceptor.async_accept(io_context2, endpoint, accept_handler); + * acceptor.async_accept(my_context2, endpoint, accept_handler); * @endcode */ - template <typename MoveAcceptHandler> + template <typename Executor1, typename MoveAcceptHandler> BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, - void (boost::system::error_code, typename Protocol::socket)) - async_accept(boost::asio::io_context& io_context, - endpoint_type& peer_endpoint, - BOOST_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. - BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept( - this->get_implementation(), &io_context, &peer_endpoint, - BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<MoveAcceptHandler, void (boost::system::error_code, - typename Protocol::socket)> init(handler); - - this->get_service().async_accept(this->get_implementation(), - &io_context, &peer_endpoint, init.completion_handler); + typename Protocol::socket::template rebind_executor< + Executor1>::other)) + async_accept(const Executor1& ex, endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + typename enable_if< + is_executor<Executor1>::value + >::type* = 0) + { + typedef typename Protocol::socket::template rebind_executor< + Executor1>::other other_socket_type; + + return async_initiate<MoveAcceptHandler, + void (boost::system::error_code, other_socket_type)>( + initiate_async_move_accept(), handler, this, + ex, &peer_endpoint, + static_cast<other_socket_type*>(0)); + } - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection. The + * function call always returns immediately. + * + * This overload requires that the Protocol template parameter satisfy the + * AcceptableProtocol type requirements. + * + * @param context The I/O execution context object to be used for the newly + * accepted socket. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. Ownership of the peer_endpoint object is + * retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * typename Protocol::socket::template rebind_executor< + * typename ExecutionContext::executor_type>::other peer + * // On success, the newly accepted socket. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error, + * boost::asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(my_context); + * ... + * boost::asio::ip::tcp::endpoint endpoint; + * acceptor.async_accept(my_context2, endpoint, accept_handler); + * @endcode + */ + template <typename ExecutionContext, typename MoveAcceptHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (boost::system::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)) + async_accept(ExecutionContext& context, + endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + { + typedef typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other other_socket_type; + + return async_initiate<MoveAcceptHandler, + void (boost::system::error_code, other_socket_type)>( + initiate_async_move_accept(), handler, this, + context.get_executor(), &peer_endpoint, + static_cast<other_socket_type*>(0)); } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + +private: + // Disallow copying and assignment. + basic_socket_acceptor(const basic_socket_acceptor&) BOOST_ASIO_DELETED; + basic_socket_acceptor& operator=( + const basic_socket_acceptor&) BOOST_ASIO_DELETED; + + struct initiate_async_wait + { + template <typename WaitHandler> + void operator()(BOOST_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. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue<WaitHandler> 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 <typename AcceptHandler, typename Protocol1, typename Executor1> + void operator()(BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, + basic_socket_acceptor* self, basic_socket<Protocol1, Executor1>* 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. + BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; + + detail::non_const_lvalue<AcceptHandler> 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 <typename MoveAcceptHandler, typename Executor1, typename Socket> + void operator()(BOOST_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. + BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( + MoveAcceptHandler, handler, Socket) type_check; + + detail::non_const_lvalue<MoveAcceptHandler> 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(BOOST_ASIO_WINDOWS_RUNTIME) + detail::io_object_impl< + detail::null_socket_service<Protocol>, Executor> impl_; +#elif defined(BOOST_ASIO_HAS_IOCP) + detail::io_object_impl< + detail::win_iocp_socket_service<Protocol>, Executor> impl_; +#else + detail::io_object_impl< + detail::reactive_socket_service<Protocol>, Executor> impl_; +#endif }; } // namespace asio @@ -1981,8 +2377,4 @@ public: #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# undef BOOST_ASIO_SVC_T -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP diff --git a/boost/asio/basic_socket_iostream.hpp b/boost/asio/basic_socket_iostream.hpp index 7a7cab9c93..b6d449d669 100644 --- a/boost/asio/basic_socket_iostream.hpp +++ b/boost/asio/basic_socket_iostream.hpp @@ -2,7 +2,7 @@ // basic_socket_iostream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -23,10 +23,6 @@ #include <ostream> #include <boost/asio/basic_socket_streambuf.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/stream_socket_service.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) # include <boost/asio/detail/variadic_templates.hpp> @@ -36,8 +32,7 @@ // explicit basic_socket_iostream(T1 x1, ..., Tn xn) // : std::basic_iostream<char>( // &this->detail::socket_iostream_base< -// Protocol BOOST_ASIO_SVC_TARG, Clock, -// WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_) +// Protocol, Clock, WaitTraits>::streambuf_) // { // if (rdbuf()->connect(x1, ..., xn) == 0) // this->setstate(std::ios_base::failbit); @@ -49,8 +44,7 @@ explicit basic_socket_iostream(BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n)) \ : std::basic_iostream<char>( \ &this->detail::socket_iostream_base< \ - Protocol BOOST_ASIO_SVC_TARG, Clock, \ - WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_) \ + Protocol, Clock, WaitTraits>::streambuf_) \ { \ this->setf(std::ios_base::unitbuf); \ if (rdbuf()->connect(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \ @@ -86,8 +80,7 @@ namespace detail { // A separate base class is used to ensure that the streambuf is initialised // prior to the basic_socket_iostream's basic_iostream base class. -template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM1> +template <typename Protocol, typename Clock, typename WaitTraits> class socket_iostream_base { protected: @@ -113,8 +106,7 @@ protected: } #endif // defined(BOOST_ASIO_HAS_MOVE) - basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG, - Clock, WaitTraits BOOST_ASIO_SVC_TARG1> streambuf_; + basic_socket_streambuf<Protocol, Clock, WaitTraits> streambuf_; }; } // namespace detail @@ -123,18 +115,15 @@ protected: #define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL // Forward declaration with defaulted arguments. -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>), +template <typename Protocol, #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) typename Clock = boost::posix_time::ptime, - typename WaitTraits = time_traits<Clock> - BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)> + typename WaitTraits = time_traits<Clock> > #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> - BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)> + typename WaitTraits = wait_traits<Clock> > #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) class basic_socket_iostream; @@ -147,12 +136,10 @@ template <typename Protocol, typename Clock = chrono::steady_clock, typename WaitTraits = wait_traits<Clock> > #else // defined(GENERATING_DOCUMENTATION) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM1> +template <typename Protocol, typename Clock, typename WaitTraits> #endif // defined(GENERATING_DOCUMENTATION) class basic_socket_iostream - : private detail::socket_iostream_base<Protocol - BOOST_ASIO_SVC_TARG, Clock, WaitTraits BOOST_ASIO_SVC_TARG1>, + : private detail::socket_iostream_base<Protocol, Clock, WaitTraits>, public std::basic_iostream<char> { private: @@ -202,8 +189,7 @@ public: basic_socket_iostream() : std::basic_iostream<char>( &this->detail::socket_iostream_base< - Protocol BOOST_ASIO_SVC_TARG, Clock, - WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_) + Protocol, Clock, WaitTraits>::streambuf_) { this->setf(std::ios_base::unitbuf); } @@ -212,12 +198,10 @@ public: /// Construct a basic_socket_iostream from the supplied socket. explicit basic_socket_iostream(basic_stream_socket<protocol_type> s) : detail::socket_iostream_base< - Protocol BOOST_ASIO_SVC_TARG, Clock, - WaitTraits BOOST_ASIO_SVC_TARG1>(std::move(s)), + Protocol, Clock, WaitTraits>(std::move(s)), std::basic_iostream<char>( &this->detail::socket_iostream_base< - Protocol BOOST_ASIO_SVC_TARG, Clock, - WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_) + Protocol, Clock, WaitTraits>::streambuf_) { this->setf(std::ios_base::unitbuf); } @@ -227,13 +211,11 @@ public: /// Move-construct a basic_socket_iostream from another. basic_socket_iostream(basic_socket_iostream&& other) : detail::socket_iostream_base< - Protocol BOOST_ASIO_SVC_TARG, Clock, - WaitTraits BOOST_ASIO_SVC_TARG1>(std::move(other)), + Protocol, Clock, WaitTraits>(std::move(other)), std::basic_iostream<char>(std::move(other)) { this->set_rdbuf(&this->detail::socket_iostream_base< - Protocol BOOST_ASIO_SVC_TARG, Clock, - WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_); + Protocol, Clock, WaitTraits>::streambuf_); } /// Move-assign a basic_socket_iostream from another. @@ -241,8 +223,7 @@ public: { std::basic_iostream<char>::operator=(std::move(other)); detail::socket_iostream_base< - Protocol BOOST_ASIO_SVC_TARG, Clock, - WaitTraits BOOST_ASIO_SVC_TARG1>::operator=(std::move(other)); + Protocol, Clock, WaitTraits>::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE) @@ -263,8 +244,7 @@ public: explicit basic_socket_iostream(T... x) : std::basic_iostream<char>( &this->detail::socket_iostream_base< - Protocol BOOST_ASIO_SVC_TARG, Clock, - WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_) + Protocol, Clock, WaitTraits>::streambuf_) { this->setf(std::ios_base::unitbuf); if (rdbuf()->connect(x...) == 0) @@ -302,18 +282,15 @@ public: } /// Return a pointer to the underlying streambuf. - basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG, - Clock, WaitTraits BOOST_ASIO_SVC_TARG1>* rdbuf() const + basic_socket_streambuf<Protocol, Clock, WaitTraits>* rdbuf() const { - return const_cast<basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG, - Clock, WaitTraits BOOST_ASIO_SVC_TARG1>*>( + return const_cast<basic_socket_streambuf<Protocol, Clock, WaitTraits>*>( &this->detail::socket_iostream_base< - Protocol BOOST_ASIO_SVC_TARG, Clock, - WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_); + Protocol, Clock, WaitTraits>::streambuf_); } /// Get a reference to the underlying socket. - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket() + basic_socket<Protocol>& socket() { return rdbuf()->socket(); } diff --git a/boost/asio/basic_socket_streambuf.hpp b/boost/asio/basic_socket_streambuf.hpp index 0a2bbe56a6..99106020e7 100644 --- a/boost/asio/basic_socket_streambuf.hpp +++ b/boost/asio/basic_socket_streambuf.hpp @@ -2,7 +2,7 @@ // basic_socket_streambuf.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,17 +28,9 @@ #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/io_context.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/stream_socket_service.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) -# if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/deadline_timer_service.hpp> -# else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/detail/deadline_timer_service.hpp> -# endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +# include <boost/asio/detail/deadline_timer_service.hpp> #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) # include <boost/asio/steady_timer.hpp> @@ -55,7 +47,7 @@ // { // init_buffers(); // typedef typename Protocol::resolver resolver_type; -// resolver_type resolver(socket().get_executor().context()); +// resolver_type resolver(socket().get_executor()); // connect_to_endpoints( // resolver.resolve(x1, ..., xn, ec_)); // return !ec_ ? this : 0; @@ -68,7 +60,7 @@ { \ init_buffers(); \ typedef typename Protocol::resolver resolver_type; \ - resolver_type resolver(socket().get_executor().context()); \ + resolver_type resolver(socket().get_executor()); \ connect_to_endpoints( \ resolver.resolve(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \ return !ec_ ? this : 0; \ @@ -77,10 +69,6 @@ #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# define BOOST_ASIO_SVC_T1 detail::deadline_timer_service<traits_helper> -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -125,18 +113,15 @@ protected: #define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL // Forward declaration with defaulted arguments. -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>), +template <typename Protocol, #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) typename Clock = boost::posix_time::ptime, - typename WaitTraits = time_traits<Clock> - BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)> + typename WaitTraits = time_traits<Clock> > #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> - BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)> + typename WaitTraits = wait_traits<Clock> > #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) class basic_socket_streambuf; @@ -149,17 +134,16 @@ template <typename Protocol, typename Clock = chrono::steady_clock, typename WaitTraits = wait_traits<Clock> > #else // defined(GENERATING_DOCUMENTATION) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM1> +template <typename Protocol, typename Clock, typename WaitTraits> #endif // defined(GENERATING_DOCUMENTATION) class basic_socket_streambuf : public std::streambuf, private detail::socket_streambuf_io_context, private detail::socket_streambuf_buffers, #if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - private basic_socket<Protocol BOOST_ASIO_SVC_TARG> + private basic_socket<Protocol> #else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) - public basic_socket<Protocol BOOST_ASIO_SVC_TARG> + public basic_socket<Protocol> #endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) { private: @@ -208,7 +192,7 @@ public: /// Construct a basic_socket_streambuf without establishing a connection. basic_socket_streambuf() : detail::socket_streambuf_io_context(new io_context), - basic_socket<Protocol BOOST_ASIO_SVC_TARG>(*default_io_context_), + basic_socket<Protocol>(*default_io_context_), expiry_time_(max_expiry_time()) { init_buffers(); @@ -218,7 +202,7 @@ public: /// Construct a basic_socket_streambuf from the supplied socket. explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s) : detail::socket_streambuf_io_context(0), - basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(s)), + basic_socket<Protocol>(std::move(s)), expiry_time_(max_expiry_time()) { init_buffers(); @@ -227,7 +211,7 @@ public: /// Move-construct a basic_socket_streambuf from another. basic_socket_streambuf(basic_socket_streambuf&& other) : detail::socket_streambuf_io_context(other), - basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other.socket())), + basic_socket<Protocol>(std::move(other.socket())), ec_(other.ec_), expiry_time_(other.expiry_time_) { @@ -300,7 +284,7 @@ public: { init_buffers(); typedef typename Protocol::resolver resolver_type; - resolver_type resolver(socket().get_executor().context()); + resolver_type resolver(socket().get_executor()); connect_to_endpoints(resolver.resolve(x..., ec_)); return !ec_ ? this : 0; } @@ -323,7 +307,7 @@ public: } /// Get a reference to the underlying socket. - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket() + basic_socket<Protocol>& socket() { return *this; } @@ -696,10 +680,6 @@ private: #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# undef BOOST_ASIO_SVC_T1 -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) # undef BOOST_ASIO_PRIVATE_CONNECT_DEF #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) diff --git a/boost/asio/basic_stream_socket.hpp b/boost/asio/basic_stream_socket.hpp index 9732c3c303..18d9daca50 100644 --- a/boost/asio/basic_stream_socket.hpp +++ b/boost/asio/basic_stream_socket.hpp @@ -2,7 +2,7 @@ // basic_stream_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -20,18 +20,24 @@ #include <boost/asio/async_result.hpp> #include <boost/asio/basic_socket.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/stream_socket_service.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { +#if !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Protocol, typename Executor = executor> +class basic_stream_socket; + +#endif // !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL) + /// Provides stream-oriented socket functionality. /** * The basic_stream_socket class template provides asynchronous and blocking @@ -44,18 +50,28 @@ namespace asio { * @par Concepts: * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. */ -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>)> +template <typename Protocol, typename Executor> class basic_stream_socket - : public basic_socket<Protocol BOOST_ASIO_SVC_TARG> + : public basic_socket<Protocol, Executor> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_stream_socket<Protocol, Executor1> other; + }; + /// The native representation of a socket. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type; #else - typedef typename basic_socket< - Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type; + typedef typename basic_socket<Protocol, + Executor>::native_handle_type native_handle_type; #endif /// The protocol type. @@ -70,11 +86,30 @@ public: * needs to be opened and then connected or accepted before data can be sent * or received on it. * - * @param io_context The io_context object that the stream socket will use to + * @param ex The I/O executor that the socket will use, by default, to * dispatch handlers for any asynchronous operations performed on the socket. */ - explicit basic_stream_socket(boost::asio::io_context& io_context) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context) + explicit basic_stream_socket(const executor_type& ex) + : basic_socket<Protocol, Executor>(ex) + { + } + + /// Construct a basic_stream_socket without opening it. + /** + * This constructor creates a stream socket without opening it. The socket + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + */ + template <typename ExecutionContext> + explicit basic_stream_socket(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context) { } @@ -83,16 +118,37 @@ public: * This constructor creates and opens a stream socket. The socket needs to be * connected or accepted before data can be sent or received on it. * - * @param io_context The io_context object that the stream socket will use to + * @param ex The I/O executor that the socket will use, by default, to * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. * * @throws boost::system::system_error Thrown on failure. */ - basic_stream_socket(boost::asio::io_context& io_context, - const protocol_type& protocol) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol) + basic_stream_socket(const executor_type& ex, const protocol_type& protocol) + : basic_socket<Protocol, Executor>(ex, protocol) + { + } + + /// Construct and open a basic_stream_socket. + /** + * This constructor creates and opens a stream socket. The socket needs to be + * connected or accepted before data can be sent or received on it. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_stream_socket(ExecutionContext& context, const protocol_type& protocol, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, protocol) { } @@ -103,7 +159,7 @@ public: * to the specified endpoint on the local machine. The protocol used is the * protocol associated with the given endpoint. * - * @param io_context The io_context object that the stream socket will use to + * @param ex The I/O executor that the socket will use, by default, to * dispatch handlers for any asynchronous operations performed on the socket. * * @param endpoint An endpoint on the local machine to which the stream @@ -111,9 +167,33 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_stream_socket(boost::asio::io_context& io_context, - const endpoint_type& endpoint) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint) + basic_stream_socket(const executor_type& ex, const endpoint_type& endpoint) + : basic_socket<Protocol, Executor>(ex, endpoint) + { + } + + /// Construct a basic_stream_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a stream socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the stream + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, endpoint) { } @@ -122,7 +202,7 @@ public: * This constructor creates a stream socket object to hold an existing native * socket. * - * @param io_context The io_context object that the stream socket will use to + * @param ex The I/O executor that the socket will use, by default, to * dispatch handlers for any asynchronous operations performed on the socket. * * @param protocol An object specifying protocol parameters to be used. @@ -131,10 +211,34 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_stream_socket(boost::asio::io_context& io_context, + basic_stream_socket(const executor_type& ex, const protocol_type& protocol, const native_handle_type& native_socket) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>( - io_context, protocol, native_socket) + : basic_socket<Protocol, Executor>(ex, protocol, native_socket) + { + } + + /// Construct a basic_stream_socket on an existing native socket. + /** + * This constructor creates a stream socket object to hold an existing native + * socket. + * + * @param context An execution context which provides the I/O executor that + * the socket will use, by default, to dispatch handlers for any asynchronous + * operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_stream_socket(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_socket, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(context, protocol, native_socket) { } @@ -147,10 +251,11 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_stream_socket(io_context&) constructor. + * constructed using the @c basic_stream_socket(const executor_type&) + * constructor. */ basic_stream_socket(basic_stream_socket&& other) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other)) + : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -162,11 +267,12 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_stream_socket(io_context&) constructor. + * constructed using the @c basic_stream_socket(const executor_type&) + * constructor. */ basic_stream_socket& operator=(basic_stream_socket&& other) { - basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other)); + basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } @@ -179,13 +285,16 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_stream_socket(io_context&) constructor. + * constructed using the @c basic_stream_socket(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - basic_stream_socket( - basic_stream_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other, - typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) - : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other)) + template <typename Protocol1, typename Executor1> + basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other, + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value + >::type* = 0) + : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -197,14 +306,17 @@ public: * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_stream_socket(io_context&) constructor. + * constructed using the @c basic_stream_socket(const executor_type&) + * constructor. */ - template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> - typename enable_if<is_convertible<Protocol1, Protocol>::value, - basic_stream_socket>::type& operator=( - basic_stream_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other) + template <typename Protocol1, typename Executor1> + typename enable_if< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value, + basic_stream_socket& + >::type operator=(basic_stream_socket<Protocol1, Executor1>&& other) { - basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other)); + basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -247,8 +359,8 @@ public: std::size_t send(const ConstBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().send( - this->get_implementation(), buffers, 0, ec); + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); boost::asio::detail::throw_error(ec, "send"); return s; } @@ -285,8 +397,8 @@ public: socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().send( - this->get_implementation(), buffers, flags, ec); + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); boost::asio::detail::throw_error(ec, "send"); return s; } @@ -313,8 +425,8 @@ public: std::size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().send( - this->get_implementation(), buffers, flags, ec); + return this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, flags, ec); } /// Start an asynchronous send. @@ -335,9 +447,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The send operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all @@ -358,24 +470,10 @@ public: async_send(const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send( - this->get_implementation(), buffers, 0, - BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send( - this->get_implementation(), buffers, 0, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous send. @@ -398,9 +496,9 @@ public: * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The send operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all @@ -422,24 +520,9 @@ public: socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send( - this->get_implementation(), buffers, flags, - BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send( - this->get_implementation(), buffers, flags, - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send(), handler, this, buffers, flags); } /// Receive some data on the socket. @@ -474,8 +557,8 @@ public: std::size_t receive(const MutableBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, 0, ec); + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); boost::asio::detail::throw_error(ec, "receive"); return s; } @@ -515,8 +598,8 @@ public: socket_base::message_flags flags) { boost::system::error_code ec; - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, flags, ec); + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); boost::asio::detail::throw_error(ec, "receive"); return s; } @@ -543,8 +626,8 @@ public: std::size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, boost::system::error_code& ec) { - return this->get_service().receive( - this->get_implementation(), buffers, flags, ec); + return this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, flags, ec); } /// Start an asynchronous receive. @@ -565,9 +648,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The receive operation may not receive all of the requested number of * bytes. Consider using the @ref async_read function if you need to ensure @@ -590,22 +673,10 @@ public: async_receive(const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive(this->get_implementation(), - buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive(this->get_implementation(), - buffers, 0, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive. @@ -628,9 +699,9 @@ public: * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The receive operation may not receive all of the requested number of * bytes. Consider using the @ref async_read function if you need to ensure @@ -654,22 +725,9 @@ public: socket_base::message_flags flags, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive(this->get_implementation(), - buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive(this->get_implementation(), - buffers, flags, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive(), handler, this, buffers, flags); } /// Write some data to the socket. @@ -703,8 +761,8 @@ public: std::size_t write_some(const ConstBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().send( - this->get_implementation(), buffers, 0, ec); + std::size_t s = this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); boost::asio::detail::throw_error(ec, "write_some"); return s; } @@ -729,7 +787,8 @@ public: std::size_t write_some(const ConstBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().send(this->get_implementation(), buffers, 0, ec); + return this->impl_.get_service().send( + this->impl_.get_implementation(), buffers, 0, ec); } /// Start an asynchronous write. @@ -750,9 +809,9 @@ public: * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all @@ -773,22 +832,10 @@ public: async_write_some(const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_send(this->get_implementation(), - buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_send(this->get_implementation(), - buffers, 0, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_send(), handler, this, + buffers, socket_base::message_flags(0)); } /// Read some data from the socket. @@ -823,8 +870,8 @@ public: std::size_t read_some(const MutableBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().receive( - this->get_implementation(), buffers, 0, ec); + std::size_t s = this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); boost::asio::detail::throw_error(ec, "read_some"); return s; } @@ -850,8 +897,8 @@ public: std::size_t read_some(const MutableBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().receive( - this->get_implementation(), buffers, 0, ec); + return this->impl_.get_service().receive( + this->impl_.get_implementation(), buffers, 0, ec); } /// Start an asynchronous read. @@ -872,9 +919,9 @@ public: * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the @@ -896,23 +943,48 @@ public: async_read_some(const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_receive(this->get_implementation(), - buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_receive(this->get_implementation(), - buffers, 0, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_receive(), handler, this, + buffers, socket_base::message_flags(0)); } + +private: + struct initiate_async_send + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> 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/boost/asio/basic_streambuf.hpp b/boost/asio/basic_streambuf.hpp index e6f8f33f6b..e2e9bf9071 100644 --- a/boost/asio/basic_streambuf.hpp +++ b/boost/asio/basic_streambuf.hpp @@ -2,7 +2,7 @@ // basic_streambuf.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/basic_streambuf_fwd.hpp b/boost/asio/basic_streambuf_fwd.hpp index f2ef522d9b..68907ef282 100644 --- a/boost/asio/basic_streambuf_fwd.hpp +++ b/boost/asio/basic_streambuf_fwd.hpp @@ -2,7 +2,7 @@ // basic_streambuf_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/basic_waitable_timer.hpp b/boost/asio/basic_waitable_timer.hpp index 6dc4bded98..45373f7caf 100644 --- a/boost/asio/basic_waitable_timer.hpp +++ b/boost/asio/basic_waitable_timer.hpp @@ -2,7 +2,7 @@ // basic_waitable_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,26 +17,20 @@ #include <boost/asio/detail/config.hpp> #include <cstddef> -#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/detail/chrono_time_traits.hpp> +#include <boost/asio/detail/deadline_timer_service.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> +#include <boost/asio/executor.hpp> #include <boost/asio/wait_traits.hpp> #if defined(BOOST_ASIO_HAS_MOVE) # include <utility> #endif // defined(BOOST_ASIO_HAS_MOVE) -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/waitable_timer_service.hpp> -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/detail/chrono_time_traits.hpp> -# include <boost/asio/detail/deadline_timer_service.hpp> -# define BOOST_ASIO_SVC_T \ - detail::deadline_timer_service< \ - detail::chrono_time_traits<Clock, WaitTraits> > -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -47,8 +41,8 @@ namespace asio { // Forward declaration with defaulted arguments. template <typename Clock, - typename WaitTraits = boost::asio::wait_traits<Clock> - BOOST_ASIO_SVC_TPARAM_DEF2(= waitable_timer_service<Clock, WaitTraits>)> + typename WaitTraits = boost::asio::wait_traits<Clock>, + typename Executor = executor> class basic_waitable_timer; #endif // !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL) @@ -76,7 +70,7 @@ class basic_waitable_timer; * Performing a blocking wait (C++11): * @code * // Construct a timer without setting an expiry time. - * boost::asio::steady_timer timer(io_context); + * boost::asio::steady_timer timer(my_context); * * // Set an expiry time relative to now. * timer.expires_after(std::chrono::seconds(5)); @@ -99,7 +93,7 @@ class basic_waitable_timer; * ... * * // Construct a timer with an absolute expiry time. - * boost::asio::steady_timer timer(io_context, + * boost::asio::steady_timer timer(my_context, * std::chrono::steady_clock::now() + std::chrono::seconds(60)); * * // Start an asynchronous wait. @@ -145,13 +139,12 @@ class basic_waitable_timer; * @li If a wait handler is cancelled, the boost::system::error_code passed to * it contains the value boost::asio::error::operation_aborted. */ -template <typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM> +template <typename Clock, typename WaitTraits, typename Executor> class basic_waitable_timer - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T> { public: /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; + typedef Executor executor_type; /// The clock type. typedef Clock clock_type; @@ -171,11 +164,30 @@ public: * expires_at() or expires_after() functions must be called to set an expiry * time before the timer can be waited on. * - * @param io_context The io_context object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. + * @param ex The I/O executor that the timer will use, by default, to + * dispatch handlers for any asynchronous operations performed on the timer. + */ + explicit basic_waitable_timer(const executor_type& ex) + : impl_(ex) + { + } + + /// Constructor. + /** + * This constructor creates a timer without setting an expiry time. The + * expires_at() or expires_after() functions must be called to set an expiry + * time before the timer can be waited on. + * + * @param context An execution context which provides the I/O executor that + * the timer will use, by default, to dispatch handlers for any asynchronous + * operations performed on the timer. */ - explicit basic_waitable_timer(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + template <typename ExecutionContext> + explicit basic_waitable_timer(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { } @@ -183,38 +195,85 @@ public: /** * This constructor creates a timer and sets the expiry time. * - * @param io_context The io_context object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. + * @param ex The I/O executor object that the timer will use, by default, to + * dispatch handlers for any asynchronous operations performed on the timer. * * @param expiry_time The expiry time to be used for the timer, expressed * as an absolute time. */ - basic_waitable_timer(boost::asio::io_context& io_context, - const time_point& expiry_time) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + basic_waitable_timer(const executor_type& ex, const time_point& expiry_time) + : impl_(ex) { boost::system::error_code ec; - this->get_service().expires_at(this->get_implementation(), expiry_time, ec); + impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_at"); } + /// Constructor to set a particular expiry time as an absolute time. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param context An execution context which provides the I/O executor that + * the timer will use, by default, to dispatch handlers for any asynchronous + * operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, expressed + * as an absolute time. + */ + template <typename ExecutionContext> + explicit basic_waitable_timer(ExecutionContext& context, + const time_point& expiry_time, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_at"); + } + + /// Constructor to set a particular expiry time relative to now. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param ex The I/O executor that the timer will use, by default, to + * dispatch handlers for any asynchronous operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, relative to + * now. + */ + basic_waitable_timer(const executor_type& ex, const duration& expiry_time) + : impl_(ex) + { + boost::system::error_code ec; + impl_.get_service().expires_after( + impl_.get_implementation(), expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_after"); + } + /// Constructor to set a particular expiry time relative to now. /** * This constructor creates a timer and sets the expiry time. * - * @param io_context The io_context object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. + * @param context An execution context which provides the I/O executor that + * the timer will use, by default, to dispatch handlers for any asynchronous + * operations performed on the timer. * * @param expiry_time The expiry time to be used for the timer, relative to * now. */ - basic_waitable_timer(boost::asio::io_context& io_context, - const duration& expiry_time) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + template <typename ExecutionContext> + explicit basic_waitable_timer(ExecutionContext& context, + const duration& expiry_time, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { boost::system::error_code ec; - this->get_service().expires_after( - this->get_implementation(), expiry_time, ec); + impl_.get_service().expires_after( + impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_after"); } @@ -227,10 +286,11 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_waitable_timer(io_context&) constructor. + * constructed using the @c basic_waitable_timer(const executor_type&) + * constructor. */ basic_waitable_timer(basic_waitable_timer&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) + : impl_(std::move(other.impl_)) { } @@ -243,11 +303,12 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_waitable_timer(io_context&) constructor. + * constructed using the @c basic_waitable_timer(const executor_type&) + * constructor. */ basic_waitable_timer& operator=(basic_waitable_timer&& other) { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); + impl_ = std::move(other.impl_); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -261,45 +322,11 @@ public: { } -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - // These functions are provided by basic_io_object<>. -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Get the executor associated with the object. executor_type get_executor() BOOST_ASIO_NOEXCEPT { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); + return impl_.get_executor(); } -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) /// Cancel any asynchronous operations that are waiting on the timer. /** @@ -326,7 +353,7 @@ public: std::size_t cancel() { boost::system::error_code ec; - std::size_t s = this->get_service().cancel(this->get_implementation(), ec); + std::size_t s = impl_.get_service().cancel(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel"); return s; } @@ -357,7 +384,7 @@ public: */ std::size_t cancel(boost::system::error_code& ec) { - return this->get_service().cancel(this->get_implementation(), ec); + return impl_.get_service().cancel(impl_.get_implementation(), ec); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -388,8 +415,8 @@ public: std::size_t cancel_one() { boost::system::error_code ec; - std::size_t s = this->get_service().cancel_one( - this->get_implementation(), ec); + std::size_t s = impl_.get_service().cancel_one( + impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel_one"); return s; } @@ -422,7 +449,7 @@ public: */ std::size_t cancel_one(boost::system::error_code& ec) { - return this->get_service().cancel_one(this->get_implementation(), ec); + return impl_.get_service().cancel_one(impl_.get_implementation(), ec); } /// (Deprecated: Use expiry().) Get the timer's expiry time as an absolute @@ -433,7 +460,7 @@ public: */ time_point expires_at() const { - return this->get_service().expires_at(this->get_implementation()); + return impl_.get_service().expires_at(impl_.get_implementation()); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -444,7 +471,7 @@ public: */ time_point expiry() const { - return this->get_service().expiry(this->get_implementation()); + return impl_.get_service().expiry(impl_.get_implementation()); } /// Set the timer's expiry time as an absolute time. @@ -472,8 +499,8 @@ public: std::size_t expires_at(const time_point& expiry_time) { boost::system::error_code ec; - std::size_t s = this->get_service().expires_at( - this->get_implementation(), expiry_time, ec); + std::size_t s = impl_.get_service().expires_at( + impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_at"); return s; } @@ -505,8 +532,8 @@ public: std::size_t expires_at(const time_point& expiry_time, boost::system::error_code& ec) { - return this->get_service().expires_at( - this->get_implementation(), expiry_time, ec); + return impl_.get_service().expires_at( + impl_.get_implementation(), expiry_time, ec); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -535,8 +562,8 @@ public: std::size_t expires_after(const duration& expiry_time) { boost::system::error_code ec; - std::size_t s = this->get_service().expires_after( - this->get_implementation(), expiry_time, ec); + std::size_t s = impl_.get_service().expires_after( + impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_after"); return s; } @@ -549,7 +576,7 @@ public: */ duration expires_from_now() const { - return this->get_service().expires_from_now(this->get_implementation()); + return impl_.get_service().expires_from_now(impl_.get_implementation()); } /// (Deprecated: Use expires_after().) Set the timer's expiry time relative @@ -578,8 +605,8 @@ public: std::size_t expires_from_now(const duration& expiry_time) { boost::system::error_code ec; - std::size_t s = this->get_service().expires_from_now( - this->get_implementation(), expiry_time, ec); + std::size_t s = impl_.get_service().expires_from_now( + impl_.get_implementation(), expiry_time, ec); boost::asio::detail::throw_error(ec, "expires_from_now"); return s; } @@ -610,8 +637,8 @@ public: std::size_t expires_from_now(const duration& expiry_time, boost::system::error_code& ec) { - return this->get_service().expires_from_now( - this->get_implementation(), expiry_time, ec); + return impl_.get_service().expires_from_now( + impl_.get_implementation(), expiry_time, ec); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -625,7 +652,7 @@ public: void wait() { boost::system::error_code ec; - this->get_service().wait(this->get_implementation(), ec); + impl_.get_service().wait(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "wait"); } @@ -638,7 +665,7 @@ public: */ void wait(boost::system::error_code& ec) { - this->get_service().wait(this->get_implementation(), ec); + impl_.get_service().wait(impl_.get_implementation(), ec); } /// Start an asynchronous wait on the timer. @@ -661,31 +688,17 @@ public: * const boost::system::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename WaitHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, void (boost::system::error_code)) async_wait(BOOST_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. - BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_wait(this->get_implementation(), - BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_wait(this->get_implementation(), - init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WaitHandler, void (boost::system::error_code)>( + initiate_async_wait(), handler, this); } private: @@ -693,6 +706,28 @@ private: basic_waitable_timer(const basic_waitable_timer&) BOOST_ASIO_DELETED; basic_waitable_timer& operator=( const basic_waitable_timer&) BOOST_ASIO_DELETED; + + struct initiate_async_wait + { + template <typename WaitHandler> + void operator()(BOOST_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. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue<WaitHandler> 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<Clock, WaitTraits> >, + executor_type > impl_; }; } // namespace asio @@ -700,8 +735,4 @@ private: #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# undef BOOST_ASIO_SVC_T -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP diff --git a/boost/asio/bind_executor.hpp b/boost/asio/bind_executor.hpp index c4086b6135..cd1498098c 100644 --- a/boost/asio/bind_executor.hpp +++ b/boost/asio/bind_executor.hpp @@ -2,7 +2,7 @@ // bind_executor.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -548,37 +548,6 @@ private: async_result<T, Signature> target_; }; -#if !defined(BOOST_ASIO_NO_DEPRECATED) - -template <typename T, typename Executor, typename Signature> -struct handler_type<executor_binder<T, Executor>, Signature> -{ - typedef executor_binder< - typename handler_type<T, Signature>::type, Executor> type; -}; - -template <typename T, typename Executor> -class async_result<executor_binder<T, Executor> > -{ -public: - typedef typename async_result<T>::type type; - - explicit async_result(executor_binder<T, Executor>& b) - : target_(b.get()) - { - } - - type get() - { - return target_.get(); - } - -private: - async_result<T> target_; -}; - -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - template <typename T, typename Executor, typename Allocator> struct associated_allocator<executor_binder<T, Executor>, Allocator> { diff --git a/boost/asio/buffer.hpp b/boost/asio/buffer.hpp index 29352f6481..6958b2e84a 100644 --- a/boost/asio/buffer.hpp +++ b/boost/asio/buffer.hpp @@ -2,7 +2,7 @@ // buffer.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -23,6 +23,7 @@ #include <string> #include <vector> #include <boost/asio/detail/array_fwd.hpp> +#include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/string_view.hpp> #include <boost/asio/detail/throw_exception.hpp> #include <boost/asio/detail/type_traits.hpp> @@ -382,29 +383,45 @@ private: /*@{*/ /// Get an iterator to the first element in a buffer sequence. -inline const mutable_buffer* buffer_sequence_begin(const mutable_buffer& b) +template <typename MutableBuffer> +inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b, + typename enable_if< + is_convertible<const MutableBuffer*, const mutable_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT { - return &b; + return static_cast<const mutable_buffer*>(detail::addressof(b)); } /// Get an iterator to the first element in a buffer sequence. -inline const const_buffer* buffer_sequence_begin(const const_buffer& b) +template <typename ConstBuffer> +inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b, + typename enable_if< + is_convertible<const ConstBuffer*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT { - return &b; + return static_cast<const const_buffer*>(detail::addressof(b)); } #if defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) /// Get an iterator to the first element in a buffer sequence. template <typename C> -inline auto buffer_sequence_begin(C& c) -> decltype(c.begin()) +inline auto buffer_sequence_begin(C& c, + typename enable_if< + !is_convertible<const C*, const mutable_buffer*>::value + && !is_convertible<const C*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.begin()) { return c.begin(); } /// Get an iterator to the first element in a buffer sequence. template <typename C> -inline auto buffer_sequence_begin(const C& c) -> decltype(c.begin()) +inline auto buffer_sequence_begin(const C& c, + typename enable_if< + !is_convertible<const C*, const mutable_buffer*>::value + && !is_convertible<const C*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.begin()) { return c.begin(); } @@ -412,13 +429,21 @@ inline auto buffer_sequence_begin(const C& c) -> decltype(c.begin()) #else // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) template <typename C> -inline typename C::iterator buffer_sequence_begin(C& c) +inline typename C::iterator buffer_sequence_begin(C& c, + typename enable_if< + !is_convertible<const C*, const mutable_buffer*>::value + && !is_convertible<const C*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT { return c.begin(); } template <typename C> -inline typename C::const_iterator buffer_sequence_begin(const C& c) +inline typename C::const_iterator buffer_sequence_begin(const C& c, + typename enable_if< + !is_convertible<const C*, const mutable_buffer*>::value + && !is_convertible<const C*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT { return c.begin(); } @@ -435,29 +460,45 @@ inline typename C::const_iterator buffer_sequence_begin(const C& c) /*@{*/ /// Get an iterator to one past the end element in a buffer sequence. -inline const mutable_buffer* buffer_sequence_end(const mutable_buffer& b) +template <typename MutableBuffer> +inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b, + typename enable_if< + is_convertible<const MutableBuffer*, const mutable_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT { - return &b + 1; + return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1; } /// Get an iterator to one past the end element in a buffer sequence. -inline const const_buffer* buffer_sequence_end(const const_buffer& b) +template <typename ConstBuffer> +inline const const_buffer* buffer_sequence_end(const ConstBuffer& b, + typename enable_if< + is_convertible<const ConstBuffer*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT { - return &b + 1; + return static_cast<const const_buffer*>(detail::addressof(b)) + 1; } #if defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) /// Get an iterator to one past the end element in a buffer sequence. template <typename C> -inline auto buffer_sequence_end(C& c) -> decltype(c.end()) +inline auto buffer_sequence_end(C& c, + typename enable_if< + !is_convertible<const C*, const mutable_buffer*>::value + && !is_convertible<const C*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.end()) { return c.end(); } /// Get an iterator to one past the end element in a buffer sequence. template <typename C> -inline auto buffer_sequence_end(const C& c) -> decltype(c.end()) +inline auto buffer_sequence_end(const C& c, + typename enable_if< + !is_convertible<const C*, const mutable_buffer*>::value + && !is_convertible<const C*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.end()) { return c.end(); } @@ -465,13 +506,21 @@ inline auto buffer_sequence_end(const C& c) -> decltype(c.end()) #else // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) template <typename C> -inline typename C::iterator buffer_sequence_end(C& c) +inline typename C::iterator buffer_sequence_end(C& c, + typename enable_if< + !is_convertible<const C*, const mutable_buffer*>::value + && !is_convertible<const C*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT { return c.end(); } template <typename C> -inline typename C::const_iterator buffer_sequence_end(const C& c) +inline typename C::const_iterator buffer_sequence_end(const C& c, + typename enable_if< + !is_convertible<const C*, const mutable_buffer*>::value + && !is_convertible<const C*, const const_buffer*>::value + >::type* = 0) BOOST_ASIO_NOEXCEPT { return c.end(); } @@ -1498,19 +1547,23 @@ template <typename Elem, typename Traits, typename Allocator> class dynamic_string_buffer { public: - /// The type used to represent the input sequence as a list of buffers. + /// The type used to represent a sequence of constant buffers that refers to + /// the underlying memory. typedef BOOST_ASIO_CONST_BUFFER const_buffers_type; - /// The type used to represent the output sequence as a list of buffers. + /// The type used to represent a sequence of mutable buffers that refers to + /// the underlying memory. typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type; /// Construct a dynamic buffer from a string. /** * @param s The string to be used as backing storage for the dynamic buffer. - * Any existing data in the string is treated as the dynamic buffer's input - * sequence. The object stores a reference to the string and the user is - * responsible for ensuring that the string object remains valid until the - * dynamic_string_buffer object is destroyed. + * The object stores a reference to the string and the user is responsible + * for ensuring that the string object remains valid while the + * dynamic_string_buffer object, and copies of the object, are in use. + * + * @b DynamicBuffer_v1: Any existing data in the string is treated as the + * dynamic buffer's input sequence. * * @param maximum_size Specifies a maximum size for the buffer, in bytes. */ @@ -1518,64 +1571,131 @@ public: std::size_t maximum_size = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT : string_(s), - size_(string_.size()), +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + size_((std::numeric_limits<std::size_t>::max)()), +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) max_size_(maximum_size) { } + /// @b DynamicBuffer_v2: Copy construct a dynamic buffer. + dynamic_string_buffer(const dynamic_string_buffer& other) BOOST_ASIO_NOEXCEPT + : string_(other.string_), +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + size_(other.size_), +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + max_size_(other.max_size_) + { + } + #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move construct a dynamic buffer. dynamic_string_buffer(dynamic_string_buffer&& other) BOOST_ASIO_NOEXCEPT : string_(other.string_), +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) size_(other.size_), +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) max_size_(other.max_size_) { } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Get the size of the input sequence. + /// @b DynamicBuffer_v1: Get the size of the input sequence. + /// @b DynamicBuffer_v2: Get the current size of the underlying memory. + /** + * @returns @b DynamicBuffer_v1 The current size of the input sequence. + * @b DynamicBuffer_v2: The current size of the underlying string if less than + * max_size(). Otherwise returns max_size(). + */ std::size_t size() const BOOST_ASIO_NOEXCEPT { - return size_; +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + if (size_ != (std::numeric_limits<std::size_t>::max)()) + return size_; +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + return (std::min)(string_.size(), max_size()); } /// Get the maximum size of the dynamic buffer. /** - * @returns The allowed maximum of the sum of the sizes of the input sequence - * and output sequence. + * @returns The allowed maximum size of the underlying memory. */ std::size_t max_size() const BOOST_ASIO_NOEXCEPT { return max_size_; } - /// Get the current capacity of the dynamic buffer. + /// Get the maximum size that the buffer may grow to without triggering + /// reallocation. /** - * @returns The current total capacity of the buffer, i.e. for both the input - * sequence and output sequence. + * @returns The current capacity of the underlying string if less than + * max_size(). Otherwise returns max_size(). */ std::size_t capacity() const BOOST_ASIO_NOEXCEPT { - return string_.capacity(); + return (std::min)(string_.capacity(), max_size()); } - /// Get a list of buffers that represents the input sequence. +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// @b DynamicBuffer_v1: Get a list of buffers that represents the input + /// sequence. /** * @returns An object of type @c const_buffers_type that satisfies * ConstBufferSequence requirements, representing the basic_string memory in - * input sequence. + * the input sequence. * * @note The returned object is invalidated by any @c dynamic_string_buffer - * or @c basic_string member function that modifies the input sequence or - * output sequence. + * or @c basic_string member function that resizes or erases the string. */ const_buffers_type data() const BOOST_ASIO_NOEXCEPT { return const_buffers_type(boost::asio::buffer(string_, size_)); } +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) - /// Get a list of buffers that represents the output sequence, with the given - /// size. + /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the + /// underlying memory. + /** + * @param pos Position of the first byte to represent in the buffer sequence + * + * @param n The number of bytes to return in the buffer sequence. If the + * underlying memory is shorter, the buffer sequence represents as many bytes + * as are available. + * + * @returns An object of type @c mutable_buffers_type that satisfies + * MutableBufferSequence requirements, representing the basic_string memory. + * + * @note The returned object is invalidated by any @c dynamic_string_buffer + * or @c basic_string member function that resizes or erases the string. + */ + mutable_buffers_type data(std::size_t pos, std::size_t n) BOOST_ASIO_NOEXCEPT + { + return mutable_buffers_type(boost::asio::buffer( + boost::asio::buffer(string_, max_size_) + pos, n)); + } + + /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the + /// underlying memory. + /** + * @param pos Position of the first byte to represent in the buffer sequence + * + * @param n The number of bytes to return in the buffer sequence. If the + * underlying memory is shorter, the buffer sequence represents as many bytes + * as are available. + * + * @note The returned object is invalidated by any @c dynamic_string_buffer + * or @c basic_string member function that resizes or erases the string. + */ + const_buffers_type data(std::size_t pos, + std::size_t n) const BOOST_ASIO_NOEXCEPT + { + return const_buffers_type(boost::asio::buffer( + boost::asio::buffer(string_, max_size_) + pos, n)); + } + +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// @b DynamicBuffer_v1: Get a list of buffers that represents the output + /// sequence, with the given size. /** * Ensures that the output sequence can accommodate @c n bytes, resizing the * basic_string object as necessary. @@ -1592,18 +1712,22 @@ public: */ mutable_buffers_type prepare(std::size_t n) { - if (size () > max_size() || max_size() - size() < n) + if (size() > max_size() || max_size() - size() < n) { std::length_error ex("dynamic_string_buffer too long"); boost::asio::detail::throw_exception(ex); } + if (size_ == (std::numeric_limits<std::size_t>::max)()) + size_ = string_.size(); // Enable v1 behaviour. + string_.resize(size_ + n); return boost::asio::buffer(boost::asio::buffer(string_) + size_, n); } - /// Move bytes from the output sequence to the input sequence. + /// @b DynamicBuffer_v1: Move bytes from the output sequence to the input + /// sequence. /** * @param n The number of bytes to append from the start of the output * sequence to the end of the input sequence. The remainder of the output @@ -1620,24 +1744,69 @@ public: size_ += (std::min)(n, string_.size() - size_); string_.resize(size_); } +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) - /// Remove characters from the input sequence. + /// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of + /// bytes. /** - * Removes @c n characters from the beginning of the input sequence. + * Resizes the string to accommodate an additional @c n bytes at the end. * - * @note If @c n is greater than the size of the input sequence, the entire - * input sequence is consumed and no error is issued. + * @throws std::length_error If <tt>size() + n > max_size()</tt>. + */ + void grow(std::size_t n) + { + if (size() > max_size() || max_size() - size() < n) + { + std::length_error ex("dynamic_string_buffer too long"); + boost::asio::detail::throw_exception(ex); + } + + string_.resize(size() + n); + } + + /// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number + /// of bytes. + /** + * Erases @c n bytes from the end of the string by resizing the basic_string + * object. If @c n is greater than the current size of the string, the string + * is emptied. + */ + void shrink(std::size_t n) + { + string_.resize(n > size() ? 0 : size() - n); + } + + /// @b DynamicBuffer_v1: Remove characters from the input sequence. + /// @b DynamicBuffer_v2: Consume the specified number of bytes from the + /// beginning of the underlying memory. + /** + * @b DynamicBuffer_v1: Removes @c n characters from the beginning of the + * input sequence. @note If @c n is greater than the size of the input + * sequence, the entire input sequence is consumed and no error is issued. + * + * @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the string. + * If @c n is greater than the current size of the string, the string is + * emptied. */ void consume(std::size_t n) { - std::size_t consume_length = (std::min)(n, size_); - string_.erase(0, consume_length); - size_ -= consume_length; +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + if (size_ != (std::numeric_limits<std::size_t>::max)()) + { + std::size_t consume_length = (std::min)(n, size_); + string_.erase(0, consume_length); + size_ -= consume_length; + return; + } +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + string_.erase(0, n); } private: std::basic_string<Elem, Traits, Allocator>& string_; +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) std::size_t size_; +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) const std::size_t max_size_; }; @@ -1649,19 +1818,20 @@ template <typename Elem, typename Allocator> class dynamic_vector_buffer { public: - /// The type used to represent the input sequence as a list of buffers. + /// The type used to represent a sequence of constant buffers that refers to + /// the underlying memory. typedef BOOST_ASIO_CONST_BUFFER const_buffers_type; - /// The type used to represent the output sequence as a list of buffers. + /// The type used to represent a sequence of mutable buffers that refers to + /// the underlying memory. typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type; - /// Construct a dynamic buffer from a string. + /// Construct a dynamic buffer from a vector. /** * @param v The vector to be used as backing storage for the dynamic buffer. - * Any existing data in the vector is treated as the dynamic buffer's input - * sequence. The object stores a reference to the vector and the user is - * responsible for ensuring that the vector object remains valid until the - * dynamic_vector_buffer object is destroyed. + * The object stores a reference to the vector and the user is responsible + * for ensuring that the vector object remains valid while the + * dynamic_vector_buffer object, and copies of the object, are in use. * * @param maximum_size Specifies a maximum size for the buffer, in bytes. */ @@ -1669,77 +1839,149 @@ public: std::size_t maximum_size = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT : vector_(v), - size_(vector_.size()), +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + size_((std::numeric_limits<std::size_t>::max)()), +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) max_size_(maximum_size) { } + /// @b DynamicBuffer_v2: Copy construct a dynamic buffer. + dynamic_vector_buffer(const dynamic_vector_buffer& other) BOOST_ASIO_NOEXCEPT + : vector_(other.vector_), +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + size_(other.size_), +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + max_size_(other.max_size_) + { + } + #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move construct a dynamic buffer. dynamic_vector_buffer(dynamic_vector_buffer&& other) BOOST_ASIO_NOEXCEPT : vector_(other.vector_), +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) size_(other.size_), +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) max_size_(other.max_size_) { } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Get the size of the input sequence. + /// @b DynamicBuffer_v1: Get the size of the input sequence. + /// @b DynamicBuffer_v2: Get the current size of the underlying memory. + /** + * @returns @b DynamicBuffer_v1 The current size of the input sequence. + * @b DynamicBuffer_v2: The current size of the underlying vector if less than + * max_size(). Otherwise returns max_size(). + */ std::size_t size() const BOOST_ASIO_NOEXCEPT { - return size_; +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + if (size_ != (std::numeric_limits<std::size_t>::max)()) + return size_; +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + return (std::min)(vector_.size(), max_size()); } /// Get the maximum size of the dynamic buffer. /** - * @returns The allowed maximum of the sum of the sizes of the input sequence - * and output sequence. + * @returns @b DynamicBuffer_v1: The allowed maximum of the sum of the sizes + * of the input sequence and output sequence. @b DynamicBuffer_v2: The allowed + * maximum size of the underlying memory. */ std::size_t max_size() const BOOST_ASIO_NOEXCEPT { return max_size_; } - /// Get the current capacity of the dynamic buffer. + /// Get the maximum size that the buffer may grow to without triggering + /// reallocation. /** - * @returns The current total capacity of the buffer, i.e. for both the input - * sequence and output sequence. + * @returns @b DynamicBuffer_v1: The current total capacity of the buffer, + * i.e. for both the input sequence and output sequence. @b DynamicBuffer_v2: + * The current capacity of the underlying vector if less than max_size(). + * Otherwise returns max_size(). */ std::size_t capacity() const BOOST_ASIO_NOEXCEPT { - return vector_.capacity(); + return (std::min)(vector_.capacity(), max_size()); } - /// Get a list of buffers that represents the input sequence. +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// @b DynamicBuffer_v1: Get a list of buffers that represents the input + /// sequence. /** * @returns An object of type @c const_buffers_type that satisfies - * ConstBufferSequence requirements, representing the basic_string memory in + * ConstBufferSequence requirements, representing the vector memory in the * input sequence. * * @note The returned object is invalidated by any @c dynamic_vector_buffer - * or @c basic_string member function that modifies the input sequence or - * output sequence. + * or @c vector member function that modifies the input sequence or output + * sequence. */ const_buffers_type data() const BOOST_ASIO_NOEXCEPT { return const_buffers_type(boost::asio::buffer(vector_, size_)); } +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) - /// Get a list of buffers that represents the output sequence, with the given - /// size. + /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the + /// underlying memory. + /** + * @param pos Position of the first byte to represent in the buffer sequence + * + * @param n The number of bytes to return in the buffer sequence. If the + * underlying memory is shorter, the buffer sequence represents as many bytes + * as are available. + * + * @returns An object of type @c mutable_buffers_type that satisfies + * MutableBufferSequence requirements, representing the vector memory. + * + * @note The returned object is invalidated by any @c dynamic_vector_buffer + * or @c vector member function that resizes or erases the vector. + */ + mutable_buffers_type data(std::size_t pos, std::size_t n) BOOST_ASIO_NOEXCEPT + { + return mutable_buffers_type(boost::asio::buffer( + boost::asio::buffer(vector_, max_size_) + pos, n)); + } + + /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the + /// underlying memory. + /** + * @param pos Position of the first byte to represent in the buffer sequence + * + * @param n The number of bytes to return in the buffer sequence. If the + * underlying memory is shorter, the buffer sequence represents as many bytes + * as are available. + * + * @note The returned object is invalidated by any @c dynamic_vector_buffer + * or @c vector member function that resizes or erases the vector. + */ + const_buffers_type data(std::size_t pos, + std::size_t n) const BOOST_ASIO_NOEXCEPT + { + return const_buffers_type(boost::asio::buffer( + boost::asio::buffer(vector_, max_size_) + pos, n)); + } + +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// @b DynamicBuffer_v1: Get a list of buffers that represents the output + /// sequence, with the given size. /** * Ensures that the output sequence can accommodate @c n bytes, resizing the - * basic_string object as necessary. + * vector object as necessary. * * @returns An object of type @c mutable_buffers_type that satisfies - * MutableBufferSequence requirements, representing basic_string memory - * at the start of the output sequence of size @c n. + * MutableBufferSequence requirements, representing vector memory at the + * start of the output sequence of size @c n. * * @throws std::length_error If <tt>size() + n > max_size()</tt>. * * @note The returned object is invalidated by any @c dynamic_vector_buffer - * or @c basic_string member function that modifies the input sequence or - * output sequence. + * or @c vector member function that modifies the input sequence or output + * sequence. */ mutable_buffers_type prepare(std::size_t n) { @@ -1749,12 +1991,16 @@ public: boost::asio::detail::throw_exception(ex); } + if (size_ == (std::numeric_limits<std::size_t>::max)()) + size_ = vector_.size(); // Enable v1 behaviour. + vector_.resize(size_ + n); return boost::asio::buffer(boost::asio::buffer(vector_) + size_, n); } - /// Move bytes from the output sequence to the input sequence. + /// @b DynamicBuffer_v1: Move bytes from the output sequence to the input + /// sequence. /** * @param n The number of bytes to append from the start of the output * sequence to the end of the input sequence. The remainder of the output @@ -1771,24 +2017,69 @@ public: size_ += (std::min)(n, vector_.size() - size_); vector_.resize(size_); } +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) - /// Remove characters from the input sequence. + /// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of + /// bytes. /** - * Removes @c n characters from the beginning of the input sequence. + * Resizes the vector to accommodate an additional @c n bytes at the end. * - * @note If @c n is greater than the size of the input sequence, the entire - * input sequence is consumed and no error is issued. + * @throws std::length_error If <tt>size() + n > max_size()</tt>. + */ + void grow(std::size_t n) + { + if (size() > max_size() || max_size() - size() < n) + { + std::length_error ex("dynamic_vector_buffer too long"); + boost::asio::detail::throw_exception(ex); + } + + vector_.resize(size() + n); + } + + /// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number + /// of bytes. + /** + * Erases @c n bytes from the end of the vector by resizing the vector + * object. If @c n is greater than the current size of the vector, the vector + * is emptied. + */ + void shrink(std::size_t n) + { + vector_.resize(n > size() ? 0 : size() - n); + } + + /// @b DynamicBuffer_v1: Remove characters from the input sequence. + /// @b DynamicBuffer_v2: Consume the specified number of bytes from the + /// beginning of the underlying memory. + /** + * @b DynamicBuffer_v1: Removes @c n characters from the beginning of the + * input sequence. @note If @c n is greater than the size of the input + * sequence, the entire input sequence is consumed and no error is issued. + * + * @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the vector. + * If @c n is greater than the current size of the vector, the vector is + * emptied. */ void consume(std::size_t n) { - std::size_t consume_length = (std::min)(n, size_); - vector_.erase(vector_.begin(), vector_.begin() + consume_length); - size_ -= consume_length; +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + if (size_ != (std::numeric_limits<std::size_t>::max)()) + { + std::size_t consume_length = (std::min)(n, size_); + vector_.erase(vector_.begin(), vector_.begin() + consume_length); + size_ -= consume_length; + return; + } +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + vector_.erase(vector_.begin(), vector_.begin() + (std::min)(size(), n)); } private: std::vector<Elem, Allocator>& vector_; +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) std::size_t size_; +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) const std::size_t max_size_; }; @@ -2154,17 +2445,51 @@ struct is_const_buffer_sequence { }; -/// Trait to determine whether a type satisfies the DynamicBuffer requirements. +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) +/// Trait to determine whether a type satisfies the DynamicBuffer_v1 +/// requirements. template <typename T> -struct is_dynamic_buffer +struct is_dynamic_buffer_v1 +#if defined(GENERATING_DOCUMENTATION) + : integral_constant<bool, automatically_determined> +#else // defined(GENERATING_DOCUMENTATION) + : boost::asio::detail::is_dynamic_buffer_v1<T> +#endif // defined(GENERATING_DOCUMENTATION) +{ +}; +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +/// Trait to determine whether a type satisfies the DynamicBuffer_v2 +/// requirements. +template <typename T> +struct is_dynamic_buffer_v2 #if defined(GENERATING_DOCUMENTATION) : integral_constant<bool, automatically_determined> #else // defined(GENERATING_DOCUMENTATION) - : boost::asio::detail::is_dynamic_buffer<T> + : boost::asio::detail::is_dynamic_buffer_v2<T> #endif // defined(GENERATING_DOCUMENTATION) { }; +/// Trait to determine whether a type satisfies the DynamicBuffer requirements. +/** + * If @c BOOST_ASIO_NO_DYNAMIC_BUFFER_V1 is not defined, determines whether the + * type satisfies the DynamicBuffer_v1 requirements. Otherwise, if @c + * BOOST_ASIO_NO_DYNAMIC_BUFFER_V1 is defined, determines whether the type + * satisfies the DynamicBuffer_v1 requirements. + */ +template <typename T> +struct is_dynamic_buffer +#if defined(GENERATING_DOCUMENTATION) + : integral_constant<bool, automatically_determined> +#elif defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + : boost::asio::is_dynamic_buffer_v2<T> +#else // defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + : boost::asio::is_dynamic_buffer_v1<T> +#endif // defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) +{ +}; + } // namespace asio } // namespace boost diff --git a/boost/asio/buffered_read_stream.hpp b/boost/asio/buffered_read_stream.hpp index 28df23908d..cd1e0626a5 100644 --- a/boost/asio/buffered_read_stream.hpp +++ b/boost/asio/buffered_read_stream.hpp @@ -2,7 +2,7 @@ // buffered_read_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -26,7 +26,6 @@ #include <boost/asio/detail/noncopyable.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> #include <boost/asio/detail/push_options.hpp> @@ -106,22 +105,6 @@ public: return next_layer_.lowest_layer().get_executor(); } -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - boost::asio::io_context& get_io_context() - { - return next_layer_.get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - boost::asio::io_context& get_io_service() - { - return next_layer_.get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Close the stream. void close() { diff --git a/boost/asio/buffered_read_stream_fwd.hpp b/boost/asio/buffered_read_stream_fwd.hpp index d6b0ad14be..f250c92f34 100644 --- a/boost/asio/buffered_read_stream_fwd.hpp +++ b/boost/asio/buffered_read_stream_fwd.hpp @@ -2,7 +2,7 @@ // buffered_read_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/buffered_stream.hpp b/boost/asio/buffered_stream.hpp index ada06e1d9c..d28abf10b6 100644 --- a/boost/asio/buffered_stream.hpp +++ b/boost/asio/buffered_stream.hpp @@ -2,7 +2,7 @@ // buffered_stream.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -23,7 +23,6 @@ #include <boost/asio/buffered_stream_fwd.hpp> #include <boost/asio/detail/noncopyable.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> #include <boost/asio/detail/push_options.hpp> @@ -97,22 +96,6 @@ public: return stream_impl_.lowest_layer().get_executor(); } -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - boost::asio::io_context& get_io_context() - { - return stream_impl_.get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - boost::asio::io_context& get_io_service() - { - return stream_impl_.get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Close the stream. void close() { diff --git a/boost/asio/buffered_stream_fwd.hpp b/boost/asio/buffered_stream_fwd.hpp index a477f2be65..ceeac165f5 100644 --- a/boost/asio/buffered_stream_fwd.hpp +++ b/boost/asio/buffered_stream_fwd.hpp @@ -2,7 +2,7 @@ // buffered_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/buffered_write_stream.hpp b/boost/asio/buffered_write_stream.hpp index 3eacd5f150..aab02b5176 100644 --- a/boost/asio/buffered_write_stream.hpp +++ b/boost/asio/buffered_write_stream.hpp @@ -2,7 +2,7 @@ // buffered_write_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -25,7 +25,6 @@ #include <boost/asio/detail/noncopyable.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> #include <boost/asio/write.hpp> #include <boost/asio/detail/push_options.hpp> @@ -106,22 +105,6 @@ public: return next_layer_.lowest_layer().get_executor(); } -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - boost::asio::io_context& get_io_context() - { - return next_layer_.get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - boost::asio::io_context& get_io_service() - { - return next_layer_.get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Close the stream. void close() { diff --git a/boost/asio/buffered_write_stream_fwd.hpp b/boost/asio/buffered_write_stream_fwd.hpp index 68ab9a4d31..eec5bc2804 100644 --- a/boost/asio/buffered_write_stream_fwd.hpp +++ b/boost/asio/buffered_write_stream_fwd.hpp @@ -2,7 +2,7 @@ // buffered_write_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/buffers_iterator.hpp b/boost/asio/buffers_iterator.hpp index 9de385128f..316c144130 100644 --- a/boost/asio/buffers_iterator.hpp +++ b/boost/asio/buffers_iterator.hpp @@ -2,7 +2,7 @@ // buffers_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/co_spawn.hpp b/boost/asio/co_spawn.hpp new file mode 100644 index 0000000000..67d17e21b5 --- /dev/null +++ b/boost/asio/co_spawn.hpp @@ -0,0 +1,90 @@ +// +// co_spawn.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_CO_SPAWN_HPP +#define BOOST_ASIO_CO_SPAWN_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) + +#include <boost/asio/awaitable.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/is_executor.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename T> +struct awaitable_signature; + +template <typename T, typename Executor> +struct awaitable_signature<awaitable<T, Executor>> +{ + typedef void type(std::exception_ptr, T); +}; + +template <typename Executor> +struct awaitable_signature<awaitable<void, Executor>> +{ + typedef void type(std::exception_ptr); +}; + +} // namespace detail + +/// Spawn a new thread of execution. +/** + * The entry point function object @c f must have the signature: + * + * @code awaitable<void, E> f(); @endcode + * + * where @c E is convertible from @c Executor. + */ +template <typename Executor, typename F, typename CompletionToken> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, + typename detail::awaitable_signature<typename result_of<F()>::type>::type) +co_spawn(const Executor& ex, F&& f, CompletionToken&& token, + typename enable_if< + is_executor<Executor>::value + >::type* = 0); + +/// Spawn a new thread of execution. +/** + * The entry point function object @c f must have the signature: + * + * @code awaitable<void, E> f(); @endcode + * + * where @c E is convertible from @c ExecutionContext::executor_type. + */ +template <typename ExecutionContext, typename F, typename CompletionToken> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, + typename detail::awaitable_signature<typename result_of<F()>::type>::type) +co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0); + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/impl/co_spawn.hpp> + +#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_CO_SPAWN_HPP diff --git a/boost/asio/completion_condition.hpp b/boost/asio/completion_condition.hpp index c49517ba4f..4d0337b3fb 100644 --- a/boost/asio/completion_condition.hpp +++ b/boost/asio/completion_condition.hpp @@ -2,7 +2,7 @@ // completion_condition.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/compose.hpp b/boost/asio/compose.hpp new file mode 100644 index 0000000000..b38e4faecb --- /dev/null +++ b/boost/asio/compose.hpp @@ -0,0 +1,138 @@ +// +// compose.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_COMPOSE_HPP +#define BOOST_ASIO_COMPOSE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/async_result.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) \ + || defined(GENERATING_DOCUMENTATION) + +/// Launch an asynchronous operation with a stateful implementation. +/** + * The async_compose function simplifies the implementation of composed + * asynchronous operations automatically wrapping a stateful function object + * with a conforming intermediate completion handler. + * + * @param implementation A function object that contains the implementation of + * the composed asynchronous operation. The first argument to the function + * object is a non-const reference to the enclosing intermediate completion + * handler. The remaining arguments are any arguments that originate from the + * completion handlers of any asynchronous operations performed by the + * implementation. + + * @param token The completion token. + * + * @param io_objects_or_executors Zero or more I/O objects or I/O executors for + * which outstanding work must be maintained. + * + * @par Example: + * + * @code struct async_echo_implementation + * { + * tcp::socket& socket_; + * boost::asio::mutable_buffer buffer_; + * enum { starting, reading, writing } state_; + * + * template <typename Self> + * void operator()(Self& self, + * boost::system::error_code error = {}, + * std::size_t n = 0) + * { + * switch (state_) + * { + * case starting: + * state_ = reading; + * socket_.async_read_some( + * buffer_, std::move(self)); + * break; + * case reading: + * if (error) + * { + * self.complete(error, 0); + * } + * else + * { + * state_ = writing; + * boost::asio::async_write(socket_, buffer_, + * boost::asio::transfer_exactly(n), + * std::move(self)); + * } + * break; + * case writing: + * self.complete(error, n); + * break; + * } + * } + * }; + * + * template <typename CompletionToken> + * auto async_echo(tcp::socket& socket, + * boost::asio::mutable_buffer buffer, + * CompletionToken&& token) -> + * typename boost::asio::async_result< + * typename std::decay<CompletionToken>::type, + * void(boost::system::error_code, std::size_t)>::return_type + * { + * return boost::asio::async_compose<CompletionToken, + * void(boost::system::error_code, std::size_t)>( + * async_echo_implementation{socket, buffer, + * async_echo_implementation::starting}, + * token, socket); + * } @endcode + */ +template <typename CompletionToken, typename Signature, + typename Implementation, typename... IoObjectsOrExecutors> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) +async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors); + +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + // || defined(GENERATING_DOCUMENTATION) + +template <typename CompletionToken, typename Signature, typename Implementation> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) +async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token); + +#define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \ + template <typename CompletionToken, typename Signature, \ + typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) \ + async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \ + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ + BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)); + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF) +#undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + // || defined(GENERATING_DOCUMENTATION) + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/impl/compose.hpp> + +#endif // BOOST_ASIO_COMPOSE_HPP diff --git a/boost/asio/connect.hpp b/boost/asio/connect.hpp index 03296885dd..a500392d3c 100644 --- a/boost/asio/connect.hpp +++ b/boost/asio/connect.hpp @@ -2,7 +2,7 @@ // connect.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -83,14 +83,13 @@ struct is_endpoint_sequence * Otherwise, contains the error from the last connection attempt. * * @par Example - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * boost::asio::connect(s, r.resolve(q)); @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence> -typename Protocol::endpoint connect( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename EndpointSequence> +typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, typename enable_if<is_endpoint_sequence< EndpointSequence>::value>::type* = 0); @@ -115,9 +114,9 @@ typename Protocol::endpoint connect( * default-constructed endpoint. * * @par Example - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * boost::system::error_code ec; * boost::asio::connect(s, r.resolve(q), ec); * if (ec) @@ -125,9 +124,8 @@ typename Protocol::endpoint connect( * // An error occurred. * } @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence> -typename Protocol::endpoint connect( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename EndpointSequence> +typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, boost::system::error_code& ec, typename enable_if<is_endpoint_sequence< EndpointSequence>::value>::type* = 0); @@ -157,8 +155,8 @@ typename Protocol::endpoint connect( * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, +template <typename Protocol, typename Executor, typename Iterator> +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); /// (Deprecated: Use range overload.) Establishes a socket connection by trying @@ -185,8 +183,8 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename Iterator> +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, boost::system::error_code& ec, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -212,14 +210,14 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * Otherwise, contains the error from the last connection attempt. * * @par Example - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); * tcp::resolver::results_type e = r.resolve(q); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * boost::asio::connect(s, e.begin(), e.end()); @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename Iterator> +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end); /// Establishes a socket connection by trying each endpoint in a sequence. @@ -244,10 +242,10 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * endpoint. Otherwise, the end iterator. * * @par Example - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); * tcp::resolver::results_type e = r.resolve(q); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * boost::system::error_code ec; * boost::asio::connect(s, e.begin(), e.end(), ec); * if (ec) @@ -255,8 +253,8 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * // An error occurred. * } @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename Iterator> +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, boost::system::error_code& ec); /// Establishes a socket connection by trying each endpoint in a sequence. @@ -303,17 +301,16 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * } * }; @endcode * It would be used with the boost::asio::connect function as follows: - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * tcp::endpoint e = boost::asio::connect(s, * r.resolve(q), my_connect_condition()); * std::cout << "Connected to: " << e << std::endl; @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition> -typename Protocol::endpoint connect( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, typename enable_if<is_endpoint_sequence< EndpointSequence>::value>::type* = 0); @@ -363,9 +360,9 @@ typename Protocol::endpoint connect( * } * }; @endcode * It would be used with the boost::asio::connect function as follows: - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * boost::system::error_code ec; * tcp::endpoint e = boost::asio::connect(s, * r.resolve(q), my_connect_condition(), ec); @@ -378,10 +375,9 @@ typename Protocol::endpoint connect( * std::cout << "Connected to: " << e << std::endl; * } @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition> -typename Protocol::endpoint connect( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, boost::system::error_code& ec, typename enable_if<is_endpoint_sequence< @@ -423,9 +419,9 @@ typename Protocol::endpoint connect( * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); @@ -464,9 +460,9 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, boost::system::error_code& ec, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -517,17 +513,17 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, * } * }; @endcode * It would be used with the boost::asio::connect function as follows: - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); * tcp::resolver::results_type e = r.resolve(q); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * tcp::resolver::results_type::iterator i = boost::asio::connect( * s, e.begin(), e.end(), my_connect_condition()); * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, ConnectCondition connect_condition); /// Establishes a socket connection by trying each endpoint in a sequence. @@ -577,10 +573,10 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, * } * }; @endcode * It would be used with the boost::asio::connect function as follows: - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); * tcp::resolver::results_type e = r.resolve(q); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * boost::system::error_code ec; * tcp::resolver::results_type::iterator i = boost::asio::connect( * s, e.begin(), e.end(), my_connect_condition()); @@ -593,9 +589,9 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, * std::cout << "Connected to: " << i->endpoint() << std::endl; * } @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, ConnectCondition connect_condition, boost::system::error_code& ec); @@ -636,14 +632,14 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * const typename Protocol::endpoint& endpoint * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * * // ... * @@ -670,11 +666,11 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * // ... * } @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename EndpointSequence, typename RangeConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler, void (boost::system::error_code, typename Protocol::endpoint)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler, typename enable_if<is_endpoint_sequence< @@ -708,20 +704,20 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename IteratorConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (boost::system::error_code, Iterator)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, +async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, + BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -754,13 +750,13 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code std::vector<tcp::endpoint> endpoints = ...; - * tcp::socket s(io_context); + * tcp::socket s(my_context); * boost::asio::async_connect(s, * endpoints.begin(), endpoints.end(), * connect_handler); @@ -774,12 +770,11 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * // ... * } @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename IteratorConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (boost::system::error_code, Iterator)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, Iterator end, +async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler); /// Asynchronously establishes a socket connection by trying each endpoint in a @@ -820,9 +815,9 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * The following connect condition function object can be used to output @@ -839,9 +834,9 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * } * }; @endcode * It would be used with the boost::asio::connect function as follows: - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * * // ... * @@ -877,11 +872,11 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * } * } @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence, +template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition, typename RangeConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler, void (boost::system::error_code, typename Protocol::endpoint)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler, typename enable_if<is_endpoint_sequence< @@ -926,19 +921,19 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (boost::system::error_code, Iterator)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, +async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0); @@ -984,9 +979,9 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * The following connect condition function object can be used to output @@ -1003,9 +998,9 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, * } * }; @endcode * It would be used with the boost::asio::connect function as follows: - * @code tcp::resolver r(io_context); + * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); - * tcp::socket s(io_context); + * tcp::socket s(my_context); * * // ... * @@ -1042,12 +1037,12 @@ async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, * } * } @endcode */ -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (boost::system::error_code, Iterator)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, Iterator end, ConnectCondition connect_condition, +async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, + Iterator end, ConnectCondition connect_condition, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler); /*@}*/ diff --git a/boost/asio/coroutine.hpp b/boost/asio/coroutine.hpp index b195b12ed8..c519295310 100644 --- a/boost/asio/coroutine.hpp +++ b/boost/asio/coroutine.hpp @@ -2,7 +2,7 @@ // coroutine.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -206,7 +206,7 @@ class coroutine_ref; * { * do * { - * socket_.reset(new tcp::socket(io_context_)); + * socket_.reset(new tcp::socket(my_context_)); * yield acceptor->async_accept(*socket_, *this); * fork server(*this)(); * } while (is_parent()); @@ -228,7 +228,7 @@ class coroutine_ref; * Note that @c fork doesn't do the actual forking by itself. It is the * application's responsibility to create a clone of the coroutine and call it. * The clone can be called immediately, as above, or scheduled for delayed - * execution using something like io_context::post(). + * execution using something like boost::asio::post(). * * @par Alternate macro names * diff --git a/boost/asio/datagram_socket_service.hpp b/boost/asio/datagram_socket_service.hpp deleted file mode 100644 index 816433ba78..0000000000 --- a/boost/asio/datagram_socket_service.hpp +++ /dev/null @@ -1,468 +0,0 @@ -// -// datagram_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP -#define BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/type_traits.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/null_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_socket_service.hpp> -#else -# include <boost/asio/detail/reactive_socket_service.hpp> -#endif - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a datagram socket. -template <typename Protocol> -class datagram_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<datagram_socket_service<Protocol> > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) - typedef detail::null_socket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#else - typedef detail::reactive_socket_service<Protocol> service_impl_type; -#endif - -public: - /// The type of a datagram socket. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef typename service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new datagram socket service for the specified io_context. - explicit datagram_socket_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - datagram_socket_service<Protocol> >(io_context), - service_impl_(io_context) - { - } - - /// Construct a new datagram socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new datagram socket implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another datagram socket implementation. - void move_assign(implementation_type& impl, - datagram_socket_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } - - // All socket services have access to each other's implementations. - template <typename Protocol1> friend class datagram_socket_service; - - /// Move-construct a new datagram socket implementation from another protocol - /// type. - template <typename Protocol1> - void converting_move_construct(implementation_type& impl, - datagram_socket_service<Protocol1>& other_service, - typename datagram_socket_service< - Protocol1>::implementation_type& other_impl, - typename enable_if<is_convertible< - Protocol1, Protocol>::value>::type* = 0) - { - service_impl_.template converting_move_construct<Protocol1>( - impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a datagram socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - // Open a new datagram socket implementation. - BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl, - const protocol_type& protocol, boost::system::error_code& ec) - { - if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_DGRAM)) - service_impl_.open(impl, protocol, ec); - else - ec = boost::asio::error::invalid_argument; - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Assign an existing native socket to a datagram socket. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const protocol_type& protocol, const native_handle_type& native_socket, - boost::system::error_code& ec) - { - service_impl_.assign(impl, protocol, native_socket, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a datagram socket implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Release ownership of the underlying socket. - native_handle_type release(implementation_type& impl, - boost::system::error_code& ec) - { - return service_impl_.release(impl, ec); - } - - /// Get the native socket implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - // Bind the datagram socket to the specified local endpoint. - BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl, - const endpoint_type& endpoint, boost::system::error_code& ec) - { - service_impl_.bind(impl, endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Connect the datagram socket to the specified endpoint. - BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl, - const endpoint_type& peer_endpoint, boost::system::error_code& ec) - { - service_impl_.connect(impl, peer_endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Start an asynchronous connect. - template <typename ConnectHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, - void (boost::system::error_code)) - async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, - BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) - { - async_completion<ConnectHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_connect(impl, peer_endpoint, init.completion_handler); - - return init.result.get(); - } - - /// Set a socket option. - template <typename SettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl, - const SettableSocketOption& option, boost::system::error_code& ec) - { - service_impl_.set_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get a socket option. - template <typename GettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl, - GettableSocketOption& option, boost::system::error_code& ec) const - { - service_impl_.get_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Perform an IO control command on the socket. - template <typename IoControlCommand> - BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl, - IoControlCommand& command, boost::system::error_code& ec) - { - service_impl_.io_control(impl, command, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the socket. - bool non_blocking(const implementation_type& impl) const - { - return service_impl_.non_blocking(impl); - } - - /// Sets the non-blocking mode of the socket. - BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the native socket implementation. - bool native_non_blocking(const implementation_type& impl) const - { - return service_impl_.native_non_blocking(impl); - } - - /// Sets the non-blocking mode of the native socket implementation. - BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.native_non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl, - socket_base::shutdown_type what, boost::system::error_code& ec) - { - service_impl_.shutdown(impl, what, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Wait for the socket to become ready to read, ready to write, or to have - /// pending error conditions. - BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl, - socket_base::wait_type w, boost::system::error_code& ec) - { - service_impl_.wait(impl, w, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Asynchronously wait for the socket to become ready to read, ready to - /// write, or to have pending error conditions. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, socket_base::wait_type w, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, w, init.completion_handler); - - return init.result.get(); - } - - /// Send the given data to the peer. - template <typename ConstBufferSequence> - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_send(impl, buffers, flags, init.completion_handler); - - return init.result.get(); - } - - /// Send a datagram to the specified endpoint. - template <typename ConstBufferSequence> - std::size_t send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.send_to(impl, buffers, destination, flags, ec); - } - - /// Start an asynchronous send. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_send_to(impl, buffers, - destination, flags, init.completion_handler); - - return init.result.get(); - } - - /// Receive some data from the peer. - template <typename MutableBufferSequence> - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Start an asynchronous receive. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_receive(impl, buffers, flags, init.completion_handler); - - return init.result.get(); - } - - /// Receive a datagram with the endpoint of the sender. - template <typename MutableBufferSequence> - std::size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, - ec); - } - - /// Start an asynchronous receive that will get the endpoint of the sender. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_receive_from(impl, buffers, - sender_endpoint, flags, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP diff --git a/boost/asio/deadline_timer.hpp b/boost/asio/deadline_timer.hpp index 3a020e8b9a..1c061fc954 100644 --- a/boost/asio/deadline_timer.hpp +++ b/boost/asio/deadline_timer.hpp @@ -2,7 +2,7 @@ // deadline_timer.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/deadline_timer_service.hpp b/boost/asio/deadline_timer_service.hpp deleted file mode 100644 index 036378f93b..0000000000 --- a/boost/asio/deadline_timer_service.hpp +++ /dev/null @@ -1,175 +0,0 @@ -// -// deadline_timer_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP -#define BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ - || defined(GENERATING_DOCUMENTATION) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/deadline_timer_service.hpp> -#include <boost/asio/io_context.hpp> -#include <boost/asio/time_traits.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a timer. -template <typename TimeType, - typename TimeTraits = boost::asio::time_traits<TimeType> > -class deadline_timer_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base< - deadline_timer_service<TimeType, TimeTraits> > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - - /// The time traits type. - typedef TimeTraits traits_type; - - /// The time type. - typedef typename traits_type::time_type time_type; - - /// The duration type. - typedef typename traits_type::duration_type duration_type; - -private: - // The type of the platform-specific implementation. - typedef detail::deadline_timer_service<traits_type> service_impl_type; - -public: - /// The implementation type of the deadline timer. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new timer service for the specified io_context. - explicit deadline_timer_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - deadline_timer_service<TimeType, TimeTraits> >(io_context), - service_impl_(io_context) - { - } - - /// Construct a new timer implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a timer implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Cancel any asynchronous wait operations associated with the timer. - std::size_t cancel(implementation_type& impl, boost::system::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Cancels one asynchronous wait operation associated with the timer. - std::size_t cancel_one(implementation_type& impl, - boost::system::error_code& ec) - { - return service_impl_.cancel_one(impl, ec); - } - - /// Get the expiry time for the timer as an absolute time. - time_type expires_at(const implementation_type& impl) const - { - return service_impl_.expiry(impl); - } - - /// Set the expiry time for the timer as an absolute time. - std::size_t expires_at(implementation_type& impl, - const time_type& expiry_time, boost::system::error_code& ec) - { - return service_impl_.expires_at(impl, expiry_time, ec); - } - - /// Get the expiry time for the timer relative to now. - duration_type expires_from_now(const implementation_type& impl) const - { - return TimeTraits::subtract(service_impl_.expiry(impl), TimeTraits::now()); - } - - /// Set the expiry time for the timer relative to now. - std::size_t expires_from_now(implementation_type& impl, - const duration_type& expiry_time, boost::system::error_code& ec) - { - return service_impl_.expires_after(impl, expiry_time, ec); - } - - // Perform a blocking wait on the timer. - void wait(implementation_type& impl, boost::system::error_code& ec) - { - service_impl_.wait(impl, ec); - } - - // Start an asynchronous wait on the timer. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) - // || defined(GENERATING_DOCUMENTATION) - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP diff --git a/boost/asio/defer.hpp b/boost/asio/defer.hpp index 2eaf2d01c6..319063a718 100644 --- a/boost/asio/defer.hpp +++ b/boost/asio/defer.hpp @@ -2,7 +2,7 @@ // defer.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -32,6 +32,11 @@ namespace asio { * executor. The function object is queued for execution, and is never called * from the current thread prior to returning from <tt>defer()</tt>. * + * The use of @c defer(), rather than @ref post(), indicates the caller's + * preference that the executor defer the queueing of the function object. This + * may allow the executor to optimise queueing for cases when the function + * object represents a continuation of the current call context. + * * This function has the following effects: * * @li Constructs a function object handler of type @c Handler, initialized @@ -60,6 +65,11 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer( * The function object is queued for execution, and is never called from the * current thread prior to returning from <tt>defer()</tt>. * + * The use of @c defer(), rather than @ref post(), indicates the caller's + * preference that the executor defer the queueing of the function object. This + * may allow the executor to optimise queueing for cases when the function + * object represents a continuation of the current call context. + * * This function has the following effects: * * @li Constructs a function object handler of type @c Handler, initialized diff --git a/boost/asio/experimental/detached.hpp b/boost/asio/detached.hpp index c3e7adafac..54b6bd2063 100644 --- a/boost/asio/experimental/detached.hpp +++ b/boost/asio/detached.hpp @@ -1,15 +1,15 @@ // -// experimental/detached.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// detached.hpp +// ~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef BOOST_ASIO_EXPERIMENTAL_DETACHED_HPP -#define BOOST_ASIO_EXPERIMENTAL_DETACHED_HPP +#ifndef BOOST_ASIO_DETACHED_HPP +#define BOOST_ASIO_DETACHED_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -22,7 +22,6 @@ namespace boost { namespace asio { -namespace experimental { /// Class used to specify that an asynchronous operation is detached. /** @@ -31,9 +30,9 @@ namespace experimental { * detached. That is, there is no completion handler waiting for the * operation's result. A detached_t object may be passed as a handler to an * asynchronous operation, typically using the special value - * @c boost::asio::experimental::detached. For example: + * @c boost::asio::detached. For example: - * @code my_socket.async_send(my_buffer, boost::asio::experimental::detached); + * @code my_socket.async_send(my_buffer, boost::asio::detached); * @endcode */ class detached_t @@ -47,8 +46,7 @@ public: /// A special value, similar to std::nothrow. /** - * See the documentation for boost::asio::experimental::detached_t for a usage - * example. + * See the documentation for boost::asio::detached_t for a usage example. */ #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr detached_t detached; @@ -56,12 +54,11 @@ constexpr detached_t detached; __declspec(selectany) detached_t detached; #endif -} // namespace experimental } // namespace asio } // namespace boost #include <boost/asio/detail/pop_options.hpp> -#include <boost/asio/experimental/impl/detached.hpp> +#include <boost/asio/impl/detached.hpp> -#endif // BOOST_ASIO_EXPERIMENTAL_DETACHED_HPP +#endif // BOOST_ASIO_DETACHED_HPP diff --git a/boost/asio/detail/array.hpp b/boost/asio/detail/array.hpp index 238118e3a6..6779e484b9 100644 --- a/boost/asio/detail/array.hpp +++ b/boost/asio/detail/array.hpp @@ -2,7 +2,7 @@ // detail/array.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/array_fwd.hpp b/boost/asio/detail/array_fwd.hpp index 82f357785d..25a0c61496 100644 --- a/boost/asio/detail/array_fwd.hpp +++ b/boost/asio/detail/array_fwd.hpp @@ -2,7 +2,7 @@ // detail/array_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/assert.hpp b/boost/asio/detail/assert.hpp index fe306ce614..927dfce76f 100644 --- a/boost/asio/detail/assert.hpp +++ b/boost/asio/detail/assert.hpp @@ -2,7 +2,7 @@ // detail/assert.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/atomic_count.hpp b/boost/asio/detail/atomic_count.hpp index 78cd0fb333..ba945a9e0f 100644 --- a/boost/asio/detail/atomic_count.hpp +++ b/boost/asio/detail/atomic_count.hpp @@ -2,7 +2,7 @@ // detail/atomic_count.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/base_from_completion_cond.hpp b/boost/asio/detail/base_from_completion_cond.hpp index 88f167f3f4..7904eadc91 100644 --- a/boost/asio/detail/base_from_completion_cond.hpp +++ b/boost/asio/detail/base_from_completion_cond.hpp @@ -2,7 +2,7 @@ // detail/base_from_completion_cond.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,8 +28,9 @@ template <typename CompletionCondition> class base_from_completion_cond { protected: - explicit base_from_completion_cond(CompletionCondition completion_condition) - : completion_condition_(completion_condition) + explicit base_from_completion_cond(CompletionCondition& completion_condition) + : completion_condition_( + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)) { } diff --git a/boost/asio/detail/bind_handler.hpp b/boost/asio/detail/bind_handler.hpp index 39f1b29bcd..ddeb58fadc 100644 --- a/boost/asio/detail/bind_handler.hpp +++ b/boost/asio/detail/bind_handler.hpp @@ -2,7 +2,7 @@ // detail/bind_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/buffer_resize_guard.hpp b/boost/asio/detail/buffer_resize_guard.hpp index ad07f72c04..198e9c7dc0 100644 --- a/boost/asio/detail/buffer_resize_guard.hpp +++ b/boost/asio/detail/buffer_resize_guard.hpp @@ -2,7 +2,7 @@ // detail/buffer_resize_guard.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/buffer_sequence_adapter.hpp b/boost/asio/detail/buffer_sequence_adapter.hpp index 5ba55d266d..f33d3426ac 100644 --- a/boost/asio/detail/buffer_sequence_adapter.hpp +++ b/boost/asio/detail/buffer_sequence_adapter.hpp @@ -2,7 +2,7 @@ // detail/buffer_sequence_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/buffered_stream_storage.hpp b/boost/asio/detail/buffered_stream_storage.hpp index 3b9ca404c4..2e060ce5f2 100644 --- a/boost/asio/detail/buffered_stream_storage.hpp +++ b/boost/asio/detail/buffered_stream_storage.hpp @@ -2,7 +2,7 @@ // detail/buffered_stream_storage.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/call_stack.hpp b/boost/asio/detail/call_stack.hpp index 34f4de607f..eb63e54729 100644 --- a/boost/asio/detail/call_stack.hpp +++ b/boost/asio/detail/call_stack.hpp @@ -2,7 +2,7 @@ // detail/call_stack.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/chrono.hpp b/boost/asio/detail/chrono.hpp index 044f12c6c3..d5a55ff4e1 100644 --- a/boost/asio/detail/chrono.hpp +++ b/boost/asio/detail/chrono.hpp @@ -2,7 +2,7 @@ // detail/chrono.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/chrono_time_traits.hpp b/boost/asio/detail/chrono_time_traits.hpp index 256389acaf..85e3b8b429 100644 --- a/boost/asio/detail/chrono_time_traits.hpp +++ b/boost/asio/detail/chrono_time_traits.hpp @@ -2,7 +2,7 @@ // detail/chrono_time_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/completion_handler.hpp b/boost/asio/detail/completion_handler.hpp index e856a86f5a..3cd136974e 100644 --- a/boost/asio/detail/completion_handler.hpp +++ b/boost/asio/detail/completion_handler.hpp @@ -2,7 +2,7 @@ // detail/completion_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/concurrency_hint.hpp b/boost/asio/detail/concurrency_hint.hpp index c11b7f6109..99deb78644 100644 --- a/boost/asio/detail/concurrency_hint.hpp +++ b/boost/asio/detail/concurrency_hint.hpp @@ -2,7 +2,7 @@ // detail/concurrency_hint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/conditionally_enabled_event.hpp b/boost/asio/detail/conditionally_enabled_event.hpp index 9319c87538..2d5a45c02e 100644 --- a/boost/asio/detail/conditionally_enabled_event.hpp +++ b/boost/asio/detail/conditionally_enabled_event.hpp @@ -2,7 +2,7 @@ // detail/conditionally_enabled_event.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/conditionally_enabled_mutex.hpp b/boost/asio/detail/conditionally_enabled_mutex.hpp index ab4ef48afc..5d105e9814 100644 --- a/boost/asio/detail/conditionally_enabled_mutex.hpp +++ b/boost/asio/detail/conditionally_enabled_mutex.hpp @@ -2,7 +2,7 @@ // detail/conditionally_enabled_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/config.hpp b/boost/asio/detail/config.hpp index 2453425315..8fef292b00 100644 --- a/boost/asio/detail/config.hpp +++ b/boost/asio/detail/config.hpp @@ -2,7 +2,7 @@ // detail/config.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -120,11 +120,14 @@ #endif // !defined(BOOST_ASIO_HAS_MOVE) // If BOOST_ASIO_MOVE_CAST isn't defined, and move support is available, define -// BOOST_ASIO_MOVE_ARG and BOOST_ASIO_MOVE_CAST to take advantage of rvalue -// references and perfect forwarding. +// * BOOST_ASIO_MOVE_ARG, +// * BOOST_ASIO_NONDEDUCED_MOVE_ARG, and +// * BOOST_ASIO_MOVE_CAST +// to take advantage of rvalue references and perfect forwarding. #if defined(BOOST_ASIO_HAS_MOVE) && !defined(BOOST_ASIO_MOVE_CAST) # define BOOST_ASIO_MOVE_ARG(type) type&& # define BOOST_ASIO_MOVE_ARG2(type1, type2) type1, type2&& +# define BOOST_ASIO_NONDEDUCED_MOVE_ARG(type) type& # define BOOST_ASIO_MOVE_CAST(type) static_cast<type&&> # define BOOST_ASIO_MOVE_CAST2(type1, type2) static_cast<type1, type2&&> #endif // defined(BOOST_ASIO_HAS_MOVE) && !defined(BOOST_ASIO_MOVE_CAST) @@ -150,6 +153,7 @@ # else # define BOOST_ASIO_MOVE_ARG(type) type # endif +# define BOOST_ASIO_NONDEDUCED_MOVE_ARG(type) const type& # define BOOST_ASIO_MOVE_CAST(type) static_cast<const type&> # define BOOST_ASIO_MOVE_CAST2(type1, type2) static_cast<const type1, type2&> #endif // !defined(BOOST_ASIO_MOVE_CAST) @@ -280,9 +284,9 @@ # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) # endif // defined(__GNUC__) # if defined(BOOST_ASIO_MSVC) -# if (_MSC_VER >= 1700) +# if (_MSC_VER >= 1800) # define BOOST_ASIO_HAS_DECLTYPE 1 -# endif // (_MSC_VER >= 1700) +# endif // (_MSC_VER >= 1800) # endif // defined(BOOST_ASIO_MSVC) # endif // !defined(BOOST_ASIO_DISABLE_DECLTYPE) #endif // !defined(BOOST_ASIO_HAS_DECLTYPE) @@ -446,7 +450,13 @@ # if __has_include(<atomic>) # define BOOST_ASIO_HAS_STD_ATOMIC 1 # endif // __has_include(<atomic>) -# endif // (__cplusplus >= 201103) +# elif defined(__apple_build_version__) && defined(_LIBCPP_VERSION) +# if (__clang_major__ >= 10) +# if __has_include(<atomic>) +# define BOOST_ASIO_HAS_STD_ATOMIC 1 +# endif // __has_include(<atomic>) +# endif // (__clang_major__ >= 10) +# endif /// defined(__apple_build_version__) && defined(_LIBCPP_VERSION) # endif // defined(__clang__) # if defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) @@ -922,15 +932,15 @@ # if defined(_MSC_VER) || defined(__BORLANDC__) # pragma message( \ "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\ - "- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\ - "- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\ - "Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).") + "- add -D_WIN32_WINNT=0x0601 to the compiler command line; or\n"\ + "- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.\n"\ + "Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).") # else // defined(_MSC_VER) || defined(__BORLANDC__) # warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. -# warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line. -# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target). +# warning For example, add -D_WIN32_WINNT=0x0601 to the compiler command line. +# warning Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target). # endif // defined(_MSC_VER) || defined(__BORLANDC__) -# define _WIN32_WINNT 0x0501 +# define _WIN32_WINNT 0x0601 # endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) # if defined(_MSC_VER) # if defined(_WIN32) && !defined(WIN32) @@ -1001,7 +1011,8 @@ || defined(__FreeBSD__) \ || defined(__NetBSD__) \ || defined(__OpenBSD__) \ - || defined(__linux__) + || defined(__linux__) \ + || defined(__HAIKU__) # define BOOST_ASIO_HAS_UNISTD_H 1 # endif # endif // !defined(BOOST_ASIO_HAS_BOOST_CONFIG) @@ -1365,33 +1376,6 @@ // || (defined(__MACH__) && defined(__APPLE__)) #endif // !defined(BOOST_ASIO_DISABLE_SSIZE_T) -// Helper macros to manage the transition away from the old services-based API. -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# define BOOST_ASIO_SVC_TPARAM , typename Service -# define BOOST_ASIO_SVC_TPARAM_DEF1(d1) , typename Service d1 -# define BOOST_ASIO_SVC_TPARAM_DEF2(d1, d2) , typename Service d1, d2 -# define BOOST_ASIO_SVC_TARG , Service -# define BOOST_ASIO_SVC_T Service -# define BOOST_ASIO_SVC_TPARAM1 , typename Service1 -# define BOOST_ASIO_SVC_TPARAM1_DEF1(d1) , typename Service1 d1 -# define BOOST_ASIO_SVC_TPARAM1_DEF2(d1, d2) , typename Service1 d1, d2 -# define BOOST_ASIO_SVC_TARG1 , Service1 -# define BOOST_ASIO_SVC_T1 Service1 -# define BOOST_ASIO_SVC_ACCESS public -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# define BOOST_ASIO_SVC_TPARAM -# define BOOST_ASIO_SVC_TPARAM_DEF1(d1) -# define BOOST_ASIO_SVC_TPARAM_DEF2(d1, d2) -# define BOOST_ASIO_SVC_TARG -// BOOST_ASIO_SVC_T is defined at each point of use. -# define BOOST_ASIO_SVC_TPARAM1 -# define BOOST_ASIO_SVC_TPARAM1_DEF1(d1) -# define BOOST_ASIO_SVC_TPARAM1_DEF2(d1, d2) -# define BOOST_ASIO_SVC_TARG1 -// BOOST_ASIO_SVC_T1 is defined at each point of use. -# define BOOST_ASIO_SVC_ACCESS protected -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - // Helper macros to manage transition away from error_code return values. #if defined(BOOST_ASIO_NO_DEPRECATED) # define BOOST_ASIO_SYNC_OP_VOID void diff --git a/boost/asio/detail/consuming_buffers.hpp b/boost/asio/detail/consuming_buffers.hpp index 38eb00576c..f8226a4e8d 100644 --- a/boost/asio/detail/consuming_buffers.hpp +++ b/boost/asio/detail/consuming_buffers.hpp @@ -2,7 +2,7 @@ // detail/consuming_buffers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/cstddef.hpp b/boost/asio/detail/cstddef.hpp index 665ff3b3a3..b77d9aab7f 100644 --- a/boost/asio/detail/cstddef.hpp +++ b/boost/asio/detail/cstddef.hpp @@ -2,7 +2,7 @@ // detail/cstddef.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/cstdint.hpp b/boost/asio/detail/cstdint.hpp index 24e203aa6d..b916f78a74 100644 --- a/boost/asio/detail/cstdint.hpp +++ b/boost/asio/detail/cstdint.hpp @@ -2,7 +2,7 @@ // detail/cstdint.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/date_time_fwd.hpp b/boost/asio/detail/date_time_fwd.hpp index b6c49c75d1..c917be4ffb 100644 --- a/boost/asio/detail/date_time_fwd.hpp +++ b/boost/asio/detail/date_time_fwd.hpp @@ -2,7 +2,7 @@ // detail/date_time_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/deadline_timer_service.hpp b/boost/asio/detail/deadline_timer_service.hpp index ff162493d8..8732990a0f 100644 --- a/boost/asio/detail/deadline_timer_service.hpp +++ b/boost/asio/detail/deadline_timer_service.hpp @@ -2,7 +2,7 @@ // detail/deadline_timer_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -18,7 +18,7 @@ #include <boost/asio/detail/config.hpp> #include <cstddef> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/detail/bind_handler.hpp> #include <boost/asio/detail/fenced_block.hpp> #include <boost/asio/detail/memory.hpp> @@ -44,7 +44,7 @@ namespace detail { template <typename Time_Traits> class deadline_timer_service - : public service_base<deadline_timer_service<Time_Traits> > + : public execution_context_service_base<deadline_timer_service<Time_Traits> > { public: // The time type. @@ -64,9 +64,10 @@ public: }; // Constructor. - deadline_timer_service(boost::asio::io_context& io_context) - : service_base<deadline_timer_service<Time_Traits> >(io_context), - scheduler_(boost::asio::use_service<timer_scheduler>(io_context)) + deadline_timer_service(execution_context& context) + : execution_context_service_base< + deadline_timer_service<Time_Traits> >(context), + scheduler_(boost::asio::use_service<timer_scheduler>(context)) { scheduler_.init_task(); scheduler_.add_timer_queue(timer_queue_); @@ -226,14 +227,15 @@ public: } // Start an asynchronous wait on the timer. - template <typename Handler> - void async_wait(implementation_type& impl, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_wait(implementation_type& impl, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef wait_handler<Handler> op; + typedef wait_handler<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); impl.might_have_pending_waits = true; diff --git a/boost/asio/detail/dependent_type.hpp b/boost/asio/detail/dependent_type.hpp index 43f87dae7f..53aef3fb5f 100644 --- a/boost/asio/detail/dependent_type.hpp +++ b/boost/asio/detail/dependent_type.hpp @@ -2,7 +2,7 @@ // detail/dependent_type.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/descriptor_ops.hpp b/boost/asio/detail/descriptor_ops.hpp index bfa6ce99fa..bfb0824ffb 100644 --- a/boost/asio/detail/descriptor_ops.hpp +++ b/boost/asio/detail/descriptor_ops.hpp @@ -2,7 +2,7 @@ // detail/descriptor_ops.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/descriptor_read_op.hpp b/boost/asio/detail/descriptor_read_op.hpp index 328e2191c0..3ced62bb26 100644 --- a/boost/asio/detail/descriptor_read_op.hpp +++ b/boost/asio/detail/descriptor_read_op.hpp @@ -2,7 +2,7 @@ // detail/descriptor_read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -67,20 +67,21 @@ private: MutableBufferSequence buffers_; }; -template <typename MutableBufferSequence, typename Handler> +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> class descriptor_read_op : public descriptor_read_op_base<MutableBufferSequence> { public: BOOST_ASIO_DEFINE_HANDLER_PTR(descriptor_read_op); - descriptor_read_op(int descriptor, - const MutableBufferSequence& buffers, Handler& handler) + descriptor_read_op(int descriptor, const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) : descriptor_read_op_base<MutableBufferSequence>( descriptor, buffers, &descriptor_read_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -90,7 +91,7 @@ public: // Take ownership of the handler object. descriptor_read_op* o(static_cast<descriptor_read_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -117,6 +118,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/descriptor_write_op.hpp b/boost/asio/detail/descriptor_write_op.hpp index 80ddf37d37..d1eea52789 100644 --- a/boost/asio/detail/descriptor_write_op.hpp +++ b/boost/asio/detail/descriptor_write_op.hpp @@ -2,7 +2,7 @@ // detail/descriptor_write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -67,20 +67,21 @@ private: ConstBufferSequence buffers_; }; -template <typename ConstBufferSequence, typename Handler> +template <typename ConstBufferSequence, typename Handler, typename IoExecutor> class descriptor_write_op : public descriptor_write_op_base<ConstBufferSequence> { public: BOOST_ASIO_DEFINE_HANDLER_PTR(descriptor_write_op); - descriptor_write_op(int descriptor, - const ConstBufferSequence& buffers, Handler& handler) + descriptor_write_op(int descriptor, const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) : descriptor_write_op_base<ConstBufferSequence>( descriptor, buffers, &descriptor_write_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -90,7 +91,7 @@ public: // Take ownership of the handler object. descriptor_write_op* o(static_cast<descriptor_write_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -117,6 +118,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/dev_poll_reactor.hpp b/boost/asio/detail/dev_poll_reactor.hpp index cb15a9671b..63a0c3058f 100644 --- a/boost/asio/detail/dev_poll_reactor.hpp +++ b/boost/asio/detail/dev_poll_reactor.hpp @@ -2,7 +2,7 @@ // detail/dev_poll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/epoll_reactor.hpp b/boost/asio/detail/epoll_reactor.hpp index 31a7b3dff3..c361978853 100644 --- a/boost/asio/detail/epoll_reactor.hpp +++ b/boost/asio/detail/epoll_reactor.hpp @@ -2,7 +2,7 @@ // detail/epoll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/event.hpp b/boost/asio/detail/event.hpp index 8cb097cb24..b55a204059 100644 --- a/boost/asio/detail/event.hpp +++ b/boost/asio/detail/event.hpp @@ -2,7 +2,7 @@ // detail/event.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/eventfd_select_interrupter.hpp b/boost/asio/detail/eventfd_select_interrupter.hpp index 4871c971ed..0bcbcb96db 100644 --- a/boost/asio/detail/eventfd_select_interrupter.hpp +++ b/boost/asio/detail/eventfd_select_interrupter.hpp @@ -2,7 +2,7 @@ // detail/eventfd_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/detail/executor_function.hpp b/boost/asio/detail/executor_function.hpp new file mode 100644 index 0000000000..2b8fb40a12 --- /dev/null +++ b/boost/asio/detail/executor_function.hpp @@ -0,0 +1,106 @@ +// +// detail/executor_function.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP +#define BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/handler_alloc_helpers.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class executor_function_base +{ +public: + void complete() + { + func_(this, true); + } + + void destroy() + { + func_(this, false); + } + +protected: + typedef void (*func_type)(executor_function_base*, bool); + + executor_function_base(func_type func) + : func_(func) + { + } + + // Prevents deletion through this type. + ~executor_function_base() + { + } + +private: + func_type func_; +}; + +template <typename Function, typename Alloc> +class executor_function : public executor_function_base +{ +public: + BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR( + thread_info_base::executor_function_tag, executor_function); + + template <typename F> + executor_function(BOOST_ASIO_MOVE_ARG(F) f, const Alloc& allocator) + : executor_function_base(&executor_function::do_complete), + function_(BOOST_ASIO_MOVE_CAST(F)(f)), + allocator_(allocator) + { + } + + static void do_complete(executor_function_base* base, bool call) + { + // Take ownership of the function object. + executor_function* o(static_cast<executor_function*>(base)); + Alloc allocator(o->allocator_); + ptr p = { detail::addressof(allocator), o, o }; + + // Make a copy of the function so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the function may be the true owner of the memory + // associated with the function. Consequently, a local copy of the function + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Function function(BOOST_ASIO_MOVE_CAST(Function)(o->function_)); + p.reset(); + + // Make the upcall if required. + if (call) + { + function(); + } + } + +private: + Function function_; + Alloc allocator_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP diff --git a/boost/asio/detail/executor_op.hpp b/boost/asio/detail/executor_op.hpp index 1c8671abc8..b2581201f3 100644 --- a/boost/asio/detail/executor_op.hpp +++ b/boost/asio/detail/executor_op.hpp @@ -2,7 +2,7 @@ // detail/executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/fd_set_adapter.hpp b/boost/asio/detail/fd_set_adapter.hpp index 26ba12665e..d502910a6f 100644 --- a/boost/asio/detail/fd_set_adapter.hpp +++ b/boost/asio/detail/fd_set_adapter.hpp @@ -2,7 +2,7 @@ // detail/fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/fenced_block.hpp b/boost/asio/detail/fenced_block.hpp index e80ed4073c..479db6daa7 100644 --- a/boost/asio/detail/fenced_block.hpp +++ b/boost/asio/detail/fenced_block.hpp @@ -2,7 +2,7 @@ // detail/fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/functional.hpp b/boost/asio/detail/functional.hpp index 23218bb5df..73f06ece21 100644 --- a/boost/asio/detail/functional.hpp +++ b/boost/asio/detail/functional.hpp @@ -2,7 +2,7 @@ // detail/functional.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/future.hpp b/boost/asio/detail/future.hpp index 38cc7c1e83..67a0c1bde3 100644 --- a/boost/asio/detail/future.hpp +++ b/boost/asio/detail/future.hpp @@ -2,7 +2,7 @@ // detail/future.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/gcc_arm_fenced_block.hpp b/boost/asio/detail/gcc_arm_fenced_block.hpp index 3a5a1dfacf..4051657ed7 100644 --- a/boost/asio/detail/gcc_arm_fenced_block.hpp +++ b/boost/asio/detail/gcc_arm_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/gcc_arm_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/gcc_hppa_fenced_block.hpp b/boost/asio/detail/gcc_hppa_fenced_block.hpp index bc0bc8afb4..a3061c0301 100644 --- a/boost/asio/detail/gcc_hppa_fenced_block.hpp +++ b/boost/asio/detail/gcc_hppa_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/gcc_hppa_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/gcc_sync_fenced_block.hpp b/boost/asio/detail/gcc_sync_fenced_block.hpp index e464738ee0..a167c52f75 100644 --- a/boost/asio/detail/gcc_sync_fenced_block.hpp +++ b/boost/asio/detail/gcc_sync_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/gcc_sync_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/gcc_x86_fenced_block.hpp b/boost/asio/detail/gcc_x86_fenced_block.hpp index f66289fe96..5d5e4eef4a 100644 --- a/boost/asio/detail/gcc_x86_fenced_block.hpp +++ b/boost/asio/detail/gcc_x86_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/gcc_x86_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/global.hpp b/boost/asio/detail/global.hpp index 967890408f..383ceb8cd8 100644 --- a/boost/asio/detail/global.hpp +++ b/boost/asio/detail/global.hpp @@ -2,7 +2,7 @@ // detail/global.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/handler_alloc_helpers.hpp b/boost/asio/detail/handler_alloc_helpers.hpp index 6e72051393..85b825dd02 100644 --- a/boost/asio/detail/handler_alloc_helpers.hpp +++ b/boost/asio/detail/handler_alloc_helpers.hpp @@ -2,7 +2,7 @@ // detail/handler_alloc_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -194,7 +194,7 @@ struct get_hook_allocator<Handler, std::allocator<T> > } \ /**/ -#define BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \ +#define BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(purpose, op) \ struct ptr \ { \ const Alloc* a; \ @@ -207,9 +207,10 @@ struct get_hook_allocator<Handler, std::allocator<T> > static op* allocate(const Alloc& a) \ { \ typedef typename ::boost::asio::detail::get_recycling_allocator< \ - Alloc>::type recycling_allocator_type; \ + Alloc, purpose>::type recycling_allocator_type; \ BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \ - ::boost::asio::detail::get_recycling_allocator<Alloc>::get(a)); \ + ::boost::asio::detail::get_recycling_allocator< \ + Alloc, purpose>::get(a)); \ return a1.allocate(1); \ } \ void reset() \ @@ -222,9 +223,10 @@ struct get_hook_allocator<Handler, std::allocator<T> > if (v) \ { \ typedef typename ::boost::asio::detail::get_recycling_allocator< \ - Alloc>::type recycling_allocator_type; \ + Alloc, purpose>::type recycling_allocator_type; \ BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \ - ::boost::asio::detail::get_recycling_allocator<Alloc>::get(*a)); \ + ::boost::asio::detail::get_recycling_allocator< \ + Alloc, purpose>::get(*a)); \ a1.deallocate(static_cast<op*>(v), 1); \ v = 0; \ } \ @@ -232,6 +234,11 @@ struct get_hook_allocator<Handler, std::allocator<T> > } \ /**/ +#define BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \ + BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR( \ + ::boost::asio::detail::thread_info_base::default_tag, op ) \ + /**/ + #include <boost/asio/detail/pop_options.hpp> #endif // BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP diff --git a/boost/asio/detail/handler_cont_helpers.hpp b/boost/asio/detail/handler_cont_helpers.hpp index 700505d579..204097e032 100644 --- a/boost/asio/detail/handler_cont_helpers.hpp +++ b/boost/asio/detail/handler_cont_helpers.hpp @@ -2,7 +2,7 @@ // detail/handler_cont_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/handler_invoke_helpers.hpp b/boost/asio/detail/handler_invoke_helpers.hpp index 8ced5f617c..e453b02cf4 100644 --- a/boost/asio/detail/handler_invoke_helpers.hpp +++ b/boost/asio/detail/handler_invoke_helpers.hpp @@ -2,7 +2,7 @@ // detail/handler_invoke_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/handler_tracking.hpp b/boost/asio/detail/handler_tracking.hpp index 0839e09159..35eff023e2 100644 --- a/boost/asio/detail/handler_tracking.hpp +++ b/boost/asio/detail/handler_tracking.hpp @@ -2,7 +2,7 @@ // detail/handler_tracking.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/handler_type_requirements.hpp b/boost/asio/detail/handler_type_requirements.hpp index 3a83c8d154..cf57d67652 100644 --- a/boost/asio/detail/handler_type_requirements.hpp +++ b/boost/asio/detail/handler_type_requirements.hpp @@ -2,7 +2,7 @@ // detail/handler_type_requirements.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/handler_work.hpp b/boost/asio/detail/handler_work.hpp index dbd1bb911a..06da376178 100644 --- a/boost/asio/detail/handler_work.hpp +++ b/boost/asio/detail/handler_work.hpp @@ -2,7 +2,7 @@ // detail/handler_work.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,24 +28,41 @@ namespace detail { // A helper class template to allow completion handlers to be dispatched // through either the new executors framework or the old invocaton hook. The // primary template uses the new executors framework. -template <typename Handler, typename Executor - = typename associated_executor<Handler>::type> +template <typename Handler, + typename IoExecutor = system_executor, typename HandlerExecutor + = typename associated_executor<Handler, IoExecutor>::type> class handler_work { public: explicit handler_work(Handler& handler) BOOST_ASIO_NOEXCEPT - : executor_(associated_executor<Handler>::get(handler)) + : io_executor_(), + executor_(boost::asio::get_associated_executor(handler, io_executor_)) + { + } + + handler_work(Handler& handler, const IoExecutor& io_ex) BOOST_ASIO_NOEXCEPT + : io_executor_(io_ex), + executor_(boost::asio::get_associated_executor(handler, io_executor_)) { } static void start(Handler& handler) BOOST_ASIO_NOEXCEPT { - Executor ex(associated_executor<Handler>::get(handler)); + HandlerExecutor ex(boost::asio::get_associated_executor(handler)); + ex.on_work_started(); + } + + static void start(Handler& handler, + const IoExecutor& io_ex) BOOST_ASIO_NOEXCEPT + { + HandlerExecutor ex(boost::asio::get_associated_executor(handler, io_ex)); ex.on_work_started(); + io_ex.on_work_started(); } ~handler_work() { + io_executor_.on_work_finished(); executor_.on_work_finished(); } @@ -53,7 +70,7 @@ public: void complete(Function& function, Handler& handler) { executor_.dispatch(BOOST_ASIO_MOVE_CAST(Function)(function), - associated_allocator<Handler>::get(handler)); + boost::asio::get_associated_allocator(handler)); } private: @@ -61,7 +78,8 @@ private: handler_work(const handler_work&); handler_work& operator=(const handler_work&); - typename associated_executor<Handler>::type executor_; + IoExecutor io_executor_; + HandlerExecutor executor_; }; // This specialisation dispatches a handler through the old invocation hook. @@ -69,7 +87,7 @@ private: // system_executor will dispatch through the hook anyway. However, by doing // this we avoid an extra copy of the handler. template <typename Handler> -class handler_work<Handler, system_executor> +class handler_work<Handler, system_executor, system_executor> { public: explicit handler_work(Handler&) BOOST_ASIO_NOEXCEPT {} diff --git a/boost/asio/detail/hash_map.hpp b/boost/asio/detail/hash_map.hpp index 6a13620e92..ac80abdc79 100644 --- a/boost/asio/detail/hash_map.hpp +++ b/boost/asio/detail/hash_map.hpp @@ -2,7 +2,7 @@ // detail/hash_map.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/buffer_sequence_adapter.ipp b/boost/asio/detail/impl/buffer_sequence_adapter.ipp index 26708ced33..b3fb59ccc7 100644 --- a/boost/asio/detail/impl/buffer_sequence_adapter.ipp +++ b/boost/asio/detail/impl/buffer_sequence_adapter.ipp @@ -2,7 +2,7 @@ // detail/impl/buffer_sequence_adapter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/descriptor_ops.ipp b/boost/asio/detail/impl/descriptor_ops.ipp index 1bb68be1c0..1a26e6db69 100644 --- a/boost/asio/detail/impl/descriptor_ops.ipp +++ b/boost/asio/detail/impl/descriptor_ops.ipp @@ -2,7 +2,7 @@ // detail/impl/descriptor_ops.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/dev_poll_reactor.hpp b/boost/asio/detail/impl/dev_poll_reactor.hpp index 797937bad8..87dd20ab4b 100644 --- a/boost/asio/detail/impl/dev_poll_reactor.hpp +++ b/boost/asio/detail/impl/dev_poll_reactor.hpp @@ -2,7 +2,7 @@ // detail/impl/dev_poll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/dev_poll_reactor.ipp b/boost/asio/detail/impl/dev_poll_reactor.ipp index 5cc73ca9c1..807741dc4d 100644 --- a/boost/asio/detail/impl/dev_poll_reactor.ipp +++ b/boost/asio/detail/impl/dev_poll_reactor.ipp @@ -2,7 +2,7 @@ // detail/impl/dev_poll_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/epoll_reactor.hpp b/boost/asio/detail/impl/epoll_reactor.hpp index 101b1d6ead..15968a30b3 100644 --- a/boost/asio/detail/impl/epoll_reactor.hpp +++ b/boost/asio/detail/impl/epoll_reactor.hpp @@ -2,7 +2,7 @@ // detail/impl/epoll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/epoll_reactor.ipp b/boost/asio/detail/impl/epoll_reactor.ipp index 1e9babcc14..b1e1b39d05 100644 --- a/boost/asio/detail/impl/epoll_reactor.ipp +++ b/boost/asio/detail/impl/epoll_reactor.ipp @@ -2,7 +2,7 @@ // detail/impl/epoll_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/eventfd_select_interrupter.ipp b/boost/asio/detail/impl/eventfd_select_interrupter.ipp index 8804009442..38d4b2a61d 100644 --- a/boost/asio/detail/impl/eventfd_select_interrupter.ipp +++ b/boost/asio/detail/impl/eventfd_select_interrupter.ipp @@ -2,7 +2,7 @@ // detail/impl/eventfd_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/detail/impl/handler_tracking.ipp b/boost/asio/detail/impl/handler_tracking.ipp index b3abbb513a..c873a50987 100644 --- a/boost/asio/detail/impl/handler_tracking.ipp +++ b/boost/asio/detail/impl/handler_tracking.ipp @@ -2,7 +2,7 @@ // detail/impl/handler_tracking.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/kqueue_reactor.hpp b/boost/asio/detail/impl/kqueue_reactor.hpp index 4d79ba5d7c..f4dd174fdc 100644 --- a/boost/asio/detail/impl/kqueue_reactor.hpp +++ b/boost/asio/detail/impl/kqueue_reactor.hpp @@ -2,7 +2,7 @@ // detail/impl/kqueue_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/detail/impl/kqueue_reactor.ipp b/boost/asio/detail/impl/kqueue_reactor.ipp index 9069ae4442..02475aaa36 100644 --- a/boost/asio/detail/impl/kqueue_reactor.ipp +++ b/boost/asio/detail/impl/kqueue_reactor.ipp @@ -2,7 +2,7 @@ // detail/impl/kqueue_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/detail/impl/null_event.ipp b/boost/asio/detail/impl/null_event.ipp index 19bab80b33..b7568413fb 100644 --- a/boost/asio/detail/impl/null_event.ipp +++ b/boost/asio/detail/impl/null_event.ipp @@ -2,7 +2,7 @@ // detail/impl/null_event.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/pipe_select_interrupter.ipp b/boost/asio/detail/impl/pipe_select_interrupter.ipp index bfff076747..f7bb7851b2 100644 --- a/boost/asio/detail/impl/pipe_select_interrupter.ipp +++ b/boost/asio/detail/impl/pipe_select_interrupter.ipp @@ -2,7 +2,7 @@ // detail/impl/pipe_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/posix_event.ipp b/boost/asio/detail/impl/posix_event.ipp index 6f096bc08e..1c6d885a63 100644 --- a/boost/asio/detail/impl/posix_event.ipp +++ b/boost/asio/detail/impl/posix_event.ipp @@ -2,7 +2,7 @@ // detail/impl/posix_event.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/posix_mutex.ipp b/boost/asio/detail/impl/posix_mutex.ipp index 57564714a1..fc86d43815 100644 --- a/boost/asio/detail/impl/posix_mutex.ipp +++ b/boost/asio/detail/impl/posix_mutex.ipp @@ -2,7 +2,7 @@ // detail/impl/posix_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/posix_thread.ipp b/boost/asio/detail/impl/posix_thread.ipp index c2ee8efef7..d01922c625 100644 --- a/boost/asio/detail/impl/posix_thread.ipp +++ b/boost/asio/detail/impl/posix_thread.ipp @@ -2,7 +2,7 @@ // detail/impl/posix_thread.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/posix_tss_ptr.ipp b/boost/asio/detail/impl/posix_tss_ptr.ipp index a40f3f81a6..623dc679c5 100644 --- a/boost/asio/detail/impl/posix_tss_ptr.ipp +++ b/boost/asio/detail/impl/posix_tss_ptr.ipp @@ -2,7 +2,7 @@ // detail/impl/posix_tss_ptr.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/reactive_descriptor_service.ipp b/boost/asio/detail/impl/reactive_descriptor_service.ipp index 735239c597..0611a953db 100644 --- a/boost/asio/detail/impl/reactive_descriptor_service.ipp +++ b/boost/asio/detail/impl/reactive_descriptor_service.ipp @@ -2,7 +2,7 @@ // detail/impl/reactive_descriptor_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -31,9 +31,9 @@ namespace asio { namespace detail { reactive_descriptor_service::reactive_descriptor_service( - boost::asio::io_context& io_context) - : service_base<reactive_descriptor_service>(io_context), - reactor_(boost::asio::use_service<reactor>(io_context)) + execution_context& context) + : execution_context_service_base<reactive_descriptor_service>(context), + reactor_(boost::asio::use_service<reactor>(context)) { reactor_.init_task(); } diff --git a/boost/asio/detail/impl/reactive_serial_port_service.ipp b/boost/asio/detail/impl/reactive_serial_port_service.ipp index c1ff461830..62546604b4 100644 --- a/boost/asio/detail/impl/reactive_serial_port_service.ipp +++ b/boost/asio/detail/impl/reactive_serial_port_service.ipp @@ -2,7 +2,7 @@ // detail/impl/reactive_serial_port_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -31,9 +31,9 @@ namespace asio { namespace detail { reactive_serial_port_service::reactive_serial_port_service( - boost::asio::io_context& io_context) - : service_base<reactive_serial_port_service>(io_context), - descriptor_service_(io_context) + execution_context& context) + : execution_context_service_base<reactive_serial_port_service>(context), + descriptor_service_(context) { } diff --git a/boost/asio/detail/impl/reactive_socket_service_base.ipp b/boost/asio/detail/impl/reactive_socket_service_base.ipp index 6fdf437c1d..5ae4b64a6d 100644 --- a/boost/asio/detail/impl/reactive_socket_service_base.ipp +++ b/boost/asio/detail/impl/reactive_socket_service_base.ipp @@ -2,7 +2,7 @@ // detail/reactive_socket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -29,9 +29,8 @@ namespace asio { namespace detail { reactive_socket_service_base::reactive_socket_service_base( - boost::asio::io_context& io_context) - : io_context_(io_context), - reactor_(use_service<reactor>(io_context)) + execution_context& context) + : reactor_(use_service<reactor>(context)) { reactor_.init_task(); } diff --git a/boost/asio/detail/impl/resolver_service_base.ipp b/boost/asio/detail/impl/resolver_service_base.ipp index 144e2a1753..64b92a89ac 100644 --- a/boost/asio/detail/impl/resolver_service_base.ipp +++ b/boost/asio/detail/impl/resolver_service_base.ipp @@ -2,7 +2,7 @@ // detail/impl/resolver_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -24,25 +24,30 @@ namespace boost { namespace asio { namespace detail { -class resolver_service_base::work_io_context_runner +class resolver_service_base::work_scheduler_runner { public: - work_io_context_runner(boost::asio::io_context& io_context) - : io_context_(io_context) {} - void operator()() { io_context_.run(); } + work_scheduler_runner(scheduler_impl& work_scheduler) + : work_scheduler_(work_scheduler) + { + } + + void operator()() + { + boost::system::error_code ec; + work_scheduler_.run(ec); + } + private: - boost::asio::io_context& io_context_; + scheduler_impl& work_scheduler_; }; -resolver_service_base::resolver_service_base( - boost::asio::io_context& io_context) - : io_context_impl_(boost::asio::use_service<io_context_impl>(io_context)), - work_io_context_(new boost::asio::io_context(-1)), - work_io_context_impl_(boost::asio::use_service< - io_context_impl>(*work_io_context_)), - work_(boost::asio::make_work_guard(*work_io_context_)), +resolver_service_base::resolver_service_base(execution_context& context) + : scheduler_(boost::asio::use_service<scheduler_impl>(context)), + work_scheduler_(new scheduler_impl(context, -1, false)), work_thread_(0) { + work_scheduler_->work_started(); } resolver_service_base::~resolver_service_base() @@ -52,34 +57,35 @@ resolver_service_base::~resolver_service_base() void resolver_service_base::base_shutdown() { - work_.reset(); - if (work_io_context_.get()) + if (work_scheduler_.get()) { - work_io_context_->stop(); + work_scheduler_->work_finished(); + work_scheduler_->stop(); if (work_thread_.get()) { work_thread_->join(); work_thread_.reset(); } - work_io_context_.reset(); + work_scheduler_.reset(); } } void resolver_service_base::base_notify_fork( - boost::asio::io_context::fork_event fork_ev) + execution_context::fork_event fork_ev) { if (work_thread_.get()) { - if (fork_ev == boost::asio::io_context::fork_prepare) + if (fork_ev == execution_context::fork_prepare) { - work_io_context_->stop(); + work_scheduler_->stop(); work_thread_->join(); + work_thread_.reset(); } else { - work_io_context_->restart(); + work_scheduler_->restart(); work_thread_.reset(new boost::asio::detail::thread( - work_io_context_runner(*work_io_context_))); + work_scheduler_runner(*work_scheduler_))); } } } @@ -93,7 +99,7 @@ void resolver_service_base::construct( void resolver_service_base::destroy( resolver_service_base::implementation_type& impl) { - BOOST_ASIO_HANDLER_OPERATION((io_context_impl_.context(), + BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(), "resolver", &impl, 0, "cancel")); impl.reset(); @@ -115,7 +121,7 @@ void resolver_service_base::move_assign(implementation_type& impl, void resolver_service_base::cancel( resolver_service_base::implementation_type& impl) { - BOOST_ASIO_HANDLER_OPERATION((io_context_impl_.context(), + BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(), "resolver", &impl, 0, "cancel")); impl.reset(static_cast<void*>(0), socket_ops::noop_deleter()); @@ -124,16 +130,16 @@ void resolver_service_base::cancel( void resolver_service_base::start_resolve_op(resolve_op* op) { if (BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER, - io_context_impl_.concurrency_hint())) + scheduler_.concurrency_hint())) { start_work_thread(); - io_context_impl_.work_started(); - work_io_context_impl_.post_immediate_completion(op, false); + scheduler_.work_started(); + work_scheduler_->post_immediate_completion(op, false); } else { op->ec_ = boost::asio::error::operation_not_supported; - io_context_impl_.post_immediate_completion(op, false); + scheduler_.post_immediate_completion(op, false); } } @@ -143,7 +149,7 @@ void resolver_service_base::start_work_thread() if (!work_thread_.get()) { work_thread_.reset(new boost::asio::detail::thread( - work_io_context_runner(*work_io_context_))); + work_scheduler_runner(*work_scheduler_))); } } diff --git a/boost/asio/detail/impl/scheduler.ipp b/boost/asio/detail/impl/scheduler.ipp index 9dae6836ce..4ef5c86688 100644 --- a/boost/asio/detail/impl/scheduler.ipp +++ b/boost/asio/detail/impl/scheduler.ipp @@ -2,7 +2,7 @@ // detail/impl/scheduler.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -23,6 +23,7 @@ #include <boost/asio/detail/reactor.hpp> #include <boost/asio/detail/scheduler.hpp> #include <boost/asio/detail/scheduler_thread_info.hpp> +#include <boost/asio/detail/signal_blocker.hpp> #include <boost/asio/detail/push_options.hpp> @@ -30,6 +31,24 @@ namespace boost { namespace asio { namespace detail { +class scheduler::thread_function +{ +public: + explicit thread_function(scheduler* s) + : this_(s) + { + } + + void operator()() + { + boost::system::error_code ec; + this_->run(ec); + } + +private: + scheduler* this_; +}; + struct scheduler::task_cleanup { ~task_cleanup() @@ -85,8 +104,8 @@ struct scheduler::work_cleanup thread_info* this_thread_; }; -scheduler::scheduler( - boost::asio::execution_context& ctx, int concurrency_hint) +scheduler::scheduler(boost::asio::execution_context& ctx, + int concurrency_hint, bool own_thread) : boost::asio::detail::execution_context_service_base<scheduler>(ctx), one_thread_(concurrency_hint == 1 || !BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING( @@ -100,17 +119,44 @@ scheduler::scheduler( outstanding_work_(0), stopped_(false), shutdown_(false), - concurrency_hint_(concurrency_hint) + concurrency_hint_(concurrency_hint), + thread_(0) { BOOST_ASIO_HANDLER_TRACKING_INIT; + + if (own_thread) + { + ++outstanding_work_; + boost::asio::detail::signal_blocker sb; + thread_ = new boost::asio::detail::thread(thread_function(this)); + } +} + +scheduler::~scheduler() +{ + if (thread_) + { + thread_->join(); + delete thread_; + } } void scheduler::shutdown() { mutex::scoped_lock lock(mutex_); shutdown_ = true; + if (thread_) + stop_all_threads(lock); lock.unlock(); + // Join thread to ensure task operation is returned to queue. + if (thread_) + { + thread_->join(); + delete thread_; + thread_ = 0; + } + // Destroy handler objects. while (!op_queue_.empty()) { diff --git a/boost/asio/detail/impl/select_reactor.hpp b/boost/asio/detail/impl/select_reactor.hpp index 0fbaeb9ced..c741492c6a 100644 --- a/boost/asio/detail/impl/select_reactor.hpp +++ b/boost/asio/detail/impl/select_reactor.hpp @@ -2,7 +2,7 @@ // detail/impl/select_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/select_reactor.ipp b/boost/asio/detail/impl/select_reactor.ipp index 4f1f5a8303..34d3d9f031 100644 --- a/boost/asio/detail/impl/select_reactor.ipp +++ b/boost/asio/detail/impl/select_reactor.ipp @@ -2,7 +2,7 @@ // detail/impl/select_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/service_registry.hpp b/boost/asio/detail/impl/service_registry.hpp index c50614410e..e18473c8c8 100644 --- a/boost/asio/detail/impl/service_registry.hpp +++ b/boost/asio/detail/impl/service_registry.hpp @@ -2,7 +2,7 @@ // detail/impl/service_registry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/service_registry.ipp b/boost/asio/detail/impl/service_registry.ipp index abdcd6a01a..da920fbc50 100644 --- a/boost/asio/detail/impl/service_registry.ipp +++ b/boost/asio/detail/impl/service_registry.ipp @@ -2,7 +2,7 @@ // detail/impl/service_registry.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/signal_set_service.ipp b/boost/asio/detail/impl/signal_set_service.ipp index abd83b480c..5e23702bb0 100644 --- a/boost/asio/detail/impl/signal_set_service.ipp +++ b/boost/asio/detail/impl/signal_set_service.ipp @@ -2,7 +2,7 @@ // detail/impl/signal_set_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -119,14 +119,13 @@ public: // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) -signal_set_service::signal_set_service( - boost::asio::io_context& io_context) - : service_base<signal_set_service>(io_context), - io_context_(boost::asio::use_service<io_context_impl>(io_context)), +signal_set_service::signal_set_service(execution_context& context) + : execution_context_service_base<signal_set_service>(context), + scheduler_(boost::asio::use_service<scheduler_impl>(context)), #if !defined(BOOST_ASIO_WINDOWS) \ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__) - reactor_(boost::asio::use_service<reactor>(io_context)), + reactor_(boost::asio::use_service<reactor>(context)), #endif // !defined(BOOST_ASIO_WINDOWS) // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) @@ -170,11 +169,10 @@ void signal_set_service::shutdown() } } - io_context_.abandon_operations(ops); + scheduler_.abandon_operations(ops); } -void signal_set_service::notify_fork( - boost::asio::io_context::fork_event fork_ev) +void signal_set_service::notify_fork(execution_context::fork_event fork_ev) { #if !defined(BOOST_ASIO_WINDOWS) \ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ @@ -184,7 +182,7 @@ void signal_set_service::notify_fork( switch (fork_ev) { - case boost::asio::io_context::fork_prepare: + case execution_context::fork_prepare: { int read_descriptor = state->read_descriptor_; state->fork_prepared_ = true; @@ -193,7 +191,7 @@ void signal_set_service::notify_fork( reactor_.cleanup_descriptor_data(reactor_data_); } break; - case boost::asio::io_context::fork_parent: + case execution_context::fork_parent: if (state->fork_prepared_) { int read_descriptor = state->read_descriptor_; @@ -203,7 +201,7 @@ void signal_set_service::notify_fork( read_descriptor, reactor_data_, new pipe_read_op); } break; - case boost::asio::io_context::fork_child: + case execution_context::fork_child: if (state->fork_prepared_) { boost::asio::detail::signal_blocker blocker; @@ -442,7 +440,7 @@ boost::system::error_code signal_set_service::cancel( signal_set_service::implementation_type& impl, boost::system::error_code& ec) { - BOOST_ASIO_HANDLER_OPERATION((io_context_.context(), + BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(), "signal_set", &impl, 0, "cancel")); op_queue<operation> ops; @@ -458,7 +456,7 @@ boost::system::error_code signal_set_service::cancel( } } - io_context_.post_deferred_completions(ops); + scheduler_.post_deferred_completions(ops); ec = boost::system::error_code(); return ec; @@ -494,7 +492,7 @@ void signal_set_service::deliver_signal(int signal_number) reg = reg->next_in_table_; } - service->io_context_.post_deferred_completions(ops); + service->scheduler_.post_deferred_completions(ops); service = service->next_; } @@ -511,17 +509,17 @@ void signal_set_service::add_service(signal_set_service* service) open_descriptors(); #endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) - // If an io_context object is thread-unsafe then it must be the only - // io_context used to create signal_set objects. + // If a scheduler_ object is thread-unsafe then it must be the only + // scheduler used to create signal_set objects. if (state->service_list_ != 0) { if (!BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER, - service->io_context_.concurrency_hint()) + service->scheduler_.concurrency_hint()) || !BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER, - state->service_list_->io_context_.concurrency_hint())) + state->service_list_->scheduler_.concurrency_hint())) { std::logic_error ex( - "Thread-unsafe io_context objects require " + "Thread-unsafe execution context objects require " "exclusive access to signal handling."); boost::asio::detail::throw_exception(ex); } @@ -640,7 +638,7 @@ void signal_set_service::close_descriptors() void signal_set_service::start_wait_op( signal_set_service::implementation_type& impl, signal_op* op) { - io_context_.work_started(); + scheduler_.work_started(); signal_state* state = get_signal_state(); static_mutex::scoped_lock lock(state->mutex_); @@ -652,7 +650,7 @@ void signal_set_service::start_wait_op( { --reg->undelivered_; op->signal_number_ = reg->signal_number_; - io_context_.post_deferred_completion(op); + scheduler_.post_deferred_completion(op); return; } diff --git a/boost/asio/detail/impl/socket_ops.ipp b/boost/asio/detail/impl/socket_ops.ipp index bb60df0a8e..7d7c31fe03 100644 --- a/boost/asio/detail/impl/socket_ops.ipp +++ b/boost/asio/detail/impl/socket_ops.ipp @@ -2,7 +2,7 @@ // detail/impl/socket_ops.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -772,7 +772,7 @@ signed_size_type recv(socket_type s, buf* bufs, size_t count, else if (ec.value() == ERROR_PORT_UNREACHABLE) ec = boost::asio::error::connection_refused; else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA) - ec.assign(0, ec.category()); + result = 0; if (result != 0) return socket_error_retval; ec = boost::system::error_code(); @@ -926,7 +926,7 @@ signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, else if (ec.value() == ERROR_PORT_UNREACHABLE) ec = boost::asio::error::connection_refused; else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA) - ec.assign(0, ec.category()); + result = 0; if (result != 0) return socket_error_retval; ec = boost::system::error_code(); @@ -1503,7 +1503,8 @@ int setsockopt(socket_type s, state_type& state, int level, int optname, ec = boost::system::error_code(); #if defined(__MACH__) && defined(__APPLE__) \ - || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + || defined(__NetBSD__) || defined(__FreeBSD__) \ + || defined(__OpenBSD__) || defined(__QNX__) // To implement portable behaviour for SO_REUSEADDR with UDP sockets we // need to also set SO_REUSEPORT on BSD-based platforms. if ((state & datagram_oriented) diff --git a/boost/asio/detail/impl/socket_select_interrupter.ipp b/boost/asio/detail/impl/socket_select_interrupter.ipp index 3d9e5289d3..e09c5fbeb0 100644 --- a/boost/asio/detail/impl/socket_select_interrupter.ipp +++ b/boost/asio/detail/impl/socket_select_interrupter.ipp @@ -2,7 +2,7 @@ // detail/impl/socket_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/strand_executor_service.hpp b/boost/asio/detail/impl/strand_executor_service.hpp index 6452b949f4..67eb8361dd 100644 --- a/boost/asio/detail/impl/strand_executor_service.hpp +++ b/boost/asio/detail/impl/strand_executor_service.hpp @@ -2,7 +2,7 @@ // detail/impl/strand_executor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/strand_executor_service.ipp b/boost/asio/detail/impl/strand_executor_service.ipp index aed4d3cf6a..60681ea2f2 100644 --- a/boost/asio/detail/impl/strand_executor_service.ipp +++ b/boost/asio/detail/impl/strand_executor_service.ipp @@ -2,7 +2,7 @@ // detail/impl/strand_executor_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/strand_service.hpp b/boost/asio/detail/impl/strand_service.hpp index d47708bb98..7e82876ea2 100644 --- a/boost/asio/detail/impl/strand_service.hpp +++ b/boost/asio/detail/impl/strand_service.hpp @@ -2,7 +2,7 @@ // detail/impl/strand_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/strand_service.ipp b/boost/asio/detail/impl/strand_service.ipp index 9926f9abf3..340f310bf6 100644 --- a/boost/asio/detail/impl/strand_service.ipp +++ b/boost/asio/detail/impl/strand_service.ipp @@ -2,7 +2,7 @@ // detail/impl/strand_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/throw_error.ipp b/boost/asio/detail/impl/throw_error.ipp index ffcacf47ae..9483bd0f59 100644 --- a/boost/asio/detail/impl/throw_error.ipp +++ b/boost/asio/detail/impl/throw_error.ipp @@ -2,7 +2,7 @@ // detail/impl/throw_error.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/timer_queue_ptime.ipp b/boost/asio/detail/impl/timer_queue_ptime.ipp index 8a6d5af815..2566c9c2ca 100644 --- a/boost/asio/detail/impl/timer_queue_ptime.ipp +++ b/boost/asio/detail/impl/timer_queue_ptime.ipp @@ -2,7 +2,7 @@ // detail/impl/timer_queue_ptime.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/timer_queue_set.ipp b/boost/asio/detail/impl/timer_queue_set.ipp index 71f83216aa..b738142f28 100644 --- a/boost/asio/detail/impl/timer_queue_set.ipp +++ b/boost/asio/detail/impl/timer_queue_set.ipp @@ -2,7 +2,7 @@ // detail/impl/timer_queue_set.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/win_event.ipp b/boost/asio/detail/impl/win_event.ipp index 3e7dfdcf21..c6e1e3582f 100644 --- a/boost/asio/detail/impl/win_event.ipp +++ b/boost/asio/detail/impl/win_event.ipp @@ -2,7 +2,7 @@ // detail/win_event.ipp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/win_iocp_handle_service.ipp b/boost/asio/detail/impl/win_iocp_handle_service.ipp index 0cd7dd1719..1256c358ac 100644 --- a/boost/asio/detail/impl/win_iocp_handle_service.ipp +++ b/boost/asio/detail/impl/win_iocp_handle_service.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -66,10 +66,9 @@ public: } }; -win_iocp_handle_service::win_iocp_handle_service( - boost::asio::io_context& io_context) - : service_base<win_iocp_handle_service>(io_context), - iocp_service_(boost::asio::use_service<win_iocp_io_context>(io_context)), +win_iocp_handle_service::win_iocp_handle_service(execution_context& context) + : execution_context_service_base<win_iocp_handle_service>(context), + iocp_service_(boost::asio::use_service<win_iocp_io_context>(context)), mutex_(), impl_list_(0) { diff --git a/boost/asio/detail/impl/win_iocp_io_context.hpp b/boost/asio/detail/impl/win_iocp_io_context.hpp index 771c1f3c3a..830a07dcd9 100644 --- a/boost/asio/detail/impl/win_iocp_io_context.hpp +++ b/boost/asio/detail/impl/win_iocp_io_context.hpp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/win_iocp_io_context.ipp b/boost/asio/detail/impl/win_iocp_io_context.ipp index 87637f0b5c..5bdc540972 100644 --- a/boost/asio/detail/impl/win_iocp_io_context.ipp +++ b/boost/asio/detail/impl/win_iocp_io_context.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -24,6 +24,7 @@ #include <boost/asio/detail/handler_alloc_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/limits.hpp> +#include <boost/asio/detail/thread.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/detail/win_iocp_io_context.hpp> @@ -33,6 +34,22 @@ namespace boost { namespace asio { namespace detail { +struct win_iocp_io_context::thread_function +{ + explicit thread_function(win_iocp_io_context* s) + : this_(s) + { + } + + void operator()() + { + boost::system::error_code ec; + this_->run(ec); + } + + win_iocp_io_context* this_; +}; + struct win_iocp_io_context::work_finished_on_block_exit { ~work_finished_on_block_exit() @@ -63,7 +80,7 @@ struct win_iocp_io_context::timer_thread_function }; win_iocp_io_context::win_iocp_io_context( - boost::asio::execution_context& ctx, int concurrency_hint) + boost::asio::execution_context& ctx, int concurrency_hint, bool own_thread) : execution_context_service_base<win_iocp_io_context>(ctx), iocp_(), outstanding_work_(0), @@ -85,6 +102,21 @@ win_iocp_io_context::win_iocp_io_context( boost::asio::error::get_system_category()); boost::asio::detail::throw_error(ec, "iocp"); } + + if (own_thread) + { + ::InterlockedIncrement(&outstanding_work_); + thread_.reset(new boost::asio::detail::thread(thread_function(this))); + } +} + +win_iocp_io_context::~win_iocp_io_context() +{ + if (thread_.get()) + { + thread_->join(); + thread_.reset(); + } } void win_iocp_io_context::shutdown() @@ -98,6 +130,13 @@ void win_iocp_io_context::shutdown() ::SetWaitableTimer(waitable_timer_.handle, &timeout, 1, 0, 0, FALSE); } + if (thread_.get()) + { + thread_->join(); + thread_.reset(); + ::InterlockedDecrement(&outstanding_work_); + } + while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0) { op_queue<win_iocp_operation> ops; diff --git a/boost/asio/detail/impl/win_iocp_serial_port_service.ipp b/boost/asio/detail/impl/win_iocp_serial_port_service.ipp index 7dbf9353ee..4e30b0f678 100644 --- a/boost/asio/detail/impl/win_iocp_serial_port_service.ipp +++ b/boost/asio/detail/impl/win_iocp_serial_port_service.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_serial_port_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -30,9 +30,9 @@ namespace asio { namespace detail { win_iocp_serial_port_service::win_iocp_serial_port_service( - boost::asio::io_context& io_context) - : service_base<win_iocp_serial_port_service>(io_context), - handle_service_(io_context) + execution_context& context) + : execution_context_service_base<win_iocp_serial_port_service>(context), + handle_service_(context) { } diff --git a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp index 3b7e7066f5..f95c74ff58 100644 --- a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp +++ b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_socket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,9 +28,9 @@ namespace asio { namespace detail { win_iocp_socket_service_base::win_iocp_socket_service_base( - boost::asio::io_context& io_context) - : io_context_(io_context), - iocp_service_(use_service<win_iocp_io_context>(io_context)), + execution_context& context) + : context_(context), + iocp_service_(use_service<win_iocp_io_context>(context)), reactor_(0), connect_ex_(0), nt_set_info_(0), @@ -708,7 +708,7 @@ select_reactor& win_iocp_socket_service_base::get_reactor() reinterpret_cast<void**>(&reactor_), 0, 0)); if (!r) { - r = &(use_service<select_reactor>(io_context_)); + r = &(use_service<select_reactor>(context_)); interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r); } return *r; diff --git a/boost/asio/detail/impl/win_mutex.ipp b/boost/asio/detail/impl/win_mutex.ipp index 12922263f2..809d40f159 100644 --- a/boost/asio/detail/impl/win_mutex.ipp +++ b/boost/asio/detail/impl/win_mutex.ipp @@ -2,7 +2,7 @@ // detail/impl/win_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/win_object_handle_service.ipp b/boost/asio/detail/impl/win_object_handle_service.ipp index db56f722f2..f356a00613 100644 --- a/boost/asio/detail/impl/win_object_handle_service.ipp +++ b/boost/asio/detail/impl/win_object_handle_service.ipp @@ -2,7 +2,7 @@ // detail/impl/win_object_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -28,10 +28,9 @@ namespace boost { namespace asio { namespace detail { -win_object_handle_service::win_object_handle_service( - boost::asio::io_context& io_context) - : service_base<win_object_handle_service>(io_context), - io_context_(boost::asio::use_service<io_context_impl>(io_context)), +win_object_handle_service::win_object_handle_service(execution_context& context) + : execution_context_service_base<win_object_handle_service>(context), + scheduler_(boost::asio::use_service<scheduler_impl>(context)), mutex_(), impl_list_(0), shutdown_(false) @@ -53,7 +52,7 @@ void win_object_handle_service::shutdown() lock.unlock(); - io_context_.abandon_operations(ops); + scheduler_.abandon_operations(ops); } void win_object_handle_service::construct( @@ -179,7 +178,7 @@ void win_object_handle_service::destroy( if (is_open(impl)) { - BOOST_ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle", + BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle", &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "close")); HANDLE wait_handle = impl.wait_handle_; @@ -204,7 +203,7 @@ void win_object_handle_service::destroy( ::CloseHandle(impl.handle_); impl.handle_ = INVALID_HANDLE_VALUE; - io_context_.post_deferred_completions(ops); + scheduler_.post_deferred_completions(ops); } } @@ -229,7 +228,7 @@ boost::system::error_code win_object_handle_service::close( { if (is_open(impl)) { - BOOST_ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle", + BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle", &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "close")); mutex::scoped_lock lock(mutex_); @@ -265,7 +264,7 @@ boost::system::error_code win_object_handle_service::close( boost::asio::error::get_system_category()); } - io_context_.post_deferred_completions(completed_ops); + scheduler_.post_deferred_completions(completed_ops); } else { @@ -281,7 +280,7 @@ boost::system::error_code win_object_handle_service::cancel( { if (is_open(impl)) { - BOOST_ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle", + BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle", &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "cancel")); mutex::scoped_lock lock(mutex_); @@ -307,7 +306,7 @@ boost::system::error_code win_object_handle_service::cancel( ec = boost::system::error_code(); - io_context_.post_deferred_completions(completed_ops); + scheduler_.post_deferred_completions(completed_ops); } else { @@ -341,7 +340,7 @@ void win_object_handle_service::wait( void win_object_handle_service::start_wait_op( win_object_handle_service::implementation_type& impl, wait_op* op) { - io_context_.work_started(); + scheduler_.work_started(); if (is_open(impl)) { @@ -359,13 +358,13 @@ void win_object_handle_service::start_wait_op( else { lock.unlock(); - io_context_.post_deferred_completion(op); + scheduler_.post_deferred_completion(op); } } else { op->ec_ = boost::asio::error::bad_descriptor; - io_context_.post_deferred_completion(op); + scheduler_.post_deferred_completion(op); } } @@ -392,7 +391,7 @@ void win_object_handle_service::register_wait_callback( } lock.unlock(); - io_context_.post_deferred_completions(completed_ops); + scheduler_.post_deferred_completions(completed_ops); } } @@ -434,9 +433,9 @@ void win_object_handle_service::wait_callback(PVOID param, BOOLEAN) } } - io_context_impl& ioc = impl->owner_->io_context_; + scheduler_impl& sched = impl->owner_->scheduler_; lock.unlock(); - ioc.post_deferred_completions(completed_ops); + sched.post_deferred_completions(completed_ops); } } diff --git a/boost/asio/detail/impl/win_static_mutex.ipp b/boost/asio/detail/impl/win_static_mutex.ipp index 10e8622e37..ae53dbe105 100644 --- a/boost/asio/detail/impl/win_static_mutex.ipp +++ b/boost/asio/detail/impl/win_static_mutex.ipp @@ -2,7 +2,7 @@ // detail/impl/win_static_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/win_thread.ipp b/boost/asio/detail/impl/win_thread.ipp index 710c9b9f9b..13faa0753e 100644 --- a/boost/asio/detail/impl/win_thread.ipp +++ b/boost/asio/detail/impl/win_thread.ipp @@ -2,7 +2,7 @@ // detail/impl/win_thread.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/win_tss_ptr.ipp b/boost/asio/detail/impl/win_tss_ptr.ipp index 755d020703..8c6c5c60d7 100644 --- a/boost/asio/detail/impl/win_tss_ptr.ipp +++ b/boost/asio/detail/impl/win_tss_ptr.ipp @@ -2,7 +2,7 @@ // detail/impl/win_tss_ptr.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/impl/winrt_ssocket_service_base.ipp b/boost/asio/detail/impl/winrt_ssocket_service_base.ipp index e6254aed93..1728281091 100644 --- a/boost/asio/detail/impl/winrt_ssocket_service_base.ipp +++ b/boost/asio/detail/impl/winrt_ssocket_service_base.ipp @@ -2,7 +2,7 @@ // detail/impl/winrt_ssocket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -31,9 +31,9 @@ namespace asio { namespace detail { winrt_ssocket_service_base::winrt_ssocket_service_base( - boost::asio::io_context& io_context) - : io_context_(use_service<io_context_impl>(io_context)), - async_manager_(use_service<winrt_async_manager>(io_context)), + execution_context& context) + : scheduler_(use_service<scheduler_impl>(context)), + async_manager_(use_service<winrt_async_manager>(context)), mutex_(), impl_list_(0) { @@ -399,7 +399,7 @@ void winrt_ssocket_service_base::start_connect_op( if (!is_open(impl)) { op->ec_ = boost::asio::error::bad_descriptor; - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); return; } @@ -428,7 +428,7 @@ void winrt_ssocket_service_base::start_connect_op( if (op->ec_) { - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); return; } @@ -443,7 +443,7 @@ void winrt_ssocket_service_base::start_connect_op( { op->ec_ = boost::system::error_code( e->HResult, boost::system::system_category()); - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); } } @@ -494,14 +494,14 @@ void winrt_ssocket_service_base::start_send_op( if (flags) { op->ec_ = boost::asio::error::operation_not_supported; - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); return; } if (!is_open(impl)) { op->ec_ = boost::asio::error::bad_descriptor; - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); return; } @@ -512,7 +512,7 @@ void winrt_ssocket_service_base::start_send_op( if (bufs.all_empty()) { - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); return; } @@ -523,7 +523,7 @@ void winrt_ssocket_service_base::start_send_op( { op->ec_ = boost::system::error_code(e->HResult, boost::system::system_category()); - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); } } @@ -585,14 +585,14 @@ void winrt_ssocket_service_base::start_receive_op( if (flags) { op->ec_ = boost::asio::error::operation_not_supported; - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); return; } if (!is_open(impl)) { op->ec_ = boost::asio::error::bad_descriptor; - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); return; } @@ -603,7 +603,7 @@ void winrt_ssocket_service_base::start_receive_op( if (bufs.all_empty()) { - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); return; } @@ -616,7 +616,7 @@ void winrt_ssocket_service_base::start_receive_op( { op->ec_ = boost::system::error_code(e->HResult, boost::system::system_category()); - io_context_.post_immediate_completion(op, is_continuation); + scheduler_.post_immediate_completion(op, is_continuation); } } diff --git a/boost/asio/detail/impl/winrt_timer_scheduler.hpp b/boost/asio/detail/impl/winrt_timer_scheduler.hpp index a475f66640..89ac7a123c 100644 --- a/boost/asio/detail/impl/winrt_timer_scheduler.hpp +++ b/boost/asio/detail/impl/winrt_timer_scheduler.hpp @@ -2,7 +2,7 @@ // detail/impl/winrt_timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -47,12 +47,12 @@ void winrt_timer_scheduler::schedule_timer(timer_queue<Time_Traits>& queue, if (shutdown_) { - io_context_.post_immediate_completion(op, false); + scheduler_.post_immediate_completion(op, false); return; } bool earliest = queue.enqueue_timer(time, timer, op); - io_context_.work_started(); + scheduler_.work_started(); if (earliest) event_.signal(lock); } @@ -66,7 +66,7 @@ std::size_t winrt_timer_scheduler::cancel_timer(timer_queue<Time_Traits>& queue, op_queue<operation> ops; std::size_t n = queue.cancel_timer(timer, ops, max_cancelled); lock.unlock(); - io_context_.post_deferred_completions(ops); + scheduler_.post_deferred_completions(ops); return n; } diff --git a/boost/asio/detail/impl/winrt_timer_scheduler.ipp b/boost/asio/detail/impl/winrt_timer_scheduler.ipp index c8b77349cd..48cb29c42e 100644 --- a/boost/asio/detail/impl/winrt_timer_scheduler.ipp +++ b/boost/asio/detail/impl/winrt_timer_scheduler.ipp @@ -2,7 +2,7 @@ // detail/impl/winrt_timer_scheduler.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,10 +28,9 @@ namespace boost { namespace asio { namespace detail { -winrt_timer_scheduler::winrt_timer_scheduler( - boost::asio::io_context& io_context) - : boost::asio::detail::service_base<winrt_timer_scheduler>(io_context), - io_context_(use_service<io_context_impl>(io_context)), +winrt_timer_scheduler::winrt_timer_scheduler(execution_context& context) + : execution_context_service_base<winrt_timer_scheduler>(context), + scheduler_(use_service<scheduler_impl>(context)), mutex_(), event_(), timer_queues_(), @@ -65,10 +64,10 @@ void winrt_timer_scheduler::shutdown() op_queue<operation> ops; timer_queues_.get_all_timers(ops); - io_context_.abandon_operations(ops); + scheduler_.abandon_operations(ops); } -void winrt_timer_scheduler::notify_fork(boost::asio::io_context::fork_event) +void winrt_timer_scheduler::notify_fork(execution_context::fork_event) { } @@ -90,7 +89,7 @@ void winrt_timer_scheduler::run_thread() if (!ops.empty()) { lock.unlock(); - io_context_.post_deferred_completions(ops); + scheduler_.post_deferred_completions(ops); lock.lock(); } } diff --git a/boost/asio/detail/impl/winsock_init.ipp b/boost/asio/detail/impl/winsock_init.ipp index 5d31a03b06..85b50df5d0 100644 --- a/boost/asio/detail/impl/winsock_init.ipp +++ b/boost/asio/detail/impl/winsock_init.ipp @@ -2,7 +2,7 @@ // detail/impl/winsock_init.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/io_control.hpp b/boost/asio/detail/io_control.hpp index 112b0ad751..4f091dba08 100644 --- a/boost/asio/detail/io_control.hpp +++ b/boost/asio/detail/io_control.hpp @@ -2,7 +2,7 @@ // detail/io_control.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/io_object_executor.hpp b/boost/asio/detail/io_object_executor.hpp new file mode 100644 index 0000000000..70b026b476 --- /dev/null +++ b/boost/asio/detail/io_object_executor.hpp @@ -0,0 +1,162 @@ +// +// io_object_executor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP +#define BOOST_ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/handler_invoke_helpers.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/io_context.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// Wrap the (potentially polymorphic) executor so that we can bypass it when +// dispatching on a target executor that has a native I/O implementation. +template <typename Executor> +class io_object_executor +{ +public: + io_object_executor(const Executor& ex, + bool native_implementation) BOOST_ASIO_NOEXCEPT + : executor_(ex), + has_native_impl_(native_implementation) + { + } + + io_object_executor(const io_object_executor& other) BOOST_ASIO_NOEXCEPT + : executor_(other.executor_), + has_native_impl_(other.has_native_impl_) + { + } + + template <typename Executor1> + io_object_executor( + const io_object_executor<Executor1>& other) BOOST_ASIO_NOEXCEPT + : executor_(other.inner_executor()), + has_native_impl_(other.has_native_implementation()) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + io_object_executor(io_object_executor&& other) BOOST_ASIO_NOEXCEPT + : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)), + has_native_impl_(other.has_native_impl_) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + const Executor& inner_executor() const BOOST_ASIO_NOEXCEPT + { + return executor_; + } + + bool has_native_implementation() const BOOST_ASIO_NOEXCEPT + { + return has_native_impl_; + } + + execution_context& context() const BOOST_ASIO_NOEXCEPT + { + return executor_.context(); + } + + void on_work_started() const BOOST_ASIO_NOEXCEPT + { + if (is_same<Executor, io_context::executor_type>::value + || has_native_impl_) + { + // When using a native implementation, work is already counted by the + // execution context. + } + else + { + executor_.on_work_started(); + } + } + + void on_work_finished() const BOOST_ASIO_NOEXCEPT + { + if (is_same<Executor, io_context::executor_type>::value + || has_native_impl_) + { + // When using a native implementation, work is already counted by the + // execution context. + } + else + { + executor_.on_work_finished(); + } + } + + template <typename F, typename A> + void dispatch(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const + { + if (is_same<Executor, io_context::executor_type>::value + || has_native_impl_) + { + // When using a native implementation, I/O completion handlers are + // already dispatched according to the execution context's executor's + // rules. We can call the function directly. + typename decay<F>::type function(BOOST_ASIO_MOVE_CAST(F)(f)); + boost_asio_handler_invoke_helpers::invoke(function, function); + } + else + { + executor_.dispatch(BOOST_ASIO_MOVE_CAST(F)(f), a); + } + } + + template <typename F, typename A> + void post(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const + { + executor_.post(BOOST_ASIO_MOVE_CAST(F)(f), a); + } + + template <typename F, typename A> + void defer(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const + { + executor_.defer(BOOST_ASIO_MOVE_CAST(F)(f), a); + } + + friend bool operator==(const io_object_executor& a, + const io_object_executor& b) BOOST_ASIO_NOEXCEPT + { + return a.executor_ == b.executor_ + && a.has_native_impl_ == b.has_native_impl_; + } + + friend bool operator!=(const io_object_executor& a, + const io_object_executor& b) BOOST_ASIO_NOEXCEPT + { + return a.executor_ != b.executor_ + || a.has_native_impl_ != b.has_native_impl_; + } + +private: + Executor executor_; + const bool has_native_impl_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP diff --git a/boost/asio/detail/io_object_impl.hpp b/boost/asio/detail/io_object_impl.hpp new file mode 100644 index 0000000000..be1a5e2ac2 --- /dev/null +++ b/boost/asio/detail/io_object_impl.hpp @@ -0,0 +1,195 @@ +// +// io_object_impl.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IO_OBJECT_IMPL_HPP +#define BOOST_ASIO_DETAIL_IO_OBJECT_IMPL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <new> +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/io_object_executor.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/io_context.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +class executor; + +namespace detail { + +inline bool is_native_io_executor(const io_context::executor_type&) +{ + return true; +} + +template <typename Executor> +inline bool is_native_io_executor(const Executor&, + typename enable_if<!is_same<Executor, executor>::value>::type* = 0) +{ + return false; +} + +template <typename Executor> +inline bool is_native_io_executor(const Executor& ex, + typename enable_if<is_same<Executor, executor>::value>::type* = 0) +{ +#if !defined (BOOST_ASIO_NO_TYPEID) + return ex.target_type() == typeid(io_context::executor_type); +#else // !defined (BOOST_ASIO_NO_TYPEID) + return false; +#endif // !defined (BOOST_ASIO_NO_TYPEID) +} + +template <typename IoObjectService, + typename Executor = io_context::executor_type> +class io_object_impl +{ +public: + // The type of the service that will be used to provide I/O operations. + typedef IoObjectService service_type; + + // The underlying implementation type of I/O object. + typedef typename service_type::implementation_type implementation_type; + + // The type of the executor associated with the object. + typedef Executor executor_type; + + // The type of executor to be used when implementing asynchronous operations. + typedef io_object_executor<Executor> implementation_executor_type; + + // Construct an I/O object using an executor. + explicit io_object_impl(const executor_type& ex) + : service_(&boost::asio::use_service<IoObjectService>(ex.context())), + implementation_executor_(ex, (is_native_io_executor)(ex)) + { + service_->construct(implementation_); + } + + // Construct an I/O object using an execution context. + template <typename ExecutionContext> + explicit io_object_impl(ExecutionContext& context, + typename enable_if<is_convertible< + ExecutionContext&, execution_context&>::value>::type* = 0) + : service_(&boost::asio::use_service<IoObjectService>(context)), + implementation_executor_(context.get_executor(), + is_same<ExecutionContext, io_context>::value) + { + service_->construct(implementation_); + } + +#if defined(BOOST_ASIO_HAS_MOVE) + // Move-construct an I/O object. + io_object_impl(io_object_impl&& other) + : service_(&other.get_service()), + implementation_executor_(other.get_implementation_executor()) + { + service_->move_construct(implementation_, other.implementation_); + } + + // Perform a converting move-construction of an I/O object. + template <typename IoObjectService1, typename Executor1> + io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other) + : service_(&boost::asio::use_service<IoObjectService>( + other.get_implementation_executor().context())), + implementation_executor_(other.get_implementation_executor()) + { + service_->converting_move_construct(implementation_, + other.get_service(), other.get_implementation()); + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + // Destructor. + ~io_object_impl() + { + service_->destroy(implementation_); + } + +#if defined(BOOST_ASIO_HAS_MOVE) + // Move-assign an I/O object. + io_object_impl& operator=(io_object_impl&& other) + { + if (this != &other) + { + service_->move_assign(implementation_, + *other.service_, other.implementation_); + implementation_executor_.~implementation_executor_type(); + new (&implementation_executor_) implementation_executor_type( + std::move(other.implementation_executor_)); + service_ = other.service_; + } + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + // Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return implementation_executor_.inner_executor(); + } + + // Get the executor to be used when implementing asynchronous operations. + const implementation_executor_type& get_implementation_executor() + BOOST_ASIO_NOEXCEPT + { + return implementation_executor_; + } + + // Get the service associated with the I/O object. + service_type& get_service() + { + return *service_; + } + + // Get the service associated with the I/O object. + const service_type& get_service() const + { + return *service_; + } + + // Get the underlying implementation of the I/O object. + implementation_type& get_implementation() + { + return implementation_; + } + + // Get the underlying implementation of the I/O object. + const implementation_type& get_implementation() const + { + return implementation_; + } + +private: + // Disallow copying and copy assignment. + io_object_impl(const io_object_impl&); + io_object_impl& operator=(const io_object_impl&); + + // The service associated with the I/O object. + service_type* service_; + + // The underlying implementation of the I/O object. + implementation_type implementation_; + + // The associated executor. + implementation_executor_type implementation_executor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_IO_OBJECT_IMPL_HPP diff --git a/boost/asio/detail/is_buffer_sequence.hpp b/boost/asio/detail/is_buffer_sequence.hpp index a3fb9931d2..89b8df762d 100644 --- a/boost/asio/detail/is_buffer_sequence.hpp +++ b/boost/asio/detail/is_buffer_sequence.hpp @@ -2,7 +2,7 @@ // detail/is_buffer_sequence.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -39,6 +39,8 @@ struct buffer_sequence_memfns_base void prepare(); void commit(); void consume(); + void grow(); + void shrink(); }; template <typename T> @@ -157,6 +159,24 @@ char consume_memfn_helper( void (buffer_sequence_memfns_base::*)(), &buffer_sequence_memfns_derived<T>::consume>*); +template <typename> +char (&grow_memfn_helper(...))[2]; + +template <typename T> +char grow_memfn_helper( + buffer_sequence_memfns_check< + void (buffer_sequence_memfns_base::*)(), + &buffer_sequence_memfns_derived<T>::grow>*); + +template <typename> +char (&shrink_memfn_helper(...))[2]; + +template <typename T> +char shrink_memfn_helper( + buffer_sequence_memfns_check< + void (buffer_sequence_memfns_base::*)(), + &buffer_sequence_memfns_derived<T>::shrink>*); + template <typename, typename> char (&buffer_sequence_element_type_helper(...))[2]; @@ -234,7 +254,7 @@ struct is_buffer_sequence<const_buffer, mutable_buffer> }; template <typename T> -struct is_dynamic_buffer_class +struct is_dynamic_buffer_class_v1 : integral_constant<bool, sizeof(size_memfn_helper<T>(0)) != 1 && sizeof(max_size_memfn_helper<T>(0)) != 1 && @@ -249,9 +269,32 @@ struct is_dynamic_buffer_class }; template <typename T> -struct is_dynamic_buffer +struct is_dynamic_buffer_v1 + : conditional<is_class<T>::value, + is_dynamic_buffer_class_v1<T>, + false_type>::type +{ +}; + +template <typename T> +struct is_dynamic_buffer_class_v2 + : integral_constant<bool, + sizeof(size_memfn_helper<T>(0)) != 1 && + sizeof(max_size_memfn_helper<T>(0)) != 1 && + sizeof(capacity_memfn_helper<T>(0)) != 1 && + sizeof(data_memfn_helper<T>(0)) != 1 && + sizeof(consume_memfn_helper<T>(0)) != 1 && + sizeof(grow_memfn_helper<T>(0)) != 1 && + sizeof(shrink_memfn_helper<T>(0)) != 1 && + sizeof(const_buffers_type_typedef_helper<T>(0)) == 1 && + sizeof(mutable_buffers_type_typedef_helper<T>(0)) == 1> +{ +}; + +template <typename T> +struct is_dynamic_buffer_v2 : conditional<is_class<T>::value, - is_dynamic_buffer_class<T>, + is_dynamic_buffer_class_v2<T>, false_type>::type { }; diff --git a/boost/asio/detail/is_executor.hpp b/boost/asio/detail/is_executor.hpp index bc52ee87ce..ffcbb973f1 100644 --- a/boost/asio/detail/is_executor.hpp +++ b/boost/asio/detail/is_executor.hpp @@ -2,7 +2,7 @@ // detail/is_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/keyword_tss_ptr.hpp b/boost/asio/detail/keyword_tss_ptr.hpp index 8451b17510..b8770040a9 100644 --- a/boost/asio/detail/keyword_tss_ptr.hpp +++ b/boost/asio/detail/keyword_tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/keyword_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/kqueue_reactor.hpp b/boost/asio/detail/kqueue_reactor.hpp index 31d79ca6a4..a5de8fa901 100644 --- a/boost/asio/detail/kqueue_reactor.hpp +++ b/boost/asio/detail/kqueue_reactor.hpp @@ -2,7 +2,7 @@ // detail/kqueue_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/detail/local_free_on_block_exit.hpp b/boost/asio/detail/local_free_on_block_exit.hpp index 0f1a84108c..bcf65bed14 100644 --- a/boost/asio/detail/local_free_on_block_exit.hpp +++ b/boost/asio/detail/local_free_on_block_exit.hpp @@ -2,7 +2,7 @@ // detail/local_free_on_block_exit.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/macos_fenced_block.hpp b/boost/asio/detail/macos_fenced_block.hpp index 20196a78f6..639fc65a63 100644 --- a/boost/asio/detail/macos_fenced_block.hpp +++ b/boost/asio/detail/macos_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/macos_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/memory.hpp b/boost/asio/detail/memory.hpp index 21a68e456f..a18b4d9acc 100644 --- a/boost/asio/detail/memory.hpp +++ b/boost/asio/detail/memory.hpp @@ -2,7 +2,7 @@ // detail/memory.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/mutex.hpp b/boost/asio/detail/mutex.hpp index 9fe4ad333e..e5e75263b5 100644 --- a/boost/asio/detail/mutex.hpp +++ b/boost/asio/detail/mutex.hpp @@ -2,7 +2,7 @@ // detail/mutex.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/non_const_lvalue.hpp b/boost/asio/detail/non_const_lvalue.hpp new file mode 100644 index 0000000000..28e2a52bbe --- /dev/null +++ b/boost/asio/detail/non_const_lvalue.hpp @@ -0,0 +1,56 @@ +// +// 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 BOOST_ASIO_DETAIL_NON_CONST_LVALUE_HPP +#define BOOST_ASIO_DETAIL_NON_CONST_LVALUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/type_traits.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename T> +struct non_const_lvalue +{ +#if defined(BOOST_ASIO_HAS_MOVE) + explicit non_const_lvalue(T& t) + : value(static_cast<typename conditional< + is_same<T, typename decay<T>::type>::value, + typename decay<T>::type&, T&&>::type>(t)) + { + } + + typename conditional<is_same<T, typename decay<T>::type>::value, + typename decay<T>::type&, typename decay<T>::type>::type value; +#else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + explicit non_const_lvalue(const typename decay<T>::type& t) + : value(t) + { + } + + typename decay<T>::type value; +#endif // defined(BOOST_ASIO_HAS_MOVE) +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_NON_CONST_LVALUE_HPP diff --git a/boost/asio/detail/noncopyable.hpp b/boost/asio/detail/noncopyable.hpp index 36b30c074d..77cc71cb4d 100644 --- a/boost/asio/detail/noncopyable.hpp +++ b/boost/asio/detail/noncopyable.hpp @@ -2,7 +2,7 @@ // detail/noncopyable.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_event.hpp b/boost/asio/detail/null_event.hpp index 8394028e41..8ffc17c86c 100644 --- a/boost/asio/detail/null_event.hpp +++ b/boost/asio/detail/null_event.hpp @@ -2,7 +2,7 @@ // detail/null_event.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_fenced_block.hpp b/boost/asio/detail/null_fenced_block.hpp index f9f59af3a9..8fadff6906 100644 --- a/boost/asio/detail/null_fenced_block.hpp +++ b/boost/asio/detail/null_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/null_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_global.hpp b/boost/asio/detail/null_global.hpp index 3a4d516889..12303c295b 100644 --- a/boost/asio/detail/null_global.hpp +++ b/boost/asio/detail/null_global.hpp @@ -2,7 +2,7 @@ // detail/null_global.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_mutex.hpp b/boost/asio/detail/null_mutex.hpp index 90b92fe77b..7373675a03 100644 --- a/boost/asio/detail/null_mutex.hpp +++ b/boost/asio/detail/null_mutex.hpp @@ -2,7 +2,7 @@ // detail/null_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_reactor.hpp b/boost/asio/detail/null_reactor.hpp index 028f0f3535..4552e1cd89 100644 --- a/boost/asio/detail/null_reactor.hpp +++ b/boost/asio/detail/null_reactor.hpp @@ -2,7 +2,7 @@ // detail/null_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_signal_blocker.hpp b/boost/asio/detail/null_signal_blocker.hpp index b2285c1f45..74f5b75a54 100644 --- a/boost/asio/detail/null_signal_blocker.hpp +++ b/boost/asio/detail/null_signal_blocker.hpp @@ -2,7 +2,7 @@ // detail/null_signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_socket_service.hpp b/boost/asio/detail/null_socket_service.hpp index 2c5b784125..552d993308 100644 --- a/boost/asio/detail/null_socket_service.hpp +++ b/boost/asio/detail/null_socket_service.hpp @@ -2,7 +2,7 @@ // detail/null_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,7 +21,8 @@ #include <boost/asio/buffer.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/post.hpp> #include <boost/asio/socket_base.hpp> #include <boost/asio/detail/bind_handler.hpp> @@ -33,7 +34,7 @@ namespace detail { template <typename Protocol> class null_socket_service : - public service_base<null_socket_service<Protocol> > + public execution_context_service_base<null_socket_service<Protocol> > { public: // The protocol type. @@ -51,9 +52,8 @@ public: }; // Constructor. - null_socket_service(boost::asio::io_context& io_context) - : service_base<null_socket_service<Protocol> >(io_context), - io_context_(io_context) + null_socket_service(execution_context& context) + : execution_context_service_base<null_socket_service<Protocol> >(context) { } @@ -273,23 +273,25 @@ public: // Start an asynchronous send. The data being sent must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_send(implementation_type&, const ConstBufferSequence&, - socket_base::message_flags, Handler& handler) + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Start an asynchronous wait until data can be sent without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_send(implementation_type&, const null_buffers&, - socket_base::message_flags, Handler& handler) + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Receive some data from the peer. Returns the number of bytes received. @@ -311,23 +313,26 @@ public: // Start an asynchronous receive. The buffer for the data being received // must be valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive(implementation_type&, const MutableBufferSequence&, - socket_base::message_flags, Handler& handler) + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Wait until data can be received without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_receive(implementation_type&, const null_buffers&, - socket_base::message_flags, Handler& handler) + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Receive some data with associated flags. Returns the number of bytes @@ -352,25 +357,28 @@ public: // Start an asynchronous receive. The buffer for the data being received // must be valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive_with_flags(implementation_type&, const MutableBufferSequence&, socket_base::message_flags, - socket_base::message_flags&, Handler& handler) + socket_base::message_flags&, Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Wait until data can be received without blocking. - template <typename Handler> - void async_receive_with_flags(implementation_type&, - const null_buffers&, socket_base::message_flags, - socket_base::message_flags&, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_receive_with_flags(implementation_type&, const null_buffers&, + socket_base::message_flags, socket_base::message_flags&, + Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Send a datagram to the specified endpoint. Returns the number of bytes @@ -395,24 +403,27 @@ public: // Start an asynchronous send. The data being sent must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_send_to(implementation_type&, const ConstBufferSequence&, const endpoint_type&, socket_base::message_flags, Handler& handler) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Start an asynchronous wait until data can be sent without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_send_to(implementation_type&, const null_buffers&, - const endpoint_type&, socket_base::message_flags, Handler& handler) + const endpoint_type&, socket_base::message_flags, + Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Receive a datagram with the endpoint of the sender. Returns the number of @@ -438,25 +449,28 @@ public: // Start an asynchronous receive. The buffer for the data being received and // the sender_endpoint object must both be valid for the lifetime of the // asynchronous operation. - template <typename MutableBufferSequence, typename Handler> - void async_receive_from(implementation_type&, - const MutableBufferSequence&, endpoint_type&, - socket_base::message_flags, Handler& handler) + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_receive_from(implementation_type&, const MutableBufferSequence&, + endpoint_type&, socket_base::message_flags, Handler& handler, + const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Wait until data can be received without blocking. - template <typename Handler> - void async_receive_from(implementation_type&, - const null_buffers&, endpoint_type&, - socket_base::message_flags, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_receive_from(implementation_type&, const null_buffers&, + endpoint_type&, socket_base::message_flags, Handler& handler, + const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.post(detail::bind_handler(handler, ec, bytes_transferred)); + boost::asio::post(io_ex, detail::bind_handler( + handler, ec, bytes_transferred)); } // Accept a new connection. @@ -470,12 +484,12 @@ public: // Start an asynchronous accept. The peer and peer_endpoint objects // must be valid until the accept's handler is invoked. - template <typename Socket, typename Handler> - void async_accept(implementation_type&, Socket&, - endpoint_type*, Handler& handler) + template <typename Socket, typename Handler, typename IoExecutor> + void async_accept(implementation_type&, Socket&, endpoint_type*, + Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; - io_context_.post(detail::bind_handler(handler, ec)); + boost::asio::post(io_ex, detail::bind_handler(handler, ec)); } // Connect the socket to the specified endpoint. @@ -487,16 +501,13 @@ public: } // Start an asynchronous connect. - template <typename Handler> - void async_connect(implementation_type&, - const endpoint_type&, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_connect(implementation_type&, const endpoint_type&, + Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; - io_context_.post(detail::bind_handler(handler, ec)); + boost::asio::post(io_ex, detail::bind_handler(handler, ec)); } - -private: - boost::asio::io_context& io_context_; }; } // namespace detail diff --git a/boost/asio/detail/null_static_mutex.hpp b/boost/asio/detail/null_static_mutex.hpp index 7e2c0b522c..f8f9ab4e04 100644 --- a/boost/asio/detail/null_static_mutex.hpp +++ b/boost/asio/detail/null_static_mutex.hpp @@ -2,7 +2,7 @@ // detail/null_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_thread.hpp b/boost/asio/detail/null_thread.hpp index 56ad8bf806..bd1360c09f 100644 --- a/boost/asio/detail/null_thread.hpp +++ b/boost/asio/detail/null_thread.hpp @@ -2,7 +2,7 @@ // detail/null_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/null_tss_ptr.hpp b/boost/asio/detail/null_tss_ptr.hpp index 06d5a4d522..eacf4ff4a8 100644 --- a/boost/asio/detail/null_tss_ptr.hpp +++ b/boost/asio/detail/null_tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/null_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/object_pool.hpp b/boost/asio/detail/object_pool.hpp index 7e454a7138..0eadf7ab97 100644 --- a/boost/asio/detail/object_pool.hpp +++ b/boost/asio/detail/object_pool.hpp @@ -2,7 +2,7 @@ // detail/object_pool.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/old_win_sdk_compat.hpp b/boost/asio/detail/old_win_sdk_compat.hpp index f1b63cba0e..f5cb9d74b9 100644 --- a/boost/asio/detail/old_win_sdk_compat.hpp +++ b/boost/asio/detail/old_win_sdk_compat.hpp @@ -2,7 +2,7 @@ // detail/old_win_sdk_compat.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/op_queue.hpp b/boost/asio/detail/op_queue.hpp index 935e45920f..b2cd608cb0 100644 --- a/boost/asio/detail/op_queue.hpp +++ b/boost/asio/detail/op_queue.hpp @@ -2,7 +2,7 @@ // detail/op_queue.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/operation.hpp b/boost/asio/detail/operation.hpp index 13220231ab..4baed817f4 100644 --- a/boost/asio/detail/operation.hpp +++ b/boost/asio/detail/operation.hpp @@ -2,7 +2,7 @@ // detail/operation.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/pipe_select_interrupter.hpp b/boost/asio/detail/pipe_select_interrupter.hpp index 696d565729..01a467a415 100644 --- a/boost/asio/detail/pipe_select_interrupter.hpp +++ b/boost/asio/detail/pipe_select_interrupter.hpp @@ -2,7 +2,7 @@ // detail/pipe_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/pop_options.hpp b/boost/asio/detail/pop_options.hpp index 10450eacb5..3346b96fa4 100644 --- a/boost/asio/detail/pop_options.hpp +++ b/boost/asio/detail/pop_options.hpp @@ -2,7 +2,7 @@ // detail/pop_options.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -24,7 +24,9 @@ // Intel C++ # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) -# pragma GCC visibility pop +# if !defined(BOOST_ASIO_DISABLE_VISIBILITY) +# pragma GCC visibility pop +# endif // !defined(BOOST_ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) #elif defined(__clang__) @@ -42,7 +44,9 @@ # endif # if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) -# pragma GCC visibility pop +# if !defined(BOOST_ASIO_DISABLE_VISIBILITY) +# pragma GCC visibility pop +# endif // !defined(BOOST_ASIO_DISABLE_VISIBILITY) # endif // !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) #elif defined(__GNUC__) @@ -64,7 +68,9 @@ # endif # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) -# pragma GCC visibility pop +# if !defined(BOOST_ASIO_DISABLE_VISIBILITY) +# pragma GCC visibility pop +# endif // !defined(BOOST_ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) # if (__GNUC__ >= 7) diff --git a/boost/asio/detail/posix_event.hpp b/boost/asio/detail/posix_event.hpp index 98529eaf26..98a796c9df 100644 --- a/boost/asio/detail/posix_event.hpp +++ b/boost/asio/detail/posix_event.hpp @@ -2,7 +2,7 @@ // detail/posix_event.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -130,7 +130,7 @@ public: if (::clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { ts.tv_sec += usec / 1000000; - ts.tv_nsec = (usec % 1000000) * 1000; + ts.tv_nsec += (usec % 1000000) * 1000; ts.tv_sec += ts.tv_nsec / 1000000000; ts.tv_nsec = ts.tv_nsec % 1000000000; ::pthread_cond_timedwait(&cond_, diff --git a/boost/asio/detail/posix_fd_set_adapter.hpp b/boost/asio/detail/posix_fd_set_adapter.hpp index f68f2aa1c4..17faa564a8 100644 --- a/boost/asio/detail/posix_fd_set_adapter.hpp +++ b/boost/asio/detail/posix_fd_set_adapter.hpp @@ -2,7 +2,7 @@ // detail/posix_fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/posix_global.hpp b/boost/asio/detail/posix_global.hpp index c2c2996f88..357fe150cb 100644 --- a/boost/asio/detail/posix_global.hpp +++ b/boost/asio/detail/posix_global.hpp @@ -2,7 +2,7 @@ // detail/posix_global.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/posix_mutex.hpp b/boost/asio/detail/posix_mutex.hpp index 5e1d42c530..1418ab5759 100644 --- a/boost/asio/detail/posix_mutex.hpp +++ b/boost/asio/detail/posix_mutex.hpp @@ -2,7 +2,7 @@ // detail/posix_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/posix_signal_blocker.hpp b/boost/asio/detail/posix_signal_blocker.hpp index ea5758fb2c..729da819f6 100644 --- a/boost/asio/detail/posix_signal_blocker.hpp +++ b/boost/asio/detail/posix_signal_blocker.hpp @@ -2,7 +2,7 @@ // detail/posix_signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/posix_static_mutex.hpp b/boost/asio/detail/posix_static_mutex.hpp index cbf7013c2d..331868f0d4 100644 --- a/boost/asio/detail/posix_static_mutex.hpp +++ b/boost/asio/detail/posix_static_mutex.hpp @@ -2,7 +2,7 @@ // detail/posix_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/posix_thread.hpp b/boost/asio/detail/posix_thread.hpp index b2821f5356..b9cd59424f 100644 --- a/boost/asio/detail/posix_thread.hpp +++ b/boost/asio/detail/posix_thread.hpp @@ -2,7 +2,7 @@ // detail/posix_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/posix_tss_ptr.hpp b/boost/asio/detail/posix_tss_ptr.hpp index 93d06744a7..126c148d3b 100644 --- a/boost/asio/detail/posix_tss_ptr.hpp +++ b/boost/asio/detail/posix_tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/posix_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/push_options.hpp b/boost/asio/detail/push_options.hpp index 4927df93a2..679ac273c2 100644 --- a/boost/asio/detail/push_options.hpp +++ b/boost/asio/detail/push_options.hpp @@ -2,7 +2,7 @@ // detail/push_options.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -24,7 +24,9 @@ // Intel C++ # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) -# pragma GCC visibility push (default) +# if !defined(BOOST_ASIO_DISABLE_VISIBILITY) +# pragma GCC visibility push (default) +# endif // !defined(BOOST_ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) #elif defined(__clang__) @@ -44,7 +46,9 @@ # endif # if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) -# pragma GCC visibility push (default) +# if !defined(BOOST_ASIO_DISABLE_VISIBILITY) +# pragma GCC visibility push (default) +# endif // !defined(BOOST_ASIO_DISABLE_VISIBILITY) # endif // !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) #elif defined(__GNUC__) @@ -68,7 +72,9 @@ # endif # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) -# pragma GCC visibility push (default) +# if !defined(BOOST_ASIO_DISABLE_VISIBILITY) +# pragma GCC visibility push (default) +# endif // !defined(BOOST_ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) # if (__GNUC__ >= 7) diff --git a/boost/asio/detail/reactive_descriptor_service.hpp b/boost/asio/detail/reactive_descriptor_service.hpp index ac50a8ccb9..beed44a0ab 100644 --- a/boost/asio/detail/reactive_descriptor_service.hpp +++ b/boost/asio/detail/reactive_descriptor_service.hpp @@ -2,7 +2,7 @@ // detail/reactive_descriptor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -22,7 +22,7 @@ && !defined(__CYGWIN__) #include <boost/asio/buffer.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/detail/bind_handler.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> #include <boost/asio/detail/descriptor_ops.hpp> @@ -43,7 +43,7 @@ namespace asio { namespace detail { class reactive_descriptor_service : - public service_base<reactive_descriptor_service> + public execution_context_service_base<reactive_descriptor_service> { public: // The native type of a descriptor. @@ -76,8 +76,7 @@ public: }; // Constructor. - BOOST_ASIO_DECL reactive_descriptor_service( - boost::asio::io_context& io_context); + BOOST_ASIO_DECL reactive_descriptor_service(execution_context& context); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void shutdown(); @@ -191,18 +190,19 @@ public: // Asynchronously wait for the descriptor to become ready to read, ready to // write, or to have pending error conditions. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_wait(implementation_type& impl, - posix::descriptor_base::wait_type w, Handler& handler) + posix::descriptor_base::wait_type w, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_wait_op<Handler> op; + typedef reactive_wait_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_wait")); @@ -254,18 +254,19 @@ public: // Start an asynchronous write. The data being sent must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, Handler& handler) + const ConstBufferSequence& buffers, Handler& handler, + const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef descriptor_write_op<ConstBufferSequence, Handler> op; + typedef descriptor_write_op<ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.descriptor_, buffers, handler); + p.p = new (p.v) op(impl.descriptor_, buffers, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_write_some")); @@ -277,18 +278,18 @@ public: } // Start an asynchronous wait until data can be written without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_write_some(implementation_type& impl, - const null_buffers&, Handler& handler) + const null_buffers&, Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_null_buffers_op<Handler> op; + typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_write_some(null_buffers)")); @@ -321,18 +322,20 @@ public: // Start an asynchronous read. The buffer for the data being read must be // valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, Handler& handler) + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef descriptor_read_op<MutableBufferSequence, Handler> op; + typedef descriptor_read_op<MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.descriptor_, buffers, handler); + p.p = new (p.v) op(impl.descriptor_, buffers, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_read_some")); @@ -344,18 +347,18 @@ public: } // Wait until data can be read without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_read_some(implementation_type& impl, - const null_buffers&, Handler& handler) + const null_buffers&, Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_null_buffers_op<Handler> op; + typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_read_some(null_buffers)")); diff --git a/boost/asio/detail/reactive_null_buffers_op.hpp b/boost/asio/detail/reactive_null_buffers_op.hpp index dca3a3285f..fb25be335f 100644 --- a/boost/asio/detail/reactive_null_buffers_op.hpp +++ b/boost/asio/detail/reactive_null_buffers_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_null_buffers_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,18 +28,19 @@ namespace boost { namespace asio { namespace detail { -template <typename Handler> +template <typename Handler, typename IoExecutor> class reactive_null_buffers_op : public reactor_op { public: BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op); - reactive_null_buffers_op(Handler& handler) + reactive_null_buffers_op(Handler& handler, const IoExecutor& io_ex) : reactor_op(&reactive_null_buffers_op::do_perform, &reactive_null_buffers_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static status do_perform(reactor_op*) @@ -54,7 +55,7 @@ public: // Take ownership of the handler object. reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -81,6 +82,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/reactive_serial_port_service.hpp b/boost/asio/detail/reactive_serial_port_service.hpp index 42ff500d2c..ae752d06da 100644 --- a/boost/asio/detail/reactive_serial_port_service.hpp +++ b/boost/asio/detail/reactive_serial_port_service.hpp @@ -2,7 +2,7 @@ // detail/reactive_serial_port_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -23,7 +23,7 @@ #include <string> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/serial_port_base.hpp> #include <boost/asio/detail/descriptor_ops.hpp> #include <boost/asio/detail/reactive_descriptor_service.hpp> @@ -36,7 +36,7 @@ namespace detail { // Extend reactive_descriptor_service to provide serial port support. class reactive_serial_port_service : - public service_base<reactive_serial_port_service> + public execution_context_service_base<reactive_serial_port_service> { public: // The native type of a serial port. @@ -45,8 +45,7 @@ public: // The implementation type of the serial port. typedef reactive_descriptor_service::implementation_type implementation_type; - BOOST_ASIO_DECL reactive_serial_port_service( - boost::asio::io_context& io_context); + BOOST_ASIO_DECL reactive_serial_port_service(execution_context& context); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void shutdown(); @@ -157,11 +156,12 @@ public: // Start an asynchronous write. The data being written must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, Handler& handler) + const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { - descriptor_service_.async_write_some(impl, buffers, handler); + descriptor_service_.async_write_some(impl, buffers, handler, io_ex); } // Read some data. Returns the number of bytes received. @@ -174,11 +174,13 @@ public: // Start an asynchronous read. The buffer for the data being received must be // valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, Handler& handler) + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { - descriptor_service_.async_read_some(impl, buffers, handler); + descriptor_service_.async_read_some(impl, buffers, handler, io_ex); } private: diff --git a/boost/asio/detail/reactive_socket_accept_op.hpp b/boost/asio/detail/reactive_socket_accept_op.hpp index 292f3bdf25..972e01618c 100644 --- a/boost/asio/detail/reactive_socket_accept_op.hpp +++ b/boost/asio/detail/reactive_socket_accept_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_accept_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -86,7 +86,8 @@ private: std::size_t addrlen_; }; -template <typename Socket, typename Protocol, typename Handler> +template <typename Socket, typename Protocol, + typename Handler, typename IoExecutor> class reactive_socket_accept_op : public reactive_socket_accept_op_base<Socket, Protocol> { @@ -95,12 +96,14 @@ public: reactive_socket_accept_op(socket_type socket, socket_ops::state_type state, Socket& peer, const Protocol& protocol, - typename Protocol::endpoint* peer_endpoint, Handler& handler) + typename Protocol::endpoint* peer_endpoint, Handler& handler, + const IoExecutor& io_ex) : reactive_socket_accept_op_base<Socket, Protocol>(socket, state, peer, protocol, peer_endpoint, &reactive_socket_accept_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -110,7 +113,7 @@ public: // Take ownership of the handler object. reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); // On success, assign new connection to peer socket object. if (owner) @@ -141,28 +144,34 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; #if defined(BOOST_ASIO_HAS_MOVE) -template <typename Protocol, typename Handler> +template <typename Protocol, typename PeerIoExecutor, + typename Handler, typename IoExecutor> class reactive_socket_move_accept_op : - private Protocol::socket, - public reactive_socket_accept_op_base<typename Protocol::socket, Protocol> + private Protocol::socket::template rebind_executor<PeerIoExecutor>::other, + public reactive_socket_accept_op_base< + typename Protocol::socket::template rebind_executor<PeerIoExecutor>::other, + Protocol> { public: BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op); - reactive_socket_move_accept_op(io_context& ioc, socket_type socket, - socket_ops::state_type state, const Protocol& protocol, - typename Protocol::endpoint* peer_endpoint, Handler& handler) - : Protocol::socket(ioc), - reactive_socket_accept_op_base<typename Protocol::socket, Protocol>( + reactive_socket_move_accept_op(const PeerIoExecutor& peer_io_ex, + socket_type socket, socket_ops::state_type state, + const Protocol& protocol, typename Protocol::endpoint* peer_endpoint, + Handler& handler, const IoExecutor& io_ex) + : peer_socket_type(peer_io_ex), + reactive_socket_accept_op_base<peer_socket_type, Protocol>( socket, state, *this, protocol, peer_endpoint, &reactive_socket_move_accept_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -173,7 +182,7 @@ public: reactive_socket_move_accept_op* o( static_cast<reactive_socket_move_accept_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); // On success, assign new connection to peer socket object. if (owner) @@ -188,9 +197,9 @@ public: // to ensure that any owning sub-object remains valid until after we have // deallocated the memory here. detail::move_binder2<Handler, - boost::system::error_code, typename Protocol::socket> + boost::system::error_code, peer_socket_type> handler(0, BOOST_ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_, - BOOST_ASIO_MOVE_CAST(typename Protocol::socket)(*o)); + BOOST_ASIO_MOVE_CAST(peer_socket_type)(*o)); p.h = boost::asio::detail::addressof(handler.handler_); p.reset(); @@ -205,7 +214,11 @@ public: } private: + typedef typename Protocol::socket::template + rebind_executor<PeerIoExecutor>::other peer_socket_type; + Handler handler_; + IoExecutor io_executor_; }; #endif // defined(BOOST_ASIO_HAS_MOVE) diff --git a/boost/asio/detail/reactive_socket_connect_op.hpp b/boost/asio/detail/reactive_socket_connect_op.hpp index bbb5020501..e8701da312 100644 --- a/boost/asio/detail/reactive_socket_connect_op.hpp +++ b/boost/asio/detail/reactive_socket_connect_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -55,18 +55,20 @@ private: socket_type socket_; }; -template <typename Handler> +template <typename Handler, typename IoExecutor> class reactive_socket_connect_op : public reactive_socket_connect_op_base { public: BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op); - reactive_socket_connect_op(socket_type socket, Handler& handler) + reactive_socket_connect_op(socket_type socket, + Handler& handler, const IoExecutor& io_ex) : reactive_socket_connect_op_base(socket, &reactive_socket_connect_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -77,7 +79,7 @@ public: reactive_socket_connect_op* o (static_cast<reactive_socket_connect_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -104,6 +106,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/reactive_socket_recv_op.hpp b/boost/asio/detail/reactive_socket_recv_op.hpp index 0f124627bd..1d6889dcce 100644 --- a/boost/asio/detail/reactive_socket_recv_op.hpp +++ b/boost/asio/detail/reactive_socket_recv_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -75,21 +75,22 @@ private: socket_base::message_flags flags_; }; -template <typename MutableBufferSequence, typename Handler> +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> class reactive_socket_recv_op : public reactive_socket_recv_op_base<MutableBufferSequence> { public: BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op); - reactive_socket_recv_op(socket_type socket, - socket_ops::state_type state, const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler& handler) + reactive_socket_recv_op(socket_type socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) : reactive_socket_recv_op_base<MutableBufferSequence>(socket, state, buffers, flags, &reactive_socket_recv_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -99,7 +100,7 @@ public: // Take ownership of the handler object. reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -126,6 +127,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/reactive_socket_recvfrom_op.hpp b/boost/asio/detail/reactive_socket_recvfrom_op.hpp index b96a01327a..09aceba82f 100644 --- a/boost/asio/detail/reactive_socket_recvfrom_op.hpp +++ b/boost/asio/detail/reactive_socket_recvfrom_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_recvfrom_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -76,7 +76,8 @@ private: socket_base::message_flags flags_; }; -template <typename MutableBufferSequence, typename Endpoint, typename Handler> +template <typename MutableBufferSequence, typename Endpoint, + typename Handler, typename IoExecutor> class reactive_socket_recvfrom_op : public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint> { @@ -85,13 +86,15 @@ public: reactive_socket_recvfrom_op(socket_type socket, int protocol_type, const MutableBufferSequence& buffers, Endpoint& endpoint, - socket_base::message_flags flags, Handler& handler) + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) : reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>( socket, protocol_type, buffers, endpoint, flags, &reactive_socket_recvfrom_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -102,7 +105,7 @@ public: reactive_socket_recvfrom_op* o( static_cast<reactive_socket_recvfrom_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -129,6 +132,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/reactive_socket_recvmsg_op.hpp b/boost/asio/detail/reactive_socket_recvmsg_op.hpp index 6ae324947c..bb65a19cf4 100644 --- a/boost/asio/detail/reactive_socket_recvmsg_op.hpp +++ b/boost/asio/detail/reactive_socket_recvmsg_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_recvmsg_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -71,7 +71,7 @@ private: socket_base::message_flags& out_flags_; }; -template <typename MutableBufferSequence, typename Handler> +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> class reactive_socket_recvmsg_op : public reactive_socket_recvmsg_op_base<MutableBufferSequence> { @@ -80,12 +80,14 @@ public: reactive_socket_recvmsg_op(socket_type socket, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler& handler) + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) : reactive_socket_recvmsg_op_base<MutableBufferSequence>(socket, buffers, in_flags, out_flags, &reactive_socket_recvmsg_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -96,7 +98,7 @@ public: reactive_socket_recvmsg_op* o( static_cast<reactive_socket_recvmsg_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -123,6 +125,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/reactive_socket_send_op.hpp b/boost/asio/detail/reactive_socket_send_op.hpp index 11f3ad80af..6be6081cc9 100644 --- a/boost/asio/detail/reactive_socket_send_op.hpp +++ b/boost/asio/detail/reactive_socket_send_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -74,21 +74,22 @@ private: socket_base::message_flags flags_; }; -template <typename ConstBufferSequence, typename Handler> +template <typename ConstBufferSequence, typename Handler, typename IoExecutor> class reactive_socket_send_op : public reactive_socket_send_op_base<ConstBufferSequence> { public: BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op); - reactive_socket_send_op(socket_type socket, - socket_ops::state_type state, const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler& handler) + reactive_socket_send_op(socket_type socket, socket_ops::state_type state, + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) : reactive_socket_send_op_base<ConstBufferSequence>(socket, state, buffers, flags, &reactive_socket_send_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -98,7 +99,7 @@ public: // Take ownership of the handler object. reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -125,6 +126,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/reactive_socket_sendto_op.hpp b/boost/asio/detail/reactive_socket_sendto_op.hpp index a73934bfc1..3429a7585e 100644 --- a/boost/asio/detail/reactive_socket_sendto_op.hpp +++ b/boost/asio/detail/reactive_socket_sendto_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_sendto_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -70,7 +70,8 @@ private: socket_base::message_flags flags_; }; -template <typename ConstBufferSequence, typename Endpoint, typename Handler> +template <typename ConstBufferSequence, typename Endpoint, + typename Handler, typename IoExecutor> class reactive_socket_sendto_op : public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint> { @@ -79,12 +80,14 @@ public: reactive_socket_sendto_op(socket_type socket, const ConstBufferSequence& buffers, const Endpoint& endpoint, - socket_base::message_flags flags, Handler& handler) + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) : reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>(socket, buffers, endpoint, flags, &reactive_socket_sendto_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -94,7 +97,7 @@ public: // Take ownership of the handler object. reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -121,6 +124,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/reactive_socket_service.hpp b/boost/asio/detail/reactive_socket_service.hpp index 89940d9af0..fb3a0e4660 100644 --- a/boost/asio/detail/reactive_socket_service.hpp +++ b/boost/asio/detail/reactive_socket_service.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,7 +21,7 @@ #include <boost/asio/buffer.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/socket_base.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> #include <boost/asio/detail/memory.hpp> @@ -46,7 +46,7 @@ namespace detail { template <typename Protocol> class reactive_socket_service : - public service_base<reactive_socket_service<Protocol> >, + public execution_context_service_base<reactive_socket_service<Protocol> >, public reactive_socket_service_base { public: @@ -74,9 +74,10 @@ public: }; // Constructor. - reactive_socket_service(boost::asio::io_context& io_context) - : service_base<reactive_socket_service<Protocol> >(io_context), - reactive_socket_service_base(io_context) + reactive_socket_service(execution_context& context) + : execution_context_service_base< + reactive_socket_service<Protocol> >(context), + reactive_socket_service_base(context) { } @@ -240,21 +241,22 @@ public: // Start an asynchronous send. The data being sent must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_send_to(implementation_type& impl, const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, - Handler& handler) + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. typedef reactive_socket_sendto_op<ConstBufferSequence, - endpoint_type, Handler> op; + endpoint_type, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler); + p.p = new (p.v) op(impl.socket_, buffers, + destination, flags, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send_to")); @@ -264,18 +266,19 @@ public: } // Start an asynchronous wait until data can be sent without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_send_to(implementation_type& impl, const null_buffers&, - const endpoint_type&, socket_base::message_flags, Handler& handler) + const endpoint_type&, socket_base::message_flags, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_null_buffers_op<Handler> op; + typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send_to(null_buffers)")); @@ -323,22 +326,24 @@ public: // Start an asynchronous receive. The buffer for the data being received and // the sender_endpoint object must both be valid for the lifetime of the // asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive_from(implementation_type& impl, const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, Handler& handler) + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. typedef reactive_socket_recvfrom_op<MutableBufferSequence, - endpoint_type, Handler> op; + endpoint_type, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; int protocol = impl.protocol_.type(); - p.p = new (p.v) op(impl.socket_, protocol, - buffers, sender_endpoint, flags, handler); + p.p = new (p.v) op(impl.socket_, protocol, buffers, + sender_endpoint, flags, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_from")); @@ -351,19 +356,19 @@ public: } // Wait until data can be received without blocking. - template <typename Handler> - void async_receive_from(implementation_type& impl, - const null_buffers&, endpoint_type& sender_endpoint, - socket_base::message_flags flags, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_null_buffers_op<Handler> op; + typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_from(null_buffers)")); @@ -408,49 +413,21 @@ public: return ec; } -#if defined(BOOST_ASIO_HAS_MOVE) - // Accept a new connection. - typename Protocol::socket accept(implementation_type& impl, - io_context* peer_io_context, endpoint_type* peer_endpoint, - boost::system::error_code& ec) - { - typename Protocol::socket peer( - peer_io_context ? *peer_io_context : io_context_); - - std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; - socket_holder new_socket(socket_ops::sync_accept(impl.socket_, - impl.state_, peer_endpoint ? peer_endpoint->data() : 0, - peer_endpoint ? &addr_len : 0, ec)); - - // On success, assign new connection to peer socket object. - if (new_socket.get() != invalid_socket) - { - if (peer_endpoint) - peer_endpoint->resize(addr_len); - peer.assign(impl.protocol_, new_socket.get(), ec); - if (!ec) - new_socket.release(); - } - - return peer; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) - // Start an asynchronous accept. The peer and peer_endpoint objects must be // valid until the accept's handler is invoked. - template <typename Socket, typename Handler> + template <typename Socket, typename Handler, typename IoExecutor> void async_accept(implementation_type& impl, Socket& peer, - endpoint_type* peer_endpoint, Handler& handler) + endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_socket_accept_op<Socket, Protocol, Handler> op; + typedef reactive_socket_accept_op<Socket, Protocol, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(impl.socket_, impl.state_, peer, - impl.protocol_, peer_endpoint, handler); + impl.protocol_, peer_endpoint, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_accept")); @@ -462,20 +439,21 @@ public: #if defined(BOOST_ASIO_HAS_MOVE) // Start an asynchronous accept. The peer_endpoint object must be valid until // the accept's handler is invoked. - template <typename Handler> - void async_accept(implementation_type& impl, - boost::asio::io_context* peer_io_context, - endpoint_type* peer_endpoint, Handler& handler) + template <typename PeerIoExecutor, typename Handler, typename IoExecutor> + void async_move_accept(implementation_type& impl, + const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_socket_move_accept_op<Protocol, Handler> op; + typedef reactive_socket_move_accept_op<Protocol, + PeerIoExecutor, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(peer_io_context ? *peer_io_context : io_context_, - impl.socket_, impl.state_, impl.protocol_, peer_endpoint, handler); + p.p = new (p.v) op(peer_io_ex, impl.socket_, impl.state_, + impl.protocol_, peer_endpoint, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_accept")); @@ -495,18 +473,19 @@ public: } // Start an asynchronous connect. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler& handler) + const endpoint_type& peer_endpoint, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_socket_connect_op<Handler> op; + typedef reactive_socket_connect_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.socket_, handler); + p.p = new (p.v) op(impl.socket_, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_connect")); diff --git a/boost/asio/detail/reactive_socket_service_base.hpp b/boost/asio/detail/reactive_socket_service_base.hpp index 9d3d54cc11..26fb828b01 100644 --- a/boost/asio/detail/reactive_socket_service_base.hpp +++ b/boost/asio/detail/reactive_socket_service_base.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -22,7 +22,7 @@ #include <boost/asio/buffer.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/socket_base.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> #include <boost/asio/detail/memory.hpp> @@ -63,8 +63,7 @@ public: }; // Constructor. - BOOST_ASIO_DECL reactive_socket_service_base( - boost::asio::io_context& io_context); + BOOST_ASIO_DECL reactive_socket_service_base(execution_context& context); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void base_shutdown(); @@ -194,18 +193,18 @@ public: // Asynchronously wait for the socket to become ready to read, ready to // write, or to have pending error conditions. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_wait(base_implementation_type& impl, - socket_base::wait_type w, Handler& handler) + socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_wait_op<Handler> op; + typedef reactive_wait_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_wait")); @@ -258,19 +257,21 @@ public: // Start an asynchronous send. The data being sent must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_send(base_implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler& handler) + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_socket_send_op<ConstBufferSequence, Handler> op; + typedef reactive_socket_send_op< + ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler); + p.p = new (p.v) op(impl.socket_, impl.state_, + buffers, flags, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send")); @@ -283,18 +284,18 @@ public: } // Start an asynchronous wait until data can be sent without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_send(base_implementation_type& impl, const null_buffers&, - socket_base::message_flags, Handler& handler) + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_null_buffers_op<Handler> op; + typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send(null_buffers)")); @@ -328,19 +329,22 @@ public: // Start an asynchronous receive. The buffer for the data being received // must be valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive(base_implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler& handler) + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_socket_recv_op<MutableBufferSequence, Handler> op; + typedef reactive_socket_recv_op< + MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler); + p.p = new (p.v) op(impl.socket_, impl.state_, + buffers, flags, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive")); @@ -357,18 +361,19 @@ public: } // Wait until data can be received without blocking. - template <typename Handler> - void async_receive(base_implementation_type& impl, const null_buffers&, - socket_base::message_flags flags, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_receive(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_null_buffers_op<Handler> op; + typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive(null_buffers)")); @@ -412,19 +417,23 @@ public: // Start an asynchronous receive. The buffer for the data being received // must be valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive_with_flags(base_implementation_type& impl, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler& handler) + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_socket_recvmsg_op<MutableBufferSequence, Handler> op; + typedef reactive_socket_recvmsg_op< + MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler); + p.p = new (p.v) op(impl.socket_, buffers, + in_flags, out_flags, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_with_flags")); @@ -438,19 +447,20 @@ public: } // Wait until data can be received without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_receive_with_flags(base_implementation_type& impl, const null_buffers&, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler& handler) + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef reactive_null_buffers_op<Handler> op; + typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); @@ -490,9 +500,6 @@ protected: reactor_op* op, bool is_continuation, const socket_addr_type* addr, size_t addrlen); - // The io_context that owns this socket service. - io_context& io_context_; - // The selector that performs event demultiplexing for the service. reactor& reactor_; }; diff --git a/boost/asio/detail/reactive_wait_op.hpp b/boost/asio/detail/reactive_wait_op.hpp index ee32502482..021059dcd5 100644 --- a/boost/asio/detail/reactive_wait_op.hpp +++ b/boost/asio/detail/reactive_wait_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_wait_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,18 +28,19 @@ namespace boost { namespace asio { namespace detail { -template <typename Handler> +template <typename Handler, typename IoExecutor> class reactive_wait_op : public reactor_op { public: BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_wait_op); - reactive_wait_op(Handler& handler) + reactive_wait_op(Handler& handler, const IoExecutor& io_ex) : reactor_op(&reactive_wait_op::do_perform, &reactive_wait_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static status do_perform(reactor_op*) @@ -54,7 +55,7 @@ public: // Take ownership of the handler object. reactive_wait_op* o(static_cast<reactive_wait_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -81,6 +82,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/reactor.hpp b/boost/asio/detail/reactor.hpp index f1e5d95864..bfe999bed3 100644 --- a/boost/asio/detail/reactor.hpp +++ b/boost/asio/detail/reactor.hpp @@ -2,7 +2,7 @@ // detail/reactor.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/reactor_fwd.hpp b/boost/asio/detail/reactor_fwd.hpp index b222b134e6..2ea1eec99e 100644 --- a/boost/asio/detail/reactor_fwd.hpp +++ b/boost/asio/detail/reactor_fwd.hpp @@ -2,7 +2,7 @@ // detail/reactor_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/reactor_op.hpp b/boost/asio/detail/reactor_op.hpp index beb443eb69..4c399a5036 100644 --- a/boost/asio/detail/reactor_op.hpp +++ b/boost/asio/detail/reactor_op.hpp @@ -2,7 +2,7 @@ // detail/reactor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/reactor_op_queue.hpp b/boost/asio/detail/reactor_op_queue.hpp index fec0dd7d37..dd28b6dc98 100644 --- a/boost/asio/detail/reactor_op_queue.hpp +++ b/boost/asio/detail/reactor_op_queue.hpp @@ -2,7 +2,7 @@ // detail/reactor_op_queue.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/recycling_allocator.hpp b/boost/asio/detail/recycling_allocator.hpp index adab0a7a61..74003bfdd6 100644 --- a/boost/asio/detail/recycling_allocator.hpp +++ b/boost/asio/detail/recycling_allocator.hpp @@ -2,7 +2,7 @@ // detail/recycling_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -26,7 +26,7 @@ namespace boost { namespace asio { namespace detail { -template <typename T> +template <typename T, typename Purpose = thread_info_base::default_tag> class recycling_allocator { public: @@ -35,7 +35,7 @@ public: template <typename U> struct rebind { - typedef recycling_allocator<U> other; + typedef recycling_allocator<U, Purpose> other; }; recycling_allocator() @@ -43,26 +43,28 @@ public: } template <typename U> - recycling_allocator(const recycling_allocator<U>&) + recycling_allocator(const recycling_allocator<U, Purpose>&) { } T* allocate(std::size_t n) { typedef thread_context::thread_call_stack call_stack; - void* p = thread_info_base::allocate(call_stack::top(), sizeof(T) * n); + void* p = thread_info_base::allocate(Purpose(), + call_stack::top(), sizeof(T) * n); return static_cast<T*>(p); } void deallocate(T* p, std::size_t n) { typedef thread_context::thread_call_stack call_stack; - thread_info_base::deallocate(call_stack::top(), p, sizeof(T) * n); + thread_info_base::deallocate(Purpose(), + call_stack::top(), p, sizeof(T) * n); } }; -template <> -class recycling_allocator<void> +template <typename Purpose> +class recycling_allocator<void, Purpose> { public: typedef void value_type; @@ -70,7 +72,7 @@ public: template <typename U> struct rebind { - typedef recycling_allocator<U> other; + typedef recycling_allocator<U, Purpose> other; }; recycling_allocator() @@ -78,22 +80,22 @@ public: } template <typename U> - recycling_allocator(const recycling_allocator<U>&) + recycling_allocator(const recycling_allocator<U, Purpose>&) { } }; -template <typename Allocator> +template <typename Allocator, typename Purpose> struct get_recycling_allocator { typedef Allocator type; static type get(const Allocator& a) { return a; } }; -template <typename T> -struct get_recycling_allocator<std::allocator<T> > +template <typename T, typename Purpose> +struct get_recycling_allocator<std::allocator<T>, Purpose> { - typedef recycling_allocator<T> type; + typedef recycling_allocator<T, Purpose> type; static type get(const std::allocator<T>&) { return type(); } }; diff --git a/boost/asio/detail/regex_fwd.hpp b/boost/asio/detail/regex_fwd.hpp index 4d35a68ab9..a2dd26dff4 100644 --- a/boost/asio/detail/regex_fwd.hpp +++ b/boost/asio/detail/regex_fwd.hpp @@ -2,7 +2,7 @@ // detail/regex_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/resolve_endpoint_op.hpp b/boost/asio/detail/resolve_endpoint_op.hpp index 970544c783..72df8d94ac 100644 --- a/boost/asio/detail/resolve_endpoint_op.hpp +++ b/boost/asio/detail/resolve_endpoint_op.hpp @@ -2,7 +2,7 @@ // detail/resolve_endpoint_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,7 +17,6 @@ #include <boost/asio/detail/config.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> #include <boost/asio/ip/basic_resolver_results.hpp> #include <boost/asio/detail/bind_handler.hpp> #include <boost/asio/detail/fenced_block.hpp> @@ -27,13 +26,19 @@ #include <boost/asio/detail/resolve_op.hpp> #include <boost/asio/detail/socket_ops.hpp> +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) + #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { namespace detail { -template <typename Protocol, typename Handler> +template <typename Protocol, typename Handler, typename IoExecutor> class resolve_endpoint_op : public resolve_op { public: @@ -42,15 +47,23 @@ public: typedef typename Protocol::endpoint endpoint_type; typedef boost::asio::ip::basic_resolver_results<Protocol> results_type; +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + resolve_endpoint_op(socket_ops::weak_cancel_token_type cancel_token, - const endpoint_type& endpoint, io_context_impl& ioc, Handler& handler) + const endpoint_type& endpoint, scheduler_impl& sched, + Handler& handler, const IoExecutor& io_ex) : resolve_op(&resolve_endpoint_op::do_complete), cancel_token_(cancel_token), endpoint_(endpoint), - io_context_impl_(ioc), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + scheduler_(sched), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -60,9 +73,9 @@ public: // Take ownership of the operation object. resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); - if (owner && owner != &o->io_context_impl_) + if (owner && owner != &o->scheduler_) { // The operation is being run on the worker io_context. Time to perform // the resolver operation. @@ -76,7 +89,7 @@ public: o->results_ = results_type::create(o->endpoint_, host_name, service_name); // Pass operation back to main io_context for completion. - o->io_context_impl_.post_deferred_completion(o); + o->scheduler_.post_deferred_completion(o); p.v = p.p = 0; } else @@ -110,8 +123,9 @@ public: private: socket_ops::weak_cancel_token_type cancel_token_; endpoint_type endpoint_; - io_context_impl& io_context_impl_; + scheduler_impl& scheduler_; Handler handler_; + IoExecutor io_executor_; results_type results_; }; diff --git a/boost/asio/detail/resolve_op.hpp b/boost/asio/detail/resolve_op.hpp index fd72994fc5..2be7b196ec 100644 --- a/boost/asio/detail/resolve_op.hpp +++ b/boost/asio/detail/resolve_op.hpp @@ -2,7 +2,7 @@ // detail/resolve_op.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/resolve_query_op.hpp b/boost/asio/detail/resolve_query_op.hpp index 91bdd79654..11d5989671 100644 --- a/boost/asio/detail/resolve_query_op.hpp +++ b/boost/asio/detail/resolve_query_op.hpp @@ -2,7 +2,7 @@ // detail/resolve_query_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,7 +17,6 @@ #include <boost/asio/detail/config.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> #include <boost/asio/ip/basic_resolver_query.hpp> #include <boost/asio/ip/basic_resolver_results.hpp> #include <boost/asio/detail/bind_handler.hpp> @@ -28,13 +27,19 @@ #include <boost/asio/detail/resolve_op.hpp> #include <boost/asio/detail/socket_ops.hpp> +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) + #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { namespace detail { -template <typename Protocol, typename Handler> +template <typename Protocol, typename Handler, typename IoExecutor> class resolve_query_op : public resolve_op { public: @@ -43,16 +48,24 @@ public: typedef boost::asio::ip::basic_resolver_query<Protocol> query_type; typedef boost::asio::ip::basic_resolver_results<Protocol> results_type; +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + resolve_query_op(socket_ops::weak_cancel_token_type cancel_token, - const query_type& query, io_context_impl& ioc, Handler& handler) + const query_type& query, scheduler_impl& sched, + Handler& handler, const IoExecutor& io_ex) : resolve_op(&resolve_query_op::do_complete), cancel_token_(cancel_token), query_(query), - io_context_impl_(ioc), + scheduler_(sched), handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex), addrinfo_(0) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } ~resolve_query_op() @@ -69,7 +82,7 @@ public: resolve_query_op* o(static_cast<resolve_query_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - if (owner && owner != &o->io_context_impl_) + if (owner && owner != &o->scheduler_) { // The operation is being run on the worker io_context. Time to perform // the resolver operation. @@ -80,7 +93,7 @@ public: o->query_.hints(), &o->addrinfo_, o->ec_); // Pass operation back to main io_context for completion. - o->io_context_impl_.post_deferred_completion(o); + o->scheduler_.post_deferred_completion(o); p.v = p.p = 0; } else @@ -89,7 +102,7 @@ public: // handler is ready to be delivered. // Take ownership of the operation's outstanding work. - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -122,8 +135,9 @@ public: private: socket_ops::weak_cancel_token_type cancel_token_; query_type query_; - io_context_impl& io_context_impl_; + scheduler_impl& scheduler_; Handler handler_; + IoExecutor io_executor_; boost::asio::detail::addrinfo_type* addrinfo_; }; diff --git a/boost/asio/detail/resolver_service.hpp b/boost/asio/detail/resolver_service.hpp index 85c9c2a0a7..744b75ca46 100644 --- a/boost/asio/detail/resolver_service.hpp +++ b/boost/asio/detail/resolver_service.hpp @@ -2,7 +2,7 @@ // detail/resolver_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,7 +35,7 @@ namespace detail { template <typename Protocol> class resolver_service : - public service_base<resolver_service<Protocol> >, + public execution_context_service_base<resolver_service<Protocol> >, public resolver_service_base { public: @@ -53,9 +53,9 @@ public: typedef boost::asio::ip::basic_resolver_results<Protocol> results_type; // Constructor. - resolver_service(boost::asio::io_context& io_context) - : service_base<resolver_service<Protocol> >(io_context), - resolver_service_base(io_context) + resolver_service(execution_context& context) + : execution_context_service_base<resolver_service<Protocol> >(context), + resolver_service_base(context) { } @@ -66,7 +66,7 @@ public: } // Perform any fork-related housekeeping. - void notify_fork(boost::asio::io_context::fork_event fork_ev) + void notify_fork(execution_context::fork_event fork_ev) { this->base_notify_fork(fork_ev); } @@ -86,17 +86,17 @@ public: } // Asynchronously resolve a query to a list of entries. - template <typename Handler> - void async_resolve(implementation_type& impl, - const query_type& query, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_resolve(implementation_type& impl, const query_type& query, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef resolve_query_op<Protocol, Handler> op; + typedef resolve_query_op<Protocol, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl, query, io_context_impl_, handler); + p.p = new (p.v) op(impl, query, scheduler_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_impl_.context(), + BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "resolver", &impl, 0, "async_resolve")); start_resolve_op(p.p); @@ -118,17 +118,17 @@ public: } // Asynchronously resolve an endpoint to a list of entries. - template <typename Handler> - void async_resolve(implementation_type& impl, - const endpoint_type& endpoint, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_resolve(implementation_type& impl, const endpoint_type& endpoint, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef resolve_endpoint_op<Protocol, Handler> op; + typedef resolve_endpoint_op<Protocol, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl, endpoint, io_context_impl_, handler); + p.p = new (p.v) op(impl, endpoint, scheduler_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_impl_.context(), + BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "resolver", &impl, 0, "async_resolve")); start_resolve_op(p.p); diff --git a/boost/asio/detail/resolver_service_base.hpp b/boost/asio/detail/resolver_service_base.hpp index 40adca655a..8e1ff5bea8 100644 --- a/boost/asio/detail/resolver_service_base.hpp +++ b/boost/asio/detail/resolver_service_base.hpp @@ -2,7 +2,7 @@ // detail/resolver_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,8 +17,7 @@ #include <boost/asio/detail/config.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/executor_work_guard.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/detail/mutex.hpp> #include <boost/asio/detail/noncopyable.hpp> #include <boost/asio/detail/resolve_op.hpp> @@ -27,6 +26,12 @@ #include <boost/asio/detail/scoped_ptr.hpp> #include <boost/asio/detail/thread.hpp> +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) + #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -41,7 +46,7 @@ public: typedef socket_ops::shared_cancel_token_type implementation_type; // Constructor. - BOOST_ASIO_DECL resolver_service_base(boost::asio::io_context& io_context); + BOOST_ASIO_DECL resolver_service_base(execution_context& context); // Destructor. BOOST_ASIO_DECL ~resolver_service_base(); @@ -51,7 +56,7 @@ public: // Perform any fork-related housekeeping. BOOST_ASIO_DECL void base_notify_fork( - boost::asio::io_context::fork_event fork_ev); + execution_context::fork_event fork_ev); // Construct a new resolver implementation. BOOST_ASIO_DECL void construct(implementation_type& impl); @@ -102,28 +107,26 @@ protected: }; #endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) - // Helper class to run the work io_context in a thread. - class work_io_context_runner; + // Helper class to run the work scheduler in a thread. + class work_scheduler_runner; - // Start the work thread if it's not already running. + // Start the work scheduler if it's not already running. BOOST_ASIO_DECL void start_work_thread(); - // The io_context implementation used to post completions. - io_context_impl& io_context_impl_; + // The scheduler implementation used to post completions. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + scheduler_impl& scheduler_; private: // Mutex to protect access to internal data. boost::asio::detail::mutex mutex_; - // Private io_context used for performing asynchronous host resolution. - boost::asio::detail::scoped_ptr<boost::asio::io_context> work_io_context_; - - // The work io_context implementation used to post completions. - io_context_impl& work_io_context_impl_; - - // Work for the private io_context to perform. - boost::asio::executor_work_guard< - boost::asio::io_context::executor_type> work_; + // Private scheduler used for performing asynchronous host resolution. + boost::asio::detail::scoped_ptr<scheduler_impl> work_scheduler_; // Thread used for running the work io_context's run loop. boost::asio::detail::scoped_ptr<boost::asio::detail::thread> work_thread_; diff --git a/boost/asio/detail/scheduler.hpp b/boost/asio/detail/scheduler.hpp index 835e4c9237..e3861818d4 100644 --- a/boost/asio/detail/scheduler.hpp +++ b/boost/asio/detail/scheduler.hpp @@ -2,7 +2,7 @@ // detail/scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -25,6 +25,7 @@ #include <boost/asio/detail/op_queue.hpp> #include <boost/asio/detail/reactor_fwd.hpp> #include <boost/asio/detail/scheduler_operation.hpp> +#include <boost/asio/detail/thread.hpp> #include <boost/asio/detail/thread_context.hpp> #include <boost/asio/detail/push_options.hpp> @@ -45,7 +46,10 @@ public: // Constructor. Specifies the number of concurrent threads that are likely to // run the scheduler. If set to 1 certain optimisation are performed. BOOST_ASIO_DECL scheduler(boost::asio::execution_context& ctx, - int concurrency_hint = 0); + int concurrency_hint = 0, bool own_thread = true); + + // Destructor. + BOOST_ASIO_DECL ~scheduler(); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void shutdown(); @@ -157,6 +161,10 @@ private: BOOST_ASIO_DECL void wake_one_thread_and_unlock( mutex::scoped_lock& lock); + // Helper class to run the scheduler in its own thread. + class thread_function; + friend class thread_function; + // Helper class to perform task-related operations on block exit. struct task_cleanup; friend struct task_cleanup; @@ -200,6 +208,9 @@ private: // The concurrency hint used to initialise the scheduler. const int concurrency_hint_; + + // The thread that is running the scheduler. + boost::asio::detail::thread* thread_; }; } // namespace detail diff --git a/boost/asio/detail/scheduler_operation.hpp b/boost/asio/detail/scheduler_operation.hpp index 633a8c594f..df6237f48c 100644 --- a/boost/asio/detail/scheduler_operation.hpp +++ b/boost/asio/detail/scheduler_operation.hpp @@ -2,7 +2,7 @@ // detail/scheduler_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/scheduler_thread_info.hpp b/boost/asio/detail/scheduler_thread_info.hpp index 5f18381d50..f9b556ab8f 100644 --- a/boost/asio/detail/scheduler_thread_info.hpp +++ b/boost/asio/detail/scheduler_thread_info.hpp @@ -2,7 +2,7 @@ // detail/scheduler_thread_info.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/scoped_lock.hpp b/boost/asio/detail/scoped_lock.hpp index 005585c700..74239297ed 100644 --- a/boost/asio/detail/scoped_lock.hpp +++ b/boost/asio/detail/scoped_lock.hpp @@ -2,7 +2,7 @@ // detail/scoped_lock.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/scoped_ptr.hpp b/boost/asio/detail/scoped_ptr.hpp index 12ad834919..707be722f3 100644 --- a/boost/asio/detail/scoped_ptr.hpp +++ b/boost/asio/detail/scoped_ptr.hpp @@ -2,7 +2,7 @@ // detail/scoped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/select_interrupter.hpp b/boost/asio/detail/select_interrupter.hpp index d837634e89..0c2dd91216 100644 --- a/boost/asio/detail/select_interrupter.hpp +++ b/boost/asio/detail/select_interrupter.hpp @@ -2,7 +2,7 @@ // detail/select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/select_reactor.hpp b/boost/asio/detail/select_reactor.hpp index dfb5e96943..435ce0463f 100644 --- a/boost/asio/detail/select_reactor.hpp +++ b/boost/asio/detail/select_reactor.hpp @@ -2,7 +2,7 @@ // detail/select_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/service_registry.hpp b/boost/asio/detail/service_registry.hpp index 894fdb1b75..35140efef1 100644 --- a/boost/asio/detail/service_registry.hpp +++ b/boost/asio/detail/service_registry.hpp @@ -2,7 +2,7 @@ // detail/service_registry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/signal_blocker.hpp b/boost/asio/detail/signal_blocker.hpp index 875f188f48..9f5b6f5225 100644 --- a/boost/asio/detail/signal_blocker.hpp +++ b/boost/asio/detail/signal_blocker.hpp @@ -2,7 +2,7 @@ // detail/signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/signal_handler.hpp b/boost/asio/detail/signal_handler.hpp index 2045db2188..3796c3b63a 100644 --- a/boost/asio/detail/signal_handler.hpp +++ b/boost/asio/detail/signal_handler.hpp @@ -2,7 +2,7 @@ // detail/signal_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -30,17 +30,18 @@ namespace boost { namespace asio { namespace detail { -template <typename Handler> +template <typename Handler, typename IoExecutor> class signal_handler : public signal_op { public: BOOST_ASIO_DEFINE_HANDLER_PTR(signal_handler); - signal_handler(Handler& h) + signal_handler(Handler& h, const IoExecutor& io_ex) : signal_op(&signal_handler::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(h)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(h)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -50,7 +51,7 @@ public: // Take ownership of the handler object. signal_handler* h(static_cast<signal_handler*>(base)); ptr p = { boost::asio::detail::addressof(h->handler_), h, h }; - handler_work<Handler> w(h->handler_); + handler_work<Handler, IoExecutor> w(h->handler_, h->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*h)); @@ -77,6 +78,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/signal_init.hpp b/boost/asio/detail/signal_init.hpp index 1889de689b..9fb87e5987 100644 --- a/boost/asio/detail/signal_init.hpp +++ b/boost/asio/detail/signal_init.hpp @@ -2,7 +2,7 @@ // detail/signal_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/signal_op.hpp b/boost/asio/detail/signal_op.hpp index 74cc68290d..d7719f4cfd 100644 --- a/boost/asio/detail/signal_op.hpp +++ b/boost/asio/detail/signal_op.hpp @@ -2,7 +2,7 @@ // detail/signal_op.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/signal_set_service.hpp b/boost/asio/detail/signal_set_service.hpp index 17ae44ea37..baaf856349 100644 --- a/boost/asio/detail/signal_set_service.hpp +++ b/boost/asio/detail/signal_set_service.hpp @@ -2,7 +2,7 @@ // detail/signal_set_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -20,7 +20,7 @@ #include <cstddef> #include <signal.h> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/detail/handler_alloc_helpers.hpp> #include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/op_queue.hpp> @@ -28,6 +28,12 @@ #include <boost/asio/detail/signal_op.hpp> #include <boost/asio/detail/socket_types.hpp> +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) + #if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) # include <boost/asio/detail/reactor.hpp> #endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) @@ -49,7 +55,7 @@ extern BOOST_ASIO_DECL struct signal_state* get_signal_state(); extern "C" BOOST_ASIO_DECL void boost_asio_signal_handler(int signal_number); class signal_set_service : - public service_base<signal_set_service> + public execution_context_service_base<signal_set_service> { public: // Type used for tracking an individual signal registration. @@ -110,7 +116,7 @@ public: }; // Constructor. - BOOST_ASIO_DECL signal_set_service(boost::asio::io_context& io_context); + BOOST_ASIO_DECL signal_set_service(execution_context& context); // Destructor. BOOST_ASIO_DECL ~signal_set_service(); @@ -120,7 +126,7 @@ public: // Perform fork-related housekeeping. BOOST_ASIO_DECL void notify_fork( - boost::asio::io_context::fork_event fork_ev); + boost::asio::execution_context::fork_event fork_ev); // Construct a new signal_set implementation. BOOST_ASIO_DECL void construct(implementation_type& impl); @@ -145,16 +151,17 @@ public: boost::system::error_code& ec); // Start an asynchronous operation to wait for a signal to be delivered. - template <typename Handler> - void async_wait(implementation_type& impl, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_wait(implementation_type& impl, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef signal_handler<Handler> op; + typedef signal_handler<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_.context(), + BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "signal_set", &impl, 0, "async_wait")); start_wait_op(impl, p.p); @@ -180,8 +187,13 @@ private: // Helper function to start a wait operation. BOOST_ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op); - // The io_context instance used for dispatching handlers. - io_context_impl& io_context_; + // The scheduler used for dispatching handlers. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + scheduler_impl& scheduler_; #if !defined(BOOST_ASIO_WINDOWS) \ && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ diff --git a/boost/asio/detail/socket_holder.hpp b/boost/asio/detail/socket_holder.hpp index b229f66b1b..c96e98297c 100644 --- a/boost/asio/detail/socket_holder.hpp +++ b/boost/asio/detail/socket_holder.hpp @@ -2,7 +2,7 @@ // detail/socket_holder.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/socket_ops.hpp b/boost/asio/detail/socket_ops.hpp index 8f5fa0b3ca..506a06d776 100644 --- a/boost/asio/detail/socket_ops.hpp +++ b/boost/asio/detail/socket_ops.hpp @@ -2,7 +2,7 @@ // detail/socket_ops.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/socket_option.hpp b/boost/asio/detail/socket_option.hpp index bd940142ca..8a77b1229b 100644 --- a/boost/asio/detail/socket_option.hpp +++ b/boost/asio/detail/socket_option.hpp @@ -2,7 +2,7 @@ // detail/socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/socket_select_interrupter.hpp b/boost/asio/detail/socket_select_interrupter.hpp index dc7e30d69b..fc812701d7 100644 --- a/boost/asio/detail/socket_select_interrupter.hpp +++ b/boost/asio/detail/socket_select_interrupter.hpp @@ -2,7 +2,7 @@ // detail/socket_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/socket_types.hpp b/boost/asio/detail/socket_types.hpp index 11ed551838..867caa5845 100644 --- a/boost/asio/detail/socket_types.hpp +++ b/boost/asio/detail/socket_types.hpp @@ -2,7 +2,7 @@ // detail/socket_types.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/solaris_fenced_block.hpp b/boost/asio/detail/solaris_fenced_block.hpp index 3b605daf39..aa7fca3303 100644 --- a/boost/asio/detail/solaris_fenced_block.hpp +++ b/boost/asio/detail/solaris_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/solaris_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/static_mutex.hpp b/boost/asio/detail/static_mutex.hpp index 1bc5c2c813..b6194e400d 100644 --- a/boost/asio/detail/static_mutex.hpp +++ b/boost/asio/detail/static_mutex.hpp @@ -2,7 +2,7 @@ // detail/static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/std_event.hpp b/boost/asio/detail/std_event.hpp index d32bff422e..9532ec9f95 100644 --- a/boost/asio/detail/std_event.hpp +++ b/boost/asio/detail/std_event.hpp @@ -2,7 +2,7 @@ // detail/std_event.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/std_fenced_block.hpp b/boost/asio/detail/std_fenced_block.hpp index 3993199145..2d87752079 100644 --- a/boost/asio/detail/std_fenced_block.hpp +++ b/boost/asio/detail/std_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/std_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/std_global.hpp b/boost/asio/detail/std_global.hpp index f9df646bc6..1c19afe13c 100644 --- a/boost/asio/detail/std_global.hpp +++ b/boost/asio/detail/std_global.hpp @@ -2,7 +2,7 @@ // detail/std_global.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/std_mutex.hpp b/boost/asio/detail/std_mutex.hpp index 463735b92a..7bd17cb00f 100644 --- a/boost/asio/detail/std_mutex.hpp +++ b/boost/asio/detail/std_mutex.hpp @@ -2,7 +2,7 @@ // detail/std_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/std_static_mutex.hpp b/boost/asio/detail/std_static_mutex.hpp index 16104bcfa6..9b0581ee59 100644 --- a/boost/asio/detail/std_static_mutex.hpp +++ b/boost/asio/detail/std_static_mutex.hpp @@ -2,7 +2,7 @@ // detail/std_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/std_thread.hpp b/boost/asio/detail/std_thread.hpp index af507ed32f..314a06cae5 100644 --- a/boost/asio/detail/std_thread.hpp +++ b/boost/asio/detail/std_thread.hpp @@ -2,7 +2,7 @@ // detail/std_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/strand_executor_service.hpp b/boost/asio/detail/strand_executor_service.hpp index c3e68408dc..4fc9327ecd 100644 --- a/boost/asio/detail/strand_executor_service.hpp +++ b/boost/asio/detail/strand_executor_service.hpp @@ -2,7 +2,7 @@ // detail/strand_executor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/strand_service.hpp b/boost/asio/detail/strand_service.hpp index f036264b95..14271c4e4e 100644 --- a/boost/asio/detail/strand_service.hpp +++ b/boost/asio/detail/strand_service.hpp @@ -2,7 +2,7 @@ // detail/strand_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/string_view.hpp b/boost/asio/detail/string_view.hpp index f74d730c0b..07080c1e7c 100644 --- a/boost/asio/detail/string_view.hpp +++ b/boost/asio/detail/string_view.hpp @@ -2,7 +2,7 @@ // detail/string_view.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/thread.hpp b/boost/asio/detail/thread.hpp index 41810c6477..a888d52dd2 100644 --- a/boost/asio/detail/thread.hpp +++ b/boost/asio/detail/thread.hpp @@ -2,7 +2,7 @@ // detail/thread.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/thread_context.hpp b/boost/asio/detail/thread_context.hpp index b4a2435f0f..2005a0d76b 100644 --- a/boost/asio/detail/thread_context.hpp +++ b/boost/asio/detail/thread_context.hpp @@ -2,7 +2,7 @@ // detail/thread_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/thread_group.hpp b/boost/asio/detail/thread_group.hpp index c9c194142f..c6a4a99773 100644 --- a/boost/asio/detail/thread_group.hpp +++ b/boost/asio/detail/thread_group.hpp @@ -2,7 +2,7 @@ // detail/thread_group.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -65,6 +65,12 @@ public: } } + // Test whether the group is empty. + bool empty() const + { + return first_ == 0; + } + private: // Structure used to track a single thread in the group. struct item diff --git a/boost/asio/detail/thread_info_base.hpp b/boost/asio/detail/thread_info_base.hpp index 16bb1787f3..6b7a20c5ed 100644 --- a/boost/asio/detail/thread_info_base.hpp +++ b/boost/asio/detail/thread_info_base.hpp @@ -2,7 +2,7 @@ // detail/thread_info_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -34,11 +34,16 @@ public: enum { mem_index = 0 }; }; - struct awaitee_tag + struct awaitable_frame_tag { enum { mem_index = 1 }; }; + struct executor_function_tag + { + enum { mem_index = 2 }; + }; + thread_info_base() { for (int i = 0; i < max_mem_index; ++i) @@ -110,7 +115,7 @@ public: private: enum { chunk_size = 4 }; - enum { max_mem_index = 2 }; + enum { max_mem_index = 3 }; void* reusable_memory_[max_mem_index]; }; diff --git a/boost/asio/detail/throw_error.hpp b/boost/asio/detail/throw_error.hpp index c1775b2536..d31c859876 100644 --- a/boost/asio/detail/throw_error.hpp +++ b/boost/asio/detail/throw_error.hpp @@ -2,7 +2,7 @@ // detail/throw_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/throw_exception.hpp b/boost/asio/detail/throw_exception.hpp index 8690fa6f63..6190419f55 100644 --- a/boost/asio/detail/throw_exception.hpp +++ b/boost/asio/detail/throw_exception.hpp @@ -2,7 +2,7 @@ // detail/throw_exception.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/timer_queue.hpp b/boost/asio/detail/timer_queue.hpp index 3b2bcff774..9ce6995b73 100644 --- a/boost/asio/detail/timer_queue.hpp +++ b/boost/asio/detail/timer_queue.hpp @@ -2,7 +2,7 @@ // detail/timer_queue.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/timer_queue_base.hpp b/boost/asio/detail/timer_queue_base.hpp index f3a14238aa..c95a2a520c 100644 --- a/boost/asio/detail/timer_queue_base.hpp +++ b/boost/asio/detail/timer_queue_base.hpp @@ -2,7 +2,7 @@ // detail/timer_queue_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/timer_queue_ptime.hpp b/boost/asio/detail/timer_queue_ptime.hpp index cc053bff9d..d803befb9f 100644 --- a/boost/asio/detail/timer_queue_ptime.hpp +++ b/boost/asio/detail/timer_queue_ptime.hpp @@ -2,7 +2,7 @@ // detail/timer_queue_ptime.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/timer_queue_set.hpp b/boost/asio/detail/timer_queue_set.hpp index 2bed122fc2..9b25e20892 100644 --- a/boost/asio/detail/timer_queue_set.hpp +++ b/boost/asio/detail/timer_queue_set.hpp @@ -2,7 +2,7 @@ // detail/timer_queue_set.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/timer_scheduler.hpp b/boost/asio/detail/timer_scheduler.hpp index dc6e8d890c..9d68a602c4 100644 --- a/boost/asio/detail/timer_scheduler.hpp +++ b/boost/asio/detail/timer_scheduler.hpp @@ -2,7 +2,7 @@ // detail/timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/timer_scheduler_fwd.hpp b/boost/asio/detail/timer_scheduler_fwd.hpp index c3656c66a0..0675edf83a 100644 --- a/boost/asio/detail/timer_scheduler_fwd.hpp +++ b/boost/asio/detail/timer_scheduler_fwd.hpp @@ -2,7 +2,7 @@ // detail/timer_scheduler_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/tss_ptr.hpp b/boost/asio/detail/tss_ptr.hpp index 7850718a3c..a7c87d2103 100644 --- a/boost/asio/detail/tss_ptr.hpp +++ b/boost/asio/detail/tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/type_traits.hpp b/boost/asio/detail/type_traits.hpp index a0d4cb4902..c53a7e745c 100644 --- a/boost/asio/detail/type_traits.hpp +++ b/boost/asio/detail/type_traits.hpp @@ -2,7 +2,7 @@ // detail/type_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/variadic_templates.hpp b/boost/asio/detail/variadic_templates.hpp index c358feec18..f552b4b026 100644 --- a/boost/asio/detail/variadic_templates.hpp +++ b/boost/asio/detail/variadic_templates.hpp @@ -2,7 +2,7 @@ // detail/variadic_templates.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -58,6 +58,20 @@ # define BOOST_ASIO_VARIADIC_BYVAL_ARGS_4 x1, x2, x3, x4 # define BOOST_ASIO_VARIADIC_BYVAL_ARGS_5 x1, x2, x3, x4, x5 +# define BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n) \ + BOOST_ASIO_VARIADIC_CONSTREF_PARAMS_##n + +# define BOOST_ASIO_VARIADIC_CONSTREF_PARAMS_1 \ + const T1& x1 +# define BOOST_ASIO_VARIADIC_CONSTREF_PARAMS_2 \ + const T1& x1, const T2& x2 +# define BOOST_ASIO_VARIADIC_CONSTREF_PARAMS_3 \ + const T1& x1, const T2& x2, const T3& x3 +# define BOOST_ASIO_VARIADIC_CONSTREF_PARAMS_4 \ + const T1& x1, const T2& x2, const T3& x3, const T4& x4 +# define BOOST_ASIO_VARIADIC_CONSTREF_PARAMS_5 \ + const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5 + # define BOOST_ASIO_VARIADIC_MOVE_PARAMS(n) \ BOOST_ASIO_VARIADIC_MOVE_PARAMS_##n diff --git a/boost/asio/detail/wait_handler.hpp b/boost/asio/detail/wait_handler.hpp index a9341244f8..b94773467e 100644 --- a/boost/asio/detail/wait_handler.hpp +++ b/boost/asio/detail/wait_handler.hpp @@ -2,7 +2,7 @@ // detail/wait_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -19,9 +19,9 @@ #include <boost/asio/detail/fenced_block.hpp> #include <boost/asio/detail/handler_alloc_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> +#include <boost/asio/detail/handler_work.hpp> #include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/wait_op.hpp> -#include <boost/asio/io_context.hpp> #include <boost/asio/detail/push_options.hpp> @@ -29,17 +29,18 @@ namespace boost { namespace asio { namespace detail { -template <typename Handler> +template <typename Handler, typename IoExecutor> class wait_handler : public wait_op { public: BOOST_ASIO_DEFINE_HANDLER_PTR(wait_handler); - wait_handler(Handler& h) + wait_handler(Handler& h, const IoExecutor& ex) : wait_op(&wait_handler::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(h)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(h)), + io_executor_(ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -49,7 +50,7 @@ public: // Take ownership of the handler object. wait_handler* h(static_cast<wait_handler*>(base)); ptr p = { boost::asio::detail::addressof(h->handler_), h, h }; - handler_work<Handler> w(h->handler_); + handler_work<Handler, IoExecutor> w(h->handler_, h->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*h)); @@ -76,6 +77,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/wait_op.hpp b/boost/asio/detail/wait_op.hpp index 3a95a37580..a6b88f6e35 100644 --- a/boost/asio/detail/wait_op.hpp +++ b/boost/asio/detail/wait_op.hpp @@ -2,7 +2,7 @@ // detail/wait_op.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_event.hpp b/boost/asio/detail/win_event.hpp index 67edbcfb89..08de010af4 100644 --- a/boost/asio/detail/win_event.hpp +++ b/boost/asio/detail/win_event.hpp @@ -2,7 +2,7 @@ // detail/win_event.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_fd_set_adapter.hpp b/boost/asio/detail/win_fd_set_adapter.hpp index bdddb32a9d..3f66d4af33 100644 --- a/boost/asio/detail/win_fd_set_adapter.hpp +++ b/boost/asio/detail/win_fd_set_adapter.hpp @@ -2,7 +2,7 @@ // detail/win_fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_fenced_block.hpp b/boost/asio/detail/win_fenced_block.hpp index c595eaa00f..42aee2d774 100644 --- a/boost/asio/detail/win_fenced_block.hpp +++ b/boost/asio/detail/win_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/win_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_global.hpp b/boost/asio/detail/win_global.hpp index 11204dec6d..1165579baa 100644 --- a/boost/asio/detail/win_global.hpp +++ b/boost/asio/detail/win_global.hpp @@ -2,7 +2,7 @@ // detail/win_global.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -36,7 +36,7 @@ struct win_global_impl static win_global_impl instance_; static static_mutex mutex_; - static T* ptr_; + T* ptr_; static tss_ptr<T> tss_ptr_; }; @@ -47,9 +47,6 @@ template <typename T> static_mutex win_global_impl<T>::mutex_ = BOOST_ASIO_STATIC_MUTEX_INIT; template <typename T> -T* win_global_impl<T>::ptr_ = 0; - -template <typename T> tss_ptr<T> win_global_impl<T>::tss_ptr_; template <typename T> @@ -59,9 +56,9 @@ T& win_global() { win_global_impl<T>::mutex_.init(); static_mutex::scoped_lock lock(win_global_impl<T>::mutex_); - if (win_global_impl<T>::ptr_ == 0) - win_global_impl<T>::ptr_ = new T; - win_global_impl<T>::tss_ptr_ = win_global_impl<T>::ptr_; + if (win_global_impl<T>::instance_.ptr_ == 0) + win_global_impl<T>::instance_.ptr_ = new T; + win_global_impl<T>::tss_ptr_ = win_global_impl<T>::instance_.ptr_; } return *win_global_impl<T>::tss_ptr_; diff --git a/boost/asio/detail/win_iocp_handle_read_op.hpp b/boost/asio/detail/win_iocp_handle_read_op.hpp index 842ed80b73..04675ab9a4 100644 --- a/boost/asio/detail/win_iocp_handle_read_op.hpp +++ b/boost/asio/detail/win_iocp_handle_read_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_handle_read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -35,19 +35,20 @@ namespace boost { namespace asio { namespace detail { -template <typename MutableBufferSequence, typename Handler> +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> class win_iocp_handle_read_op : public operation { public: BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_read_op); - win_iocp_handle_read_op( - const MutableBufferSequence& buffers, Handler& handler) + win_iocp_handle_read_op(const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_handle_read_op::do_complete), buffers_(buffers), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -59,7 +60,7 @@ public: // Take ownership of the operation object. win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -100,6 +101,7 @@ public: private: MutableBufferSequence buffers_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_handle_service.hpp b/boost/asio/detail/win_iocp_handle_service.hpp index 4d5aadeef5..92aa8e88ca 100644 --- a/boost/asio/detail/win_iocp_handle_service.hpp +++ b/boost/asio/detail/win_iocp_handle_service.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_handle_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -21,7 +21,7 @@ #if defined(BOOST_ASIO_HAS_IOCP) #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> #include <boost/asio/detail/cstdint.hpp> #include <boost/asio/detail/handler_alloc_helpers.hpp> @@ -39,7 +39,7 @@ namespace asio { namespace detail { class win_iocp_handle_service : - public service_base<win_iocp_handle_service> + public execution_context_service_base<win_iocp_handle_service> { public: // The native type of a stream handle. @@ -76,7 +76,7 @@ public: implementation_type* prev_; }; - BOOST_ASIO_DECL win_iocp_handle_service(boost::asio::io_context& io_context); + BOOST_ASIO_DECL win_iocp_handle_service(execution_context& context); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void shutdown(); @@ -143,15 +143,17 @@ public: // Start an asynchronous write. The data being written must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, Handler& handler) + const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op; + typedef win_iocp_handle_write_op< + ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(buffers, handler); + p.p = new (p.v) op(buffers, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl, reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some")); @@ -164,15 +166,17 @@ public: // Start an asynchronous write at a specified offset. The data being written // must be valid for the lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> - void async_write_some_at(implementation_type& impl, uint64_t offset, - const ConstBufferSequence& buffers, Handler& handler) + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_write_some_at(implementation_type& impl, + uint64_t offset, const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op; + typedef win_iocp_handle_write_op< + ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(buffers, handler); + p.p = new (p.v) op(buffers, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl, reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some_at")); @@ -205,15 +209,18 @@ public: // Start an asynchronous read. The buffer for the data being received must be // valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, Handler& handler) + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op; + typedef win_iocp_handle_read_op< + MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(buffers, handler); + p.p = new (p.v) op(buffers, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl, reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some")); @@ -227,15 +234,18 @@ public: // Start an asynchronous read at a specified offset. The buffer for the data // being received must be valid for the lifetime of the asynchronous // operation. - template <typename MutableBufferSequence, typename Handler> - void async_read_some_at(implementation_type& impl, uint64_t offset, - const MutableBufferSequence& buffers, Handler& handler) + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_read_some_at(implementation_type& impl, + uint64_t offset, const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op; + typedef win_iocp_handle_read_op< + MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(buffers, handler); + p.p = new (p.v) op(buffers, handler, io_ex); BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl, reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some_at")); @@ -252,22 +262,24 @@ private: const null_buffers& buffers, boost::system::error_code& ec); size_t write_some_at(implementation_type& impl, uint64_t offset, const null_buffers& buffers, boost::system::error_code& ec); - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_write_some(implementation_type& impl, - const null_buffers& buffers, Handler& handler); - template <typename Handler> + const null_buffers& buffers, Handler& handler, + const IoExecutor& io_ex); + template <typename Handler, typename IoExecutor> void async_write_some_at(implementation_type& impl, uint64_t offset, - const null_buffers& buffers, Handler& handler); + const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex); size_t read_some(implementation_type& impl, const null_buffers& buffers, boost::system::error_code& ec); size_t read_some_at(implementation_type& impl, uint64_t offset, const null_buffers& buffers, boost::system::error_code& ec); - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_read_some(implementation_type& impl, - const null_buffers& buffers, Handler& handler); - template <typename Handler> + const null_buffers& buffers, Handler& handler, + const IoExecutor& io_ex); + template <typename Handler, typename IoExecutor> void async_read_some_at(implementation_type& impl, uint64_t offset, - const null_buffers& buffers, Handler& handler); + const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex); // Helper class for waiting for synchronous operations to complete. class overlapped_wrapper; diff --git a/boost/asio/detail/win_iocp_handle_write_op.hpp b/boost/asio/detail/win_iocp_handle_write_op.hpp index 582b3f2b82..7e81eb843b 100644 --- a/boost/asio/detail/win_iocp_handle_write_op.hpp +++ b/boost/asio/detail/win_iocp_handle_write_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_handle_write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -35,18 +35,20 @@ namespace boost { namespace asio { namespace detail { -template <typename ConstBufferSequence, typename Handler> +template <typename ConstBufferSequence, typename Handler, typename IoExecutor> class win_iocp_handle_write_op : public operation { public: BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_write_op); - win_iocp_handle_write_op(const ConstBufferSequence& buffers, Handler& handler) + win_iocp_handle_write_op(const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_handle_write_op::do_complete), buffers_(buffers), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -55,7 +57,7 @@ public: // Take ownership of the operation object. win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -92,6 +94,7 @@ public: private: ConstBufferSequence buffers_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_io_context.hpp b/boost/asio/detail/win_iocp_io_context.hpp index 1ccdf35f65..d551b9b27f 100644 --- a/boost/asio/detail/win_iocp_io_context.hpp +++ b/boost/asio/detail/win_iocp_io_context.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_io_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -49,7 +49,10 @@ public: // Constructor. Specifies a concurrency hint that is passed through to the // underlying I/O completion port. BOOST_ASIO_DECL win_iocp_io_context(boost::asio::execution_context& ctx, - int concurrency_hint = -1); + int concurrency_hint = -1, bool own_thread = true); + + // Destructor. + BOOST_ASIO_DECL ~win_iocp_io_context(); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void shutdown(); @@ -288,6 +291,10 @@ private: // Timeout to use with GetQueuedCompletionStatus. const DWORD gqcs_timeout_; + // Helper class to run the scheduler in its own thread. + struct thread_function; + friend struct thread_function; + // Function object for processing timeouts in a background thread. struct timer_thread_function; friend struct timer_thread_function; @@ -312,6 +319,9 @@ private: // The concurrency hint used to initialise the io_context. const int concurrency_hint_; + + // The thread that is running the io_context. + scoped_ptr<thread> thread_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_null_buffers_op.hpp b/boost/asio/detail/win_iocp_null_buffers_op.hpp index 106bedeba0..c32163987f 100644 --- a/boost/asio/detail/win_iocp_null_buffers_op.hpp +++ b/boost/asio/detail/win_iocp_null_buffers_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_null_buffers_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,20 +35,21 @@ namespace boost { namespace asio { namespace detail { -template <typename Handler> +template <typename Handler, typename IoExecutor> class win_iocp_null_buffers_op : public reactor_op { public: BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_null_buffers_op); win_iocp_null_buffers_op(socket_ops::weak_cancel_token_type cancel_token, - Handler& handler) + Handler& handler, const IoExecutor& io_ex) : reactor_op(&win_iocp_null_buffers_op::do_perform, &win_iocp_null_buffers_op::do_complete), cancel_token_(cancel_token), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static status do_perform(reactor_op*) @@ -65,7 +66,7 @@ public: // Take ownership of the operation object. win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -110,6 +111,7 @@ public: private: socket_ops::weak_cancel_token_type cancel_token_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_operation.hpp b/boost/asio/detail/win_iocp_operation.hpp index 11111f3150..5cad6e338c 100644 --- a/boost/asio/detail/win_iocp_operation.hpp +++ b/boost/asio/detail/win_iocp_operation.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_iocp_overlapped_op.hpp b/boost/asio/detail/win_iocp_overlapped_op.hpp index 18f0d63173..c36e764a11 100644 --- a/boost/asio/detail/win_iocp_overlapped_op.hpp +++ b/boost/asio/detail/win_iocp_overlapped_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_overlapped_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -33,17 +33,18 @@ namespace boost { namespace asio { namespace detail { -template <typename Handler> +template <typename Handler, typename IoExecutor> class win_iocp_overlapped_op : public operation { public: BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_overlapped_op); - win_iocp_overlapped_op(Handler& handler) + win_iocp_overlapped_op(Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_overlapped_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -52,7 +53,7 @@ public: // Take ownership of the operation object. win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -79,6 +80,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_overlapped_ptr.hpp b/boost/asio/detail/win_iocp_overlapped_ptr.hpp index 6cff7ae1d4..d1ed1cb1a0 100644 --- a/boost/asio/detail/win_iocp_overlapped_ptr.hpp +++ b/boost/asio/detail/win_iocp_overlapped_ptr.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_overlapped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,6 +21,7 @@ #include <boost/asio/io_context.hpp> #include <boost/asio/detail/handler_alloc_helpers.hpp> +#include <boost/asio/detail/io_object_executor.hpp> #include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/noncopyable.hpp> #include <boost/asio/detail/win_iocp_overlapped_op.hpp> @@ -45,13 +46,13 @@ public: } // Construct an win_iocp_overlapped_ptr to contain the specified handler. - template <typename Handler> - explicit win_iocp_overlapped_ptr( - boost::asio::io_context& io_context, BOOST_ASIO_MOVE_ARG(Handler) handler) + template <typename Executor, typename Handler> + explicit win_iocp_overlapped_ptr(const Executor& ex, + BOOST_ASIO_MOVE_ARG(Handler) handler) : ptr_(0), iocp_service_(0) { - this->reset(io_context, BOOST_ASIO_MOVE_CAST(Handler)(handler)); + this->reset(ex, BOOST_ASIO_MOVE_CAST(Handler)(handler)); } // Destructor automatically frees the OVERLAPPED object unless released. @@ -74,22 +75,25 @@ public: // Reset to contain the specified handler, freeing any current OVERLAPPED // object. - template <typename Handler> - void reset(boost::asio::io_context& io_context, Handler handler) + template <typename Executor, typename Handler> + void reset(const Executor& ex, Handler handler) { - typedef win_iocp_overlapped_op<Handler> op; + const bool native = is_same<Executor, io_context::executor_type>::value; + win_iocp_io_context* iocp_service = this->get_iocp_service(ex); + + typedef win_iocp_overlapped_op<Handler, io_object_executor<Executor> > op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_object_executor<Executor>(ex, native)); - BOOST_ASIO_HANDLER_CREATION((io_context, *p.p, - "io_context", &io_context.impl_, 0, "overlapped")); + BOOST_ASIO_HANDLER_CREATION((ex.context(), *p.p, + "iocp_service", iocp_service, 0, "overlapped")); - io_context.impl_.work_started(); + iocp_service->work_started(); reset(); ptr_ = p.p; p.v = p.p = 0; - iocp_service_ = &io_context.impl_; + iocp_service_ = iocp_service; } // Get the contained OVERLAPPED object. @@ -130,6 +134,18 @@ public: } private: + template <typename Executor> + static win_iocp_io_context* get_iocp_service(const Executor& ex) + { + return &use_service<win_iocp_io_context>(ex.context()); + } + + static win_iocp_io_context* get_iocp_service( + const io_context::executor_type& ex) + { + return &ex.context().impl_; + } + win_iocp_operation* ptr_; win_iocp_io_context* iocp_service_; }; diff --git a/boost/asio/detail/win_iocp_serial_port_service.hpp b/boost/asio/detail/win_iocp_serial_port_service.hpp index 3da2537295..6f05d92fc1 100644 --- a/boost/asio/detail/win_iocp_serial_port_service.hpp +++ b/boost/asio/detail/win_iocp_serial_port_service.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_serial_port_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -22,7 +22,7 @@ #include <string> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/detail/win_iocp_handle_service.hpp> #include <boost/asio/detail/push_options.hpp> @@ -33,7 +33,7 @@ namespace detail { // Extend win_iocp_handle_service to provide serial port support. class win_iocp_serial_port_service : - public service_base<win_iocp_serial_port_service> + public execution_context_service_base<win_iocp_serial_port_service> { public: // The native type of a serial port. @@ -43,8 +43,7 @@ public: typedef win_iocp_handle_service::implementation_type implementation_type; // Constructor. - BOOST_ASIO_DECL win_iocp_serial_port_service( - boost::asio::io_context& io_context); + BOOST_ASIO_DECL win_iocp_serial_port_service(execution_context& context); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void shutdown(); @@ -152,11 +151,12 @@ public: // Start an asynchronous write. The data being written must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, Handler& handler) + const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { - handle_service_.async_write_some(impl, buffers, handler); + handle_service_.async_write_some(impl, buffers, handler, io_ex); } // Read some data. Returns the number of bytes received. @@ -169,11 +169,13 @@ public: // Start an asynchronous read. The buffer for the data being received must be // valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, Handler& handler) + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) { - handle_service_.async_read_some(impl, buffers, handler); + handle_service_.async_read_some(impl, buffers, handler, io_ex); } private: diff --git a/boost/asio/detail/win_iocp_socket_accept_op.hpp b/boost/asio/detail/win_iocp_socket_accept_op.hpp index 8e1b7fc93a..75dadc27c1 100644 --- a/boost/asio/detail/win_iocp_socket_accept_op.hpp +++ b/boost/asio/detail/win_iocp_socket_accept_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_accept_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -36,7 +36,8 @@ namespace boost { namespace asio { namespace detail { -template <typename Socket, typename Protocol, typename Handler> +template <typename Socket, typename Protocol, + typename Handler, typename IoExecutor> class win_iocp_socket_accept_op : public operation { public: @@ -45,7 +46,7 @@ public: win_iocp_socket_accept_op(win_iocp_socket_service_base& socket_service, socket_type socket, Socket& peer, const Protocol& protocol, typename Protocol::endpoint* peer_endpoint, - bool enable_connection_aborted, Handler& handler) + bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_socket_accept_op::do_complete), socket_service_(socket_service), socket_(socket), @@ -53,9 +54,10 @@ public: protocol_(protocol), peer_endpoint_(peer_endpoint), enable_connection_aborted_(enable_connection_aborted), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } socket_holder& new_socket() @@ -82,7 +84,7 @@ public: // Take ownership of the operation object. win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); if (owner) { @@ -156,11 +158,13 @@ private: unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; bool enable_connection_aborted_; Handler handler_; + IoExecutor io_executor_; }; #if defined(BOOST_ASIO_HAS_MOVE) -template <typename Protocol, typename Handler> +template <typename Protocol, typename PeerIoExecutor, + typename Handler, typename IoExecutor> class win_iocp_socket_move_accept_op : public operation { public: @@ -168,19 +172,20 @@ public: win_iocp_socket_move_accept_op( win_iocp_socket_service_base& socket_service, socket_type socket, - const Protocol& protocol, boost::asio::io_context& peer_io_context, + const Protocol& protocol, const PeerIoExecutor& peer_io_ex, typename Protocol::endpoint* peer_endpoint, - bool enable_connection_aborted, Handler& handler) + bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_socket_move_accept_op::do_complete), socket_service_(socket_service), socket_(socket), - peer_(peer_io_context), + peer_(peer_io_ex), protocol_(protocol), peer_endpoint_(peer_endpoint), enable_connection_aborted_(enable_connection_aborted), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } socket_holder& new_socket() @@ -208,7 +213,7 @@ public: win_iocp_socket_move_accept_op* o( static_cast<win_iocp_socket_move_accept_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); if (owner) { @@ -258,9 +263,9 @@ public: // to ensure that any owning sub-object remains valid until after we have // deallocated the memory here. detail::move_binder2<Handler, - boost::system::error_code, typename Protocol::socket> + boost::system::error_code, peer_socket_type> handler(0, BOOST_ASIO_MOVE_CAST(Handler)(o->handler_), ec, - BOOST_ASIO_MOVE_CAST(typename Protocol::socket)(o->peer_)); + BOOST_ASIO_MOVE_CAST(peer_socket_type)(o->peer_)); p.h = boost::asio::detail::addressof(handler.handler_); p.reset(); @@ -275,15 +280,19 @@ public: } private: + typedef typename Protocol::socket::template + rebind_executor<PeerIoExecutor>::other peer_socket_type; + win_iocp_socket_service_base& socket_service_; socket_type socket_; socket_holder new_socket_; - typename Protocol::socket peer_; + peer_socket_type peer_; Protocol protocol_; typename Protocol::endpoint* peer_endpoint_; unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; bool enable_connection_aborted_; Handler handler_; + IoExecutor io_executor_; }; #endif // defined(BOOST_ASIO_HAS_MOVE) diff --git a/boost/asio/detail/win_iocp_socket_connect_op.hpp b/boost/asio/detail/win_iocp_socket_connect_op.hpp index 916d22ee49..0041a059ab 100644 --- a/boost/asio/detail/win_iocp_socket_connect_op.hpp +++ b/boost/asio/detail/win_iocp_socket_connect_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -57,18 +57,20 @@ public: bool connect_ex_; }; -template <typename Handler> +template <typename Handler, typename IoExecutor> class win_iocp_socket_connect_op : public win_iocp_socket_connect_op_base { public: BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_connect_op); - win_iocp_socket_connect_op(socket_type socket, Handler& handler) + win_iocp_socket_connect_op(socket_type socket, + Handler& handler, const IoExecutor& io_ex) : win_iocp_socket_connect_op_base(socket, &win_iocp_socket_connect_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -81,7 +83,7 @@ public: win_iocp_socket_connect_op* o( static_cast<win_iocp_socket_connect_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); if (owner) { @@ -116,6 +118,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_socket_recv_op.hpp b/boost/asio/detail/win_iocp_socket_recv_op.hpp index b052ec236e..daa3ca24ec 100644 --- a/boost/asio/detail/win_iocp_socket_recv_op.hpp +++ b/boost/asio/detail/win_iocp_socket_recv_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,7 +35,7 @@ namespace boost { namespace asio { namespace detail { -template <typename MutableBufferSequence, typename Handler> +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> class win_iocp_socket_recv_op : public operation { public: @@ -43,14 +43,16 @@ public: win_iocp_socket_recv_op(socket_ops::state_type state, socket_ops::weak_cancel_token_type cancel_token, - const MutableBufferSequence& buffers, Handler& handler) + const MutableBufferSequence& buffers, Handler& handler, + const IoExecutor& io_ex) : operation(&win_iocp_socket_recv_op::do_complete), state_(state), cancel_token_(cancel_token), buffers_(buffers), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -62,7 +64,7 @@ public: // Take ownership of the operation object. win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -106,6 +108,7 @@ private: socket_ops::weak_cancel_token_type cancel_token_; MutableBufferSequence buffers_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp b/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp index a7338c8877..bfd469a3d0 100644 --- a/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp +++ b/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_recvfrom_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,7 +35,8 @@ namespace boost { namespace asio { namespace detail { -template <typename MutableBufferSequence, typename Endpoint, typename Handler> +template <typename MutableBufferSequence, typename Endpoint, + typename Handler, typename IoExecutor> class win_iocp_socket_recvfrom_op : public operation { public: @@ -43,15 +44,17 @@ public: win_iocp_socket_recvfrom_op(Endpoint& endpoint, socket_ops::weak_cancel_token_type cancel_token, - const MutableBufferSequence& buffers, Handler& handler) + const MutableBufferSequence& buffers, Handler& handler, + const IoExecutor& io_ex) : operation(&win_iocp_socket_recvfrom_op::do_complete), endpoint_(endpoint), endpoint_size_(static_cast<int>(endpoint.capacity())), cancel_token_(cancel_token), buffers_(buffers), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } int& endpoint_size() @@ -69,7 +72,7 @@ public: win_iocp_socket_recvfrom_op* o( static_cast<win_iocp_socket_recvfrom_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -114,6 +117,7 @@ private: socket_ops::weak_cancel_token_type cancel_token_; MutableBufferSequence buffers_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp b/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp index 4a8313225d..73127dca80 100644 --- a/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp +++ b/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_recvmsg_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -36,7 +36,7 @@ namespace boost { namespace asio { namespace detail { -template <typename MutableBufferSequence, typename Handler> +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> class win_iocp_socket_recvmsg_op : public operation { public: @@ -45,14 +45,16 @@ public: win_iocp_socket_recvmsg_op( socket_ops::weak_cancel_token_type cancel_token, const MutableBufferSequence& buffers, - socket_base::message_flags& out_flags, Handler& handler) + socket_base::message_flags& out_flags, + Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_socket_recvmsg_op::do_complete), cancel_token_(cancel_token), buffers_(buffers), out_flags_(out_flags), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -65,7 +67,7 @@ public: win_iocp_socket_recvmsg_op* o( static_cast<win_iocp_socket_recvmsg_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -107,6 +109,7 @@ private: MutableBufferSequence buffers_; socket_base::message_flags& out_flags_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_socket_send_op.hpp b/boost/asio/detail/win_iocp_socket_send_op.hpp index 7dc9ab3175..5f1fc4ad8e 100644 --- a/boost/asio/detail/win_iocp_socket_send_op.hpp +++ b/boost/asio/detail/win_iocp_socket_send_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,20 +35,22 @@ namespace boost { namespace asio { namespace detail { -template <typename ConstBufferSequence, typename Handler> +template <typename ConstBufferSequence, typename Handler, typename IoExecutor> class win_iocp_socket_send_op : public operation { public: BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_send_op); win_iocp_socket_send_op(socket_ops::weak_cancel_token_type cancel_token, - const ConstBufferSequence& buffers, Handler& handler) + const ConstBufferSequence& buffers, Handler& handler, + const IoExecutor& io_ex) : operation(&win_iocp_socket_send_op::do_complete), cancel_token_(cancel_token), buffers_(buffers), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -60,7 +62,7 @@ public: // Take ownership of the operation object. win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -100,6 +102,7 @@ private: socket_ops::weak_cancel_token_type cancel_token_; ConstBufferSequence buffers_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_iocp_socket_service.hpp b/boost/asio/detail/win_iocp_socket_service.hpp index d71c6ee046..df2292a55e 100644 --- a/boost/asio/detail/win_iocp_socket_service.hpp +++ b/boost/asio/detail/win_iocp_socket_service.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,7 +21,7 @@ #include <cstring> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/socket_base.hpp> #include <boost/asio/detail/bind_handler.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> @@ -52,7 +52,7 @@ namespace detail { template <typename Protocol> class win_iocp_socket_service : - public service_base<win_iocp_socket_service<Protocol> >, + public execution_context_service_base<win_iocp_socket_service<Protocol> >, public win_iocp_socket_service_base { public: @@ -130,9 +130,10 @@ public: }; // Constructor. - win_iocp_socket_service(boost::asio::io_context& io_context) - : service_base<win_iocp_socket_service<Protocol> >(io_context), - win_iocp_socket_service_base(io_context) + win_iocp_socket_service(execution_context& context) + : execution_context_service_base< + win_iocp_socket_service<Protocol> >(context), + win_iocp_socket_service_base(context) { } @@ -324,18 +325,20 @@ public: // Start an asynchronous send. The data being sent must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_send_to(implementation_type& impl, const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, Handler& handler) + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op; + typedef win_iocp_socket_send_op< + ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, buffers, handler); + p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_send_to")); buffer_sequence_adapter<boost::asio::const_buffer, @@ -348,17 +351,18 @@ public: } // Start an asynchronous wait until data can be sent without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_send_to(implementation_type& impl, const null_buffers&, - const endpoint_type&, socket_base::message_flags, Handler& handler) + const endpoint_type&, socket_base::message_flags, Handler& handler, + const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_null_buffers_op<Handler> op; + typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, handler); + p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_send_to(null_buffers)")); start_reactor_op(impl, select_reactor::write_op, p.p); @@ -404,19 +408,22 @@ public: // Start an asynchronous receive. The buffer for the data being received and // the sender_endpoint object must both be valid for the lifetime of the // asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive_from(implementation_type& impl, const MutableBufferSequence& buffers, endpoint_type& sender_endp, - socket_base::message_flags flags, Handler& handler) + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_socket_recvfrom_op< - MutableBufferSequence, endpoint_type, Handler> op; + typedef win_iocp_socket_recvfrom_op<MutableBufferSequence, + endpoint_type, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(sender_endp, impl.cancel_token_, buffers, handler); + p.p = new (p.v) op(sender_endp, impl.cancel_token_, + buffers, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive_from")); buffer_sequence_adapter<boost::asio::mutable_buffer, @@ -428,18 +435,18 @@ public: } // Wait until data can be received without blocking. - template <typename Handler> - void async_receive_from(implementation_type& impl, - const null_buffers&, endpoint_type& sender_endpoint, - socket_base::message_flags flags, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_null_buffers_op<Handler> op; + typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, handler); + p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive_from(null_buffers)")); // Reset endpoint since it can be given no sensible value at this time. @@ -479,50 +486,23 @@ public: return ec; } -#if defined(BOOST_ASIO_HAS_MOVE) - // Accept a new connection. - typename Protocol::socket accept(implementation_type& impl, - io_context* peer_io_context, endpoint_type* peer_endpoint, - boost::system::error_code& ec) - { - typename Protocol::socket peer( - peer_io_context ? *peer_io_context : io_context_); - - std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; - socket_holder new_socket(socket_ops::sync_accept(impl.socket_, - impl.state_, peer_endpoint ? peer_endpoint->data() : 0, - peer_endpoint ? &addr_len : 0, ec)); - - // On success, assign new connection to peer socket object. - if (new_socket.get() != invalid_socket) - { - if (peer_endpoint) - peer_endpoint->resize(addr_len); - peer.assign(impl.protocol_, new_socket.get(), ec); - if (!ec) - new_socket.release(); - } - - return peer; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) - // Start an asynchronous accept. The peer and peer_endpoint objects // must be valid until the accept's handler is invoked. - template <typename Socket, typename Handler> + template <typename Socket, typename Handler, typename IoExecutor> void async_accept(implementation_type& impl, Socket& peer, - endpoint_type* peer_endpoint, Handler& handler) + endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_socket_accept_op<Socket, protocol_type, Handler> op; + typedef win_iocp_socket_accept_op<Socket, + protocol_type, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; bool enable_connection_aborted = (impl.state_ & socket_ops::enable_connection_aborted) != 0; p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_, - peer_endpoint, enable_connection_aborted, handler); + peer_endpoint, enable_connection_aborted, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_accept")); start_accept_op(impl, peer.is_open(), p.p->new_socket(), @@ -535,22 +515,23 @@ public: #if defined(BOOST_ASIO_HAS_MOVE) // Start an asynchronous accept. The peer and peer_endpoint objects // must be valid until the accept's handler is invoked. - template <typename Handler> - void async_accept(implementation_type& impl, - boost::asio::io_context* peer_io_context, - endpoint_type* peer_endpoint, Handler& handler) + template <typename PeerIoExecutor, typename Handler, typename IoExecutor> + void async_move_accept(implementation_type& impl, + const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_socket_move_accept_op<protocol_type, Handler> op; + typedef win_iocp_socket_move_accept_op< + protocol_type, PeerIoExecutor, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; bool enable_connection_aborted = (impl.state_ & socket_ops::enable_connection_aborted) != 0; p.p = new (p.v) op(*this, impl.socket_, impl.protocol_, - peer_io_context ? *peer_io_context : io_context_, - peer_endpoint, enable_connection_aborted, handler); + peer_io_ex, peer_endpoint, enable_connection_aborted, + handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_accept")); start_accept_op(impl, false, p.p->new_socket(), @@ -571,17 +552,18 @@ public: } // Start an asynchronous connect. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler& handler) + const endpoint_type& peer_endpoint, Handler& handler, + const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_socket_connect_op<Handler> op; + typedef win_iocp_socket_connect_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.socket_, handler); + p.p = new (p.v) op(impl.socket_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_connect")); start_connect_op(impl, impl.protocol_.family(), impl.protocol_.type(), diff --git a/boost/asio/detail/win_iocp_socket_service_base.hpp b/boost/asio/detail/win_iocp_socket_service_base.hpp index dd2bf9f6a9..7a7c900be4 100644 --- a/boost/asio/detail/win_iocp_socket_service_base.hpp +++ b/boost/asio/detail/win_iocp_socket_service_base.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -20,7 +20,7 @@ #if defined(BOOST_ASIO_HAS_IOCP) #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/socket_base.hpp> #include <boost/asio/detail/bind_handler.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> @@ -86,8 +86,7 @@ public: }; // Constructor. - BOOST_ASIO_DECL win_iocp_socket_service_base( - boost::asio::io_context& io_context); + BOOST_ASIO_DECL win_iocp_socket_service_base(execution_context& context); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void base_shutdown(); @@ -211,20 +210,20 @@ public: // Asynchronously wait for the socket to become ready to read, ready to // write, or to have pending error conditions. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_wait(base_implementation_type& impl, - socket_base::wait_type w, Handler& handler) + socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef win_iocp_wait_op<Handler> op; + typedef win_iocp_wait_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, handler); + p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_wait")); switch (w) @@ -272,18 +271,19 @@ public: // Start an asynchronous send. The data being sent must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_send(base_implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler& handler) + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op; + typedef win_iocp_socket_send_op< + ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, buffers, handler); + p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_send")); buffer_sequence_adapter<boost::asio::const_buffer, @@ -296,17 +296,17 @@ public: } // Start an asynchronous wait until data can be sent without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_send(base_implementation_type& impl, const null_buffers&, - socket_base::message_flags, Handler& handler) + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_null_buffers_op<Handler> op; + typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, handler); + p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_send(null_buffers)")); start_reactor_op(impl, select_reactor::write_op, p.p); @@ -338,18 +338,21 @@ public: // Start an asynchronous receive. The buffer for the data being received // must be valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive(base_implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler& handler) + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_socket_recv_op<MutableBufferSequence, Handler> op; + typedef win_iocp_socket_recv_op< + MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.state_, impl.cancel_token_, buffers, handler); + p.p = new (p.v) op(impl.state_, impl.cancel_token_, + buffers, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive")); buffer_sequence_adapter<boost::asio::mutable_buffer, @@ -362,17 +365,18 @@ public: } // Wait until data can be received without blocking. - template <typename Handler> - void async_receive(base_implementation_type& impl, const null_buffers&, - socket_base::message_flags flags, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_receive(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_null_buffers_op<Handler> op; + typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, handler); + p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive(null_buffers)")); start_null_buffers_receive_op(impl, flags, p.p); @@ -411,18 +415,22 @@ public: // Start an asynchronous receive. The buffer for the data being received // must be valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive_with_flags(base_implementation_type& impl, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler& handler) + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_socket_recvmsg_op<MutableBufferSequence, Handler> op; + typedef win_iocp_socket_recvmsg_op< + MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, buffers, out_flags, handler); + p.p = new (p.v) op(impl.cancel_token_, + buffers, out_flags, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive_with_flags")); buffer_sequence_adapter<boost::asio::mutable_buffer, @@ -433,18 +441,19 @@ public: } // Wait until data can be received without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_receive_with_flags(base_implementation_type& impl, const null_buffers&, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, Handler& handler) + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef win_iocp_null_buffers_op<Handler> op; + typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(impl.cancel_token_, handler); + p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket", + BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); // Reset out_flags since it can be given no sensible value at this time. @@ -519,8 +528,8 @@ protected: base_implementation_type& impl); // Helper function to get the reactor. If no reactor has been created yet, a - // new one is obtained from the io_context and a pointer to it is cached in - // this service. + // new one is obtained from the execution context and a pointer to it is + // cached in this service. BOOST_ASIO_DECL select_reactor& get_reactor(); // The type of a ConnectEx function pointer, as old SDKs may not provide it. @@ -554,8 +563,8 @@ protected: // - platform SDKs where MSVC's /Wp64 option causes spurious warnings. BOOST_ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val); - // The io_context used to obtain the reactor, if required. - boost::asio::io_context& io_context_; + // The execution context used to obtain the reactor, if required. + execution_context& context_; // The IOCP service used for running asynchronous operations and dispatching // handlers. diff --git a/boost/asio/detail/win_iocp_thread_info.hpp b/boost/asio/detail/win_iocp_thread_info.hpp index 53f853e104..c6819825c0 100644 --- a/boost/asio/detail/win_iocp_thread_info.hpp +++ b/boost/asio/detail/win_iocp_thread_info.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_thread_info.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_iocp_wait_op.hpp b/boost/asio/detail/win_iocp_wait_op.hpp index b067da3e3d..1f0929f99b 100644 --- a/boost/asio/detail/win_iocp_wait_op.hpp +++ b/boost/asio/detail/win_iocp_wait_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_wait_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,20 +35,21 @@ namespace boost { namespace asio { namespace detail { -template <typename Handler> +template <typename Handler, typename IoExecutor> class win_iocp_wait_op : public reactor_op { public: BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_wait_op); win_iocp_wait_op(socket_ops::weak_cancel_token_type cancel_token, - Handler& handler) + Handler& handler, const IoExecutor& io_ex) : reactor_op(&win_iocp_wait_op::do_perform, &win_iocp_wait_op::do_complete), cancel_token_(cancel_token), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static status do_perform(reactor_op*) @@ -65,7 +66,7 @@ public: // Take ownership of the operation object. win_iocp_wait_op* o(static_cast<win_iocp_wait_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -110,6 +111,7 @@ public: private: socket_ops::weak_cancel_token_type cancel_token_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/win_mutex.hpp b/boost/asio/detail/win_mutex.hpp index 45d87c63bb..7509131c4b 100644 --- a/boost/asio/detail/win_mutex.hpp +++ b/boost/asio/detail/win_mutex.hpp @@ -2,7 +2,7 @@ // detail/win_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_object_handle_service.hpp b/boost/asio/detail/win_object_handle_service.hpp index 03fb634888..42032224a8 100644 --- a/boost/asio/detail/win_object_handle_service.hpp +++ b/boost/asio/detail/win_object_handle_service.hpp @@ -2,7 +2,7 @@ // detail/win_object_handle_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -24,7 +24,13 @@ #include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/wait_handler.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> + +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) #include <boost/asio/detail/push_options.hpp> @@ -33,7 +39,7 @@ namespace asio { namespace detail { class win_object_handle_service : - public service_base<win_object_handle_service> + public execution_context_service_base<win_object_handle_service> { public: // The native type of an object handle. @@ -80,8 +86,7 @@ public: }; // Constructor. - BOOST_ASIO_DECL win_object_handle_service( - boost::asio::io_context& io_context); + BOOST_ASIO_DECL win_object_handle_service(execution_context& context); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void shutdown(); @@ -130,16 +135,17 @@ public: boost::system::error_code& ec); /// Start an asynchronous wait. - template <typename Handler> - void async_wait(implementation_type& impl, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_wait(implementation_type& impl, + Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. - typedef wait_handler<Handler> op; + typedef wait_handler<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_.context(), *p.p, "object_handle", + BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "object_handle", &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "async_wait")); start_wait_op(impl, p.p); @@ -158,8 +164,13 @@ private: static BOOST_ASIO_DECL VOID CALLBACK wait_callback( PVOID param, BOOLEAN timeout); - // The io_context implementation used to post completions. - io_context_impl& io_context_; + // The scheduler used to post completions. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + scheduler_impl& scheduler_; // Mutex to protect access to internal state. mutex mutex_; diff --git a/boost/asio/detail/win_static_mutex.hpp b/boost/asio/detail/win_static_mutex.hpp index 78d3a2eb7f..c310d314db 100644 --- a/boost/asio/detail/win_static_mutex.hpp +++ b/boost/asio/detail/win_static_mutex.hpp @@ -2,7 +2,7 @@ // detail/win_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_thread.hpp b/boost/asio/detail/win_thread.hpp index 377c3e3f93..ef867448a9 100644 --- a/boost/asio/detail/win_thread.hpp +++ b/boost/asio/detail/win_thread.hpp @@ -2,7 +2,7 @@ // detail/win_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/win_tss_ptr.hpp b/boost/asio/detail/win_tss_ptr.hpp index e1761c2e27..102b41a583 100644 --- a/boost/asio/detail/win_tss_ptr.hpp +++ b/boost/asio/detail/win_tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/win_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/winapp_thread.hpp b/boost/asio/detail/winapp_thread.hpp index 775f663d84..b92c7f5a67 100644 --- a/boost/asio/detail/winapp_thread.hpp +++ b/boost/asio/detail/winapp_thread.hpp @@ -2,7 +2,7 @@ // detail/winapp_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/wince_thread.hpp b/boost/asio/detail/wince_thread.hpp index 77ec7c8265..492a37c03f 100644 --- a/boost/asio/detail/wince_thread.hpp +++ b/boost/asio/detail/wince_thread.hpp @@ -2,7 +2,7 @@ // detail/wince_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/winrt_async_manager.hpp b/boost/asio/detail/winrt_async_manager.hpp index 57d6a1c218..e9dc6cb257 100644 --- a/boost/asio/detail/winrt_async_manager.hpp +++ b/boost/asio/detail/winrt_async_manager.hpp @@ -2,7 +2,7 @@ // detail/winrt_async_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -23,7 +23,13 @@ #include <boost/asio/detail/atomic_count.hpp> #include <boost/asio/detail/winrt_async_op.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> + +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) #include <boost/asio/detail/push_options.hpp> @@ -32,13 +38,13 @@ namespace asio { namespace detail { class winrt_async_manager - : public boost::asio::detail::service_base<winrt_async_manager> + : public execution_context_service_base<winrt_async_manager> { public: // Constructor. - winrt_async_manager(boost::asio::io_context& io_context) - : boost::asio::detail::service_base<winrt_async_manager>(io_context), - io_context_(use_service<io_context_impl>(io_context)), + winrt_async_manager(execution_context& context) + : execution_context_service_base<winrt_async_manager>(context), + scheduler_(use_service<scheduler_impl>(context)), outstanding_ops_(1) { } @@ -186,12 +192,12 @@ public: boost::system::system_category()); break; } - io_context_.post_deferred_completion(handler); + scheduler_.post_deferred_completion(handler); if (--outstanding_ops_ == 0) promise_.set_value(); }); - io_context_.work_started(); + scheduler_.work_started(); ++outstanding_ops_; action->Completed = on_completed; } @@ -223,12 +229,12 @@ public: boost::system::system_category()); break; } - io_context_.post_deferred_completion(handler); + scheduler_.post_deferred_completion(handler); if (--outstanding_ops_ == 0) promise_.set_value(); }); - io_context_.work_started(); + scheduler_.work_started(); ++outstanding_ops_; operation->Completed = on_completed; } @@ -264,19 +270,24 @@ public: boost::system::system_category()); break; } - io_context_.post_deferred_completion(handler); + scheduler_.post_deferred_completion(handler); if (--outstanding_ops_ == 0) promise_.set_value(); }); - io_context_.work_started(); + scheduler_.work_started(); ++outstanding_ops_; operation->Completed = on_completed; } private: - // The io_context implementation used to post completed handlers. - io_context_impl& io_context_; + // The scheduler implementation used to post completed handlers. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + scheduler_impl& scheduler_; // Count of outstanding operations. atomic_count outstanding_ops_; diff --git a/boost/asio/detail/winrt_async_op.hpp b/boost/asio/detail/winrt_async_op.hpp index c3203ff88a..251dd878e4 100644 --- a/boost/asio/detail/winrt_async_op.hpp +++ b/boost/asio/detail/winrt_async_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_async_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/winrt_resolve_op.hpp b/boost/asio/detail/winrt_resolve_op.hpp index 80f102f4c8..f7faa2993a 100644 --- a/boost/asio/detail/winrt_resolve_op.hpp +++ b/boost/asio/detail/winrt_resolve_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_resolve_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -34,7 +34,7 @@ namespace boost { namespace asio { namespace detail { -template <typename Protocol, typename Handler> +template <typename Protocol, typename Handler, typename IoExecutor> class winrt_resolve_op : public winrt_async_op< Windows::Foundation::Collections::IVectorView< @@ -47,15 +47,17 @@ public: typedef boost::asio::ip::basic_resolver_query<Protocol> query_type; typedef boost::asio::ip::basic_resolver_results<Protocol> results_type; - winrt_resolve_op(const query_type& query, Handler& handler) + winrt_resolve_op(const query_type& query, + Handler& handler, const IoExecutor& io_ex) : winrt_async_op< Windows::Foundation::Collections::IVectorView< Windows::Networking::EndpointPair^>^>( &winrt_resolve_op::do_complete), query_(query), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -64,7 +66,7 @@ public: // Take ownership of the operation object. winrt_resolve_op* o(static_cast<winrt_resolve_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -107,6 +109,7 @@ public: private: query_type query_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/winrt_resolver_service.hpp b/boost/asio/detail/winrt_resolver_service.hpp index 463dbde11f..054b6abfbc 100644 --- a/boost/asio/detail/winrt_resolver_service.hpp +++ b/boost/asio/detail/winrt_resolver_service.hpp @@ -2,7 +2,7 @@ // detail/winrt_resolver_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,6 +21,7 @@ #include <boost/asio/ip/basic_resolver_query.hpp> #include <boost/asio/ip/basic_resolver_results.hpp> +#include <boost/asio/post.hpp> #include <boost/asio/detail/bind_handler.hpp> #include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/socket_ops.hpp> @@ -28,6 +29,12 @@ #include <boost/asio/detail/winrt_resolve_op.hpp> #include <boost/asio/detail/winrt_utils.hpp> +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) + #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -36,7 +43,7 @@ namespace detail { template <typename Protocol> class winrt_resolver_service : - public service_base<winrt_resolver_service<Protocol> > + public execution_context_service_base<winrt_resolver_service<Protocol> > { public: // The implementation type of the resolver. A cancellation token is used to @@ -54,10 +61,11 @@ public: typedef boost::asio::ip::basic_resolver_results<Protocol> results_type; // Constructor. - winrt_resolver_service(boost::asio::io_context& io_context) - : service_base<winrt_resolver_service<Protocol> >(io_context), - io_context_(use_service<io_context_impl>(io_context)), - async_manager_(use_service<winrt_async_manager>(io_context)) + winrt_resolver_service(execution_context& context) + : execution_context_service_base< + winrt_resolver_service<Protocol> >(context), + scheduler_(use_service<scheduler_impl>(context)), + async_manager_(use_service<winrt_async_manager>(context)) { } @@ -72,7 +80,7 @@ public: } // Perform any fork-related housekeeping. - void notify_fork(boost::asio::io_context::fork_event) + void notify_fork(execution_context::fork_event) { } @@ -131,20 +139,20 @@ public: } // Asynchronously resolve a query to a list of entries. - template <typename Handler> - void async_resolve(implementation_type& impl, - const query_type& query, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_resolve(implementation_type& impl, const query_type& query, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef winrt_resolve_op<Protocol, Handler> op; + typedef winrt_resolve_op<Protocol, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(query, handler); + p.p = new (p.v) op(query, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_.context(), + BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "resolver", &impl, 0, "async_resolve")); (void)impl; @@ -160,7 +168,7 @@ public: { p.p->ec_ = boost::system::error_code( e->HResult, boost::system::system_category()); - io_context_.post_immediate_completion(p.p, is_continuation); + scheduler_.post_immediate_completion(p.p, is_continuation); p.v = p.p = 0; } } @@ -174,18 +182,24 @@ public: } // Asynchronously resolve an endpoint to a list of entries. - template <typename Handler> - void async_resolve(implementation_type&, - const endpoint_type&, Handler& handler) + template <typename Handler, typename IoExecutor> + void async_resolve(implementation_type&, const endpoint_type&, + Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const results_type results; - io_context_.get_io_context().post( - detail::bind_handler(handler, ec, results)); + boost::asio::post(io_ex, detail::bind_handler(handler, ec, results)); } private: - io_context_impl& io_context_; + // The scheduler implementation used for delivering completions. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + scheduler_impl& scheduler_; + winrt_async_manager& async_manager_; }; diff --git a/boost/asio/detail/winrt_socket_connect_op.hpp b/boost/asio/detail/winrt_socket_connect_op.hpp index 9926da97d9..291c886086 100644 --- a/boost/asio/detail/winrt_socket_connect_op.hpp +++ b/boost/asio/detail/winrt_socket_connect_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -34,18 +34,19 @@ namespace boost { namespace asio { namespace detail { -template <typename Handler> +template <typename Handler, typename IoExecutor> class winrt_socket_connect_op : public winrt_async_op<void> { public: BOOST_ASIO_DEFINE_HANDLER_PTR(winrt_socket_connect_op); - winrt_socket_connect_op(Handler& handler) + winrt_socket_connect_op(Handler& handler, const IoExecutor& io_ex) : winrt_async_op<void>(&winrt_socket_connect_op::do_complete), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -54,7 +55,7 @@ public: // Take ownership of the operation object. winrt_socket_connect_op* o(static_cast<winrt_socket_connect_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -81,6 +82,7 @@ public: private: Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/winrt_socket_recv_op.hpp b/boost/asio/detail/winrt_socket_recv_op.hpp index 0701208da4..34a5a755bf 100644 --- a/boost/asio/detail/winrt_socket_recv_op.hpp +++ b/boost/asio/detail/winrt_socket_recv_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -34,20 +34,22 @@ namespace boost { namespace asio { namespace detail { -template <typename MutableBufferSequence, typename Handler> +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> class winrt_socket_recv_op : public winrt_async_op<Windows::Storage::Streams::IBuffer^> { public: BOOST_ASIO_DEFINE_HANDLER_PTR(winrt_socket_recv_op); - winrt_socket_recv_op(const MutableBufferSequence& buffers, Handler& handler) + winrt_socket_recv_op(const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) : winrt_async_op<Windows::Storage::Streams::IBuffer^>( &winrt_socket_recv_op::do_complete), buffers_(buffers), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -56,7 +58,7 @@ public: // Take ownership of the operation object. winrt_socket_recv_op* o(static_cast<winrt_socket_recv_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -101,6 +103,7 @@ public: private: MutableBufferSequence buffers_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/winrt_socket_send_op.hpp b/boost/asio/detail/winrt_socket_send_op.hpp index 4e62056c4f..cbf42110f8 100644 --- a/boost/asio/detail/winrt_socket_send_op.hpp +++ b/boost/asio/detail/winrt_socket_send_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -34,19 +34,21 @@ namespace boost { namespace asio { namespace detail { -template <typename ConstBufferSequence, typename Handler> +template <typename ConstBufferSequence, typename Handler, typename IoExecutor> class winrt_socket_send_op : public winrt_async_op<unsigned int> { public: BOOST_ASIO_DEFINE_HANDLER_PTR(winrt_socket_send_op); - winrt_socket_send_op(const ConstBufferSequence& buffers, Handler& handler) + winrt_socket_send_op(const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) : winrt_async_op<unsigned int>(&winrt_socket_send_op::do_complete), buffers_(buffers), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + io_executor_(io_ex) { - handler_work<Handler>::start(handler_); + handler_work<Handler, IoExecutor>::start(handler_, io_executor_); } static void do_complete(void* owner, operation* base, @@ -55,7 +57,7 @@ public: // Take ownership of the operation object. winrt_socket_send_op* o(static_cast<winrt_socket_send_op*>(base)); ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; - handler_work<Handler> w(o->handler_); + handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_); BOOST_ASIO_HANDLER_COMPLETION((*o)); @@ -92,6 +94,7 @@ public: private: ConstBufferSequence buffers_; Handler handler_; + IoExecutor io_executor_; }; } // namespace detail diff --git a/boost/asio/detail/winrt_ssocket_service.hpp b/boost/asio/detail/winrt_ssocket_service.hpp index c874f2520d..af2c718699 100644 --- a/boost/asio/detail/winrt_ssocket_service.hpp +++ b/boost/asio/detail/winrt_ssocket_service.hpp @@ -2,7 +2,7 @@ // detail/winrt_ssocket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -20,7 +20,7 @@ #if defined(BOOST_ASIO_WINDOWS_RUNTIME) #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/winrt_socket_connect_op.hpp> #include <boost/asio/detail/winrt_ssocket_service_base.hpp> @@ -34,7 +34,7 @@ namespace detail { template <typename Protocol> class winrt_ssocket_service : - public service_base<winrt_ssocket_service<Protocol> >, + public execution_context_service_base<winrt_ssocket_service<Protocol> >, public winrt_ssocket_service_base { public: @@ -62,9 +62,9 @@ public: }; // Constructor. - winrt_ssocket_service(boost::asio::io_context& io_context) - : service_base<winrt_ssocket_service<Protocol> >(io_context), - winrt_ssocket_service_base(io_context) + winrt_ssocket_service(execution_context& context) + : execution_context_service_base<winrt_ssocket_service<Protocol> >(context), + winrt_ssocket_service_base(context) { } @@ -211,20 +211,21 @@ public: } // Start an asynchronous connect. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler& handler) + const endpoint_type& peer_endpoint, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef winrt_socket_connect_op<Handler> op; + typedef winrt_socket_connect_op<Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(handler); + p.p = new (p.v) op(handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_.context(), + BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "socket", &impl, 0, "async_connect")); start_connect_op(impl, peer_endpoint.data(), p.p, is_continuation); diff --git a/boost/asio/detail/winrt_ssocket_service_base.hpp b/boost/asio/detail/winrt_ssocket_service_base.hpp index dcb5aa1c40..cb7b6c07f7 100644 --- a/boost/asio/detail/winrt_ssocket_service_base.hpp +++ b/boost/asio/detail/winrt_ssocket_service_base.hpp @@ -2,7 +2,7 @@ // detail/winrt_ssocket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,7 +21,7 @@ #include <boost/asio/buffer.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> #include <boost/asio/socket_base.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> #include <boost/asio/detail/memory.hpp> @@ -30,6 +30,12 @@ #include <boost/asio/detail/winrt_socket_recv_op.hpp> #include <boost/asio/detail/winrt_socket_send_op.hpp> +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) + #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -62,8 +68,7 @@ public: }; // Constructor. - BOOST_ASIO_DECL winrt_ssocket_service_base( - boost::asio::io_context& io_context); + BOOST_ASIO_DECL winrt_ssocket_service_base(execution_context& context); // Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL void base_shutdown(); @@ -193,21 +198,21 @@ public: // Start an asynchronous send. The data being sent must be valid for the // lifetime of the asynchronous operation. - template <typename ConstBufferSequence, typename Handler> + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> void async_send(base_implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler& handler) + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef winrt_socket_send_op<ConstBufferSequence, Handler> op; + typedef winrt_socket_send_op<ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(buffers, handler); + p.p = new (p.v) op(buffers, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_.context(), + BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "socket", &impl, 0, "async_send")); start_send_op(impl, @@ -218,13 +223,13 @@ public: } // Start an asynchronous wait until data can be sent without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_send(base_implementation_type&, const null_buffers&, - socket_base::message_flags, Handler& handler) + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.get_io_context().post( + boost::asio::post(io_ex, detail::bind_handler(handler, ec, bytes_transferred)); } @@ -249,21 +254,22 @@ public: // Start an asynchronous receive. The buffer for the data being received // must be valid for the lifetime of the asynchronous operation. - template <typename MutableBufferSequence, typename Handler> + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> void async_receive(base_implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler& handler) + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) { bool is_continuation = boost_asio_handler_cont_helpers::is_continuation(handler); // Allocate and construct an operation to wrap the handler. - typedef winrt_socket_recv_op<MutableBufferSequence, Handler> op; + typedef winrt_socket_recv_op<MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { boost::asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(buffers, handler); + p.p = new (p.v) op(buffers, handler, io_ex); - BOOST_ASIO_HANDLER_CREATION((io_context_.context(), + BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "socket", &impl, 0, "async_receive")); start_receive_op(impl, @@ -274,13 +280,13 @@ public: } // Wait until data can be received without blocking. - template <typename Handler> + template <typename Handler, typename IoExecutor> void async_receive(base_implementation_type&, const null_buffers&, - socket_base::message_flags, Handler& handler) + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) { boost::system::error_code ec = boost::asio::error::operation_not_supported; const std::size_t bytes_transferred = 0; - io_context_.get_io_context().post( + boost::asio::post(io_ex, detail::bind_handler(handler, ec, bytes_transferred)); } @@ -333,8 +339,13 @@ protected: winrt_async_op<Windows::Storage::Streams::IBuffer^>* op, bool is_continuation); - // The io_context implementation used for delivering completions. - io_context_impl& io_context_; + // The scheduler implementation used for delivering completions. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + scheduler_impl& scheduler_; // The manager that keeps track of outstanding operations. winrt_async_manager& async_manager_; diff --git a/boost/asio/detail/winrt_timer_scheduler.hpp b/boost/asio/detail/winrt_timer_scheduler.hpp index 8f61ad843e..d48ed2cb6a 100644 --- a/boost/asio/detail/winrt_timer_scheduler.hpp +++ b/boost/asio/detail/winrt_timer_scheduler.hpp @@ -2,7 +2,7 @@ // detail/winrt_timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,7 +28,13 @@ #include <boost/asio/detail/timer_queue_base.hpp> #include <boost/asio/detail/timer_queue_set.hpp> #include <boost/asio/detail/wait_op.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> + +#if defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_io_context.hpp> +#else // defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/scheduler.hpp> +#endif // defined(BOOST_ASIO_HAS_IOCP) #if defined(BOOST_ASIO_HAS_IOCP) # include <boost/asio/detail/thread.hpp> @@ -41,11 +47,11 @@ namespace asio { namespace detail { class winrt_timer_scheduler - : public boost::asio::detail::service_base<winrt_timer_scheduler> + : public execution_context_service_base<winrt_timer_scheduler> { public: // Constructor. - BOOST_ASIO_DECL winrt_timer_scheduler(boost::asio::io_context& io_context); + BOOST_ASIO_DECL winrt_timer_scheduler(execution_context& context); // Destructor. BOOST_ASIO_DECL ~winrt_timer_scheduler(); @@ -54,8 +60,7 @@ public: BOOST_ASIO_DECL void shutdown(); // Recreate internal descriptors following a fork. - BOOST_ASIO_DECL void notify_fork( - boost::asio::io_context::fork_event fork_ev); + BOOST_ASIO_DECL void notify_fork(execution_context::fork_event fork_ev); // Initialise the task. No effect as this class uses its own thread. BOOST_ASIO_DECL void init_task(); @@ -101,8 +106,13 @@ private: // Helper function to remove a timer queue. BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue); - // The io_context implementation used to post completions. - io_context_impl& io_context_; + // The scheduler implementation used to post completions. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef class win_iocp_io_context scheduler_impl; +#else + typedef class scheduler scheduler_impl; +#endif + scheduler_impl& scheduler_; // Mutex used to protect internal variables. boost::asio::detail::mutex mutex_; diff --git a/boost/asio/detail/winrt_utils.hpp b/boost/asio/detail/winrt_utils.hpp index 765edeecb8..bc765aeb66 100644 --- a/boost/asio/detail/winrt_utils.hpp +++ b/boost/asio/detail/winrt_utils.hpp @@ -2,7 +2,7 @@ // detail/winrt_utils.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/winsock_init.hpp b/boost/asio/detail/winsock_init.hpp index abf59cd1bf..dfda010839 100644 --- a/boost/asio/detail/winsock_init.hpp +++ b/boost/asio/detail/winsock_init.hpp @@ -2,7 +2,7 @@ // detail/winsock_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/detail/work_dispatcher.hpp b/boost/asio/detail/work_dispatcher.hpp index 3167f244fd..9a92c45e02 100644 --- a/boost/asio/detail/work_dispatcher.hpp +++ b/boost/asio/detail/work_dispatcher.hpp @@ -2,7 +2,7 @@ // detail/work_dispatcher.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -30,9 +30,10 @@ template <typename Handler> class work_dispatcher { public: - work_dispatcher(Handler& handler) + template <typename CompletionHandler> + explicit work_dispatcher(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) : work_((get_associated_executor)(handler)), - handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + handler_(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)) { } diff --git a/boost/asio/detail/wrapped_handler.hpp b/boost/asio/detail/wrapped_handler.hpp index 8e23d1db9e..8496168975 100644 --- a/boost/asio/detail/wrapped_handler.hpp +++ b/boost/asio/detail/wrapped_handler.hpp @@ -2,7 +2,7 @@ // detail/wrapped_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/dispatch.hpp b/boost/asio/dispatch.hpp index 4136eda64f..578608c0c3 100644 --- a/boost/asio/dispatch.hpp +++ b/boost/asio/dispatch.hpp @@ -2,7 +2,7 @@ // dispatch.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -29,8 +29,8 @@ namespace asio { /// Submits a completion token or function object for execution. /** * This function submits an object for execution using the object's associated - * executor. The function object is queued for execution, and is never called - * from the current thread prior to returning from <tt>dispatch()</tt>. + * executor. The function object may be called from the current thread prior to + * returning from <tt>dispatch()</tt>. Otherwise, it is queued for execution. * * This function has the following effects: * @@ -57,8 +57,8 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch( /// Submits a completion token or function object for execution. /** * This function submits an object for execution using the specified executor. - * The function object is queued for execution, and is never called from the - * current thread prior to returning from <tt>dispatch()</tt>. + * The function object may be called from the current thread prior to returning + * from <tt>dispatch()</tt>. Otherwise, it is queued for execution. * * This function has the following effects: * diff --git a/boost/asio/error.hpp b/boost/asio/error.hpp index 53810b287a..448d9aeb84 100644 --- a/boost/asio/error.hpp +++ b/boost/asio/error.hpp @@ -2,7 +2,7 @@ // error.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/execution_context.hpp b/boost/asio/execution_context.hpp index 4ebb607a1a..f89fb4cdeb 100644 --- a/boost/asio/execution_context.hpp +++ b/boost/asio/execution_context.hpp @@ -2,7 +2,7 @@ // execution_context.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -110,13 +110,14 @@ public: class id; class service; -protected: +public: /// Constructor. BOOST_ASIO_DECL execution_context(); /// Destructor. BOOST_ASIO_DECL ~execution_context(); +protected: /// Shuts down all services in the context. /** * This function is implemented as follows: diff --git a/boost/asio/executor.hpp b/boost/asio/executor.hpp index 43a5a2c105..7c6a353f0e 100644 --- a/boost/asio/executor.hpp +++ b/boost/asio/executor.hpp @@ -2,7 +2,7 @@ // executor.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/executor_work_guard.hpp b/boost/asio/executor_work_guard.hpp index a9303462eb..546f7ef9cf 100644 --- a/boost/asio/executor_work_guard.hpp +++ b/boost/asio/executor_work_guard.hpp @@ -2,7 +2,7 @@ // executor_work_guard.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -56,7 +56,7 @@ public: #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. - executor_work_guard(executor_work_guard&& other) + executor_work_guard(executor_work_guard&& other) BOOST_ASIO_NOEXCEPT : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)), owns_(other.owns_) { diff --git a/boost/asio/experimental.hpp b/boost/asio/experimental.hpp deleted file mode 100644 index 0ca0a9658f..0000000000 --- a/boost/asio/experimental.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// -// experimental.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_EXPERIMENTAL_HPP -#define BOOST_ASIO_EXPERIMENTAL_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/experimental/co_spawn.hpp> -#include <boost/asio/experimental/detached.hpp> -#include <boost/asio/experimental/redirect_error.hpp> - -#endif // BOOST_ASIO_EXPERIMENTAL_HPP diff --git a/boost/asio/experimental/co_spawn.hpp b/boost/asio/experimental/co_spawn.hpp deleted file mode 100644 index c900da11f0..0000000000 --- a/boost/asio/experimental/co_spawn.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// -// experimental/co_spawn.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_EXPERIMENTAL_CO_SPAWN_HPP -#define BOOST_ASIO_EXPERIMENTAL_CO_SPAWN_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) - -#include <experimental/coroutine> -#include <boost/asio/executor.hpp> -#include <boost/asio/strand.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace experimental { -namespace detail { - -using std::experimental::coroutine_handle; - -template <typename> class awaiter; -template <typename> class awaitee_base; -template <typename, typename> class awaitee; -template <typename, typename> class await_handler_base; -template <typename Executor, typename F, typename CompletionToken> -auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token); - -} // namespace detail - -namespace this_coro { - -/// Awaitable type that returns a completion token for the current coroutine. -struct token_t {}; - -/// Awaitable object that returns a completion token for the current coroutine. -constexpr inline token_t token() { return {}; } - -/// Awaitable type that returns the executor of the current coroutine. -struct executor_t {}; - -/// Awaitable object that returns the executor of the current coroutine. -constexpr inline executor_t executor() { return {}; } - -} // namespace this_coro - -/// A completion token that represents the currently executing coroutine. -/** - * The await_token class is used to represent the currently executing - * coroutine. An await_token may be passed as a handler to an asynchronous - * operation. For example: - * - * @code awaitable<void> my_coroutine() - * { - * await_token token = co_await this_coro::token(); - * ... - * std::size_t n = co_await my_socket.async_read_some(buffer, token); - * ... - * } @endcode - * - * The initiating function (async_read_some in the above example) suspends the - * current coroutine. The coroutine is resumed when the asynchronous operation - * completes, and the result of the operation is returned. - */ -template <typename Executor> -class await_token -{ -public: - /// The associated executor type. - typedef Executor executor_type; - - /// Copy constructor. - await_token(const await_token& other) noexcept - : awaiter_(other.awaiter_) - { - } - - /// Move constructor. - await_token(await_token&& other) noexcept - : awaiter_(std::exchange(other.awaiter_, nullptr)) - { - } - - /// Get the associated executor. - executor_type get_executor() const noexcept - { - return awaiter_->get_executor(); - } - -private: - // No assignment allowed. - await_token& operator=(const await_token&) = delete; - - template <typename> friend class detail::awaitee_base; - template <typename, typename> friend class detail::await_handler_base; - - // Private constructor used by awaitee_base. - explicit await_token(detail::awaiter<Executor>* a) - : awaiter_(a) - { - } - - detail::awaiter<Executor>* awaiter_; -}; - -/// The return type of a coroutine or asynchronous operation. -template <typename T, typename Executor = strand<executor>> -class awaitable -{ -public: - /// The type of the awaited value. - typedef T value_type; - - /// The executor type that will be used for the coroutine. - typedef Executor executor_type; - - /// Move constructor. - awaitable(awaitable&& other) noexcept - : awaitee_(std::exchange(other.awaitee_, nullptr)) - { - } - - /// Destructor - ~awaitable() - { - if (awaitee_) - { - detail::coroutine_handle< - detail::awaitee<T, Executor>>::from_promise( - *awaitee_).destroy(); - } - } - -#if !defined(GENERATING_DOCUMENTATION) - - // Support for co_await keyword. - bool await_ready() const noexcept - { - return awaitee_->ready(); - } - - // Support for co_await keyword. - void await_suspend(detail::coroutine_handle<detail::awaiter<Executor>> h) - { - awaitee_->attach_caller(h); - } - - // Support for co_await keyword. - template <class U> - void await_suspend(detail::coroutine_handle<detail::awaitee<U, Executor>> h) - { - awaitee_->attach_caller(h); - } - - // Support for co_await keyword. - T await_resume() - { - return awaitee_->get(); - } - -#endif // !defined(GENERATING_DOCUMENTATION) - -private: - template <typename, typename> friend class detail::awaitee; - template <typename, typename> friend class detail::await_handler_base; - - // Not copy constructible or copy assignable. - awaitable(const awaitable&) = delete; - awaitable& operator=(const awaitable&) = delete; - - // Construct the awaitable from a coroutine's promise object. - explicit awaitable(detail::awaitee<T, Executor>* a) : awaitee_(a) {} - - detail::awaitee<T, Executor>* awaitee_; -}; - -/// Spawn a new thread of execution. -template <typename Executor, typename F, typename CompletionToken, - typename = typename enable_if<is_executor<Executor>::value>::type> -inline auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token) -{ - return detail::co_spawn(ex, std::forward<F>(f), - std::forward<CompletionToken>(token)); -} - -/// Spawn a new thread of execution. -template <typename ExecutionContext, typename F, typename CompletionToken, - typename = typename enable_if< - is_convertible<ExecutionContext&, execution_context&>::value>::type> -inline auto co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token) -{ - return detail::co_spawn(ctx.get_executor(), std::forward<F>(f), - std::forward<CompletionToken>(token)); -} - -/// Spawn a new thread of execution. -template <typename Executor, typename F, typename CompletionToken> -inline auto co_spawn(const await_token<Executor>& parent, - F&& f, CompletionToken&& token) -{ - return detail::co_spawn(parent.get_executor(), std::forward<F>(f), - std::forward<CompletionToken>(token)); -} - -} // namespace experimental -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#include <boost/asio/experimental/impl/co_spawn.hpp> - -#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) - -#endif // BOOST_ASIO_EXPERIMENTAL_CO_SPAWN_HPP diff --git a/boost/asio/experimental/impl/co_spawn.hpp b/boost/asio/experimental/impl/co_spawn.hpp deleted file mode 100644 index 51ffb4eeb1..0000000000 --- a/boost/asio/experimental/impl/co_spawn.hpp +++ /dev/null @@ -1,878 +0,0 @@ -// -// experimental/impl/co_spawn.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_EXPERIMENTAL_IMPL_CO_SPAWN_HPP -#define BOOST_ASIO_EXPERIMENTAL_IMPL_CO_SPAWN_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> -#include <exception> -#include <functional> -#include <memory> -#include <new> -#include <tuple> -#include <utility> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/thread_context.hpp> -#include <boost/asio/detail/thread_info_base.hpp> -#include <boost/asio/detail/type_traits.hpp> -#include <boost/asio/dispatch.hpp> -#include <boost/asio/post.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace experimental { -namespace detail { - -// Promise object for coroutine at top of thread-of-execution "stack". -template <typename Executor> -class awaiter -{ -public: - struct deleter - { - void operator()(awaiter* a) - { - if (a) - a->release(); - } - }; - - typedef std::unique_ptr<awaiter, deleter> ptr; - - typedef Executor executor_type; - - ~awaiter() - { - if (has_executor_) - static_cast<Executor*>(static_cast<void*>(executor_))->~Executor(); - } - - void set_executor(const Executor& ex) - { - new (&executor_) Executor(ex); - has_executor_ = true; - } - - executor_type get_executor() const noexcept - { - return *static_cast<const Executor*>(static_cast<const void*>(executor_)); - } - - awaiter* get_return_object() - { - return this; - } - - auto initial_suspend() - { - return std::experimental::suspend_always(); - } - - auto final_suspend() - { - return std::experimental::suspend_always(); - } - - void return_void() - { - } - - awaiter* add_ref() - { - ++ref_count_; - return this; - } - - void release() - { - if (--ref_count_ == 0) - coroutine_handle<awaiter>::from_promise(*this).destroy(); - } - - void unhandled_exception() - { - pending_exception_ = std::current_exception(); - } - - void rethrow_unhandled_exception() - { - if (pending_exception_) - { - std::exception_ptr ex = std::exchange(pending_exception_, nullptr); - std::rethrow_exception(ex); - } - } - -private: - std::size_t ref_count_ = 0; - std::exception_ptr pending_exception_ = nullptr; - alignas(Executor) unsigned char executor_[sizeof(Executor)]; - bool has_executor_ = false; -}; - -// Base promise for coroutines further down the thread-of-execution "stack". -template <typename Executor> -class awaitee_base -{ -public: -#if !defined(BOOST_ASIO_DISABLE_AWAITEE_RECYCLING) - void* operator new(std::size_t size) - { - return boost::asio::detail::thread_info_base::allocate( - boost::asio::detail::thread_info_base::awaitee_tag(), - boost::asio::detail::thread_context::thread_call_stack::top(), - size); - } - - void operator delete(void* pointer, std::size_t size) - { - boost::asio::detail::thread_info_base::deallocate( - boost::asio::detail::thread_info_base::awaitee_tag(), - boost::asio::detail::thread_context::thread_call_stack::top(), - pointer, size); - } -#endif // !defined(BOOST_ASIO_DISABLE_AWAITEE_RECYCLING) - - auto initial_suspend() - { - return std::experimental::suspend_never(); - } - - struct final_suspender - { - awaitee_base* this_; - - bool await_ready() const noexcept - { - return false; - } - - void await_suspend(coroutine_handle<void>) - { - this_->wake_caller(); - } - - void await_resume() const noexcept - { - } - }; - - auto final_suspend() - { - return final_suspender{this}; - } - - void set_except(std::exception_ptr e) - { - pending_exception_ = e; - } - - void unhandled_exception() - { - set_except(std::current_exception()); - } - - void rethrow_exception() - { - if (pending_exception_) - { - std::exception_ptr ex = std::exchange(pending_exception_, nullptr); - std::rethrow_exception(ex); - } - } - - awaiter<Executor>* top() - { - return awaiter_; - } - - coroutine_handle<void> caller() - { - return caller_; - } - - bool ready() const - { - return ready_; - } - - void wake_caller() - { - if (caller_) - caller_.resume(); - else - ready_ = true; - } - - class awaitable_executor - { - public: - explicit awaitable_executor(awaitee_base* a) - : this_(a) - { - } - - bool await_ready() const noexcept - { - return this_->awaiter_ != nullptr; - } - - template <typename U, typename Ex> - void await_suspend(coroutine_handle<detail::awaitee<U, Ex>> h) noexcept - { - this_->resume_on_attach_ = h; - } - - Executor await_resume() - { - return this_->awaiter_->get_executor(); - } - - private: - awaitee_base* this_; - }; - - awaitable_executor await_transform(this_coro::executor_t) noexcept - { - return awaitable_executor(this); - } - - class awaitable_token - { - public: - explicit awaitable_token(awaitee_base* a) - : this_(a) - { - } - - bool await_ready() const noexcept - { - return this_->awaiter_ != nullptr; - } - - template <typename U, typename Ex> - void await_suspend(coroutine_handle<detail::awaitee<U, Ex>> h) noexcept - { - this_->resume_on_attach_ = h; - } - - await_token<Executor> await_resume() - { - return await_token<Executor>(this_->awaiter_); - } - - private: - awaitee_base* this_; - }; - - awaitable_token await_transform(this_coro::token_t) noexcept - { - return awaitable_token(this); - } - - template <typename T> - awaitable<T, Executor> await_transform(awaitable<T, Executor>& t) const - { - return std::move(t); - } - - template <typename T> - awaitable<T, Executor> await_transform(awaitable<T, Executor>&& t) const - { - return std::move(t); - } - - std::experimental::suspend_always await_transform( - std::experimental::suspend_always) const - { - return std::experimental::suspend_always(); - } - - void attach_caller(coroutine_handle<awaiter<Executor>> h) - { - this->caller_ = h; - this->attach_callees(&h.promise()); - } - - template <typename U> - void attach_caller(coroutine_handle<awaitee<U, Executor>> h) - { - this->caller_ = h; - if (h.promise().awaiter_) - this->attach_callees(h.promise().awaiter_); - else - h.promise().unattached_callee_ = this; - } - - void attach_callees(awaiter<Executor>* a) - { - for (awaitee_base* curr = this; curr != nullptr; - curr = std::exchange(curr->unattached_callee_, nullptr)) - { - curr->awaiter_ = a; - if (curr->resume_on_attach_) - return std::exchange(curr->resume_on_attach_, nullptr).resume(); - } - } - -protected: - awaiter<Executor>* awaiter_ = nullptr; - coroutine_handle<void> caller_ = nullptr; - awaitee_base<Executor>* unattached_callee_ = nullptr; - std::exception_ptr pending_exception_ = nullptr; - coroutine_handle<void> resume_on_attach_ = nullptr; - bool ready_ = false; -}; - -// Promise object for coroutines further down the thread-of-execution "stack". -template <typename T, typename Executor> -class awaitee - : public awaitee_base<Executor> -{ -public: - awaitee() - { - } - - awaitee(awaitee&& other) noexcept - : awaitee_base<Executor>(std::move(other)) - { - } - - ~awaitee() - { - if (has_result_) - static_cast<T*>(static_cast<void*>(result_))->~T(); - } - - awaitable<T, Executor> get_return_object() - { - return awaitable<T, Executor>(this); - }; - - template <typename U> - void return_value(U&& u) - { - new (&result_) T(std::forward<U>(u)); - has_result_ = true; - } - - T get() - { - this->caller_ = nullptr; - this->rethrow_exception(); - return std::move(*static_cast<T*>(static_cast<void*>(result_))); - } - -private: - alignas(T) unsigned char result_[sizeof(T)]; - bool has_result_ = false; -}; - -// Promise object for coroutines further down the thread-of-execution "stack". -template <typename Executor> -class awaitee<void, Executor> - : public awaitee_base<Executor> -{ -public: - awaitable<void, Executor> get_return_object() - { - return awaitable<void, Executor>(this); - }; - - void return_void() - { - } - - void get() - { - this->caller_ = nullptr; - this->rethrow_exception(); - } -}; - -template <typename Executor> -class awaiter_task -{ -public: - typedef Executor executor_type; - - awaiter_task(awaiter<Executor>* a) - : awaiter_(a->add_ref()) - { - } - - awaiter_task(awaiter_task&& other) noexcept - : awaiter_(std::exchange(other.awaiter_, nullptr)) - { - } - - ~awaiter_task() - { - if (awaiter_) - { - // Coroutine "stack unwinding" must be performed through the executor. - executor_type ex(awaiter_->get_executor()); - (post)(ex, - [a = std::move(awaiter_)]() mutable - { - typename awaiter<Executor>::ptr(std::move(a)); - }); - } - } - - executor_type get_executor() const noexcept - { - return awaiter_->get_executor(); - } - -protected: - typename awaiter<Executor>::ptr awaiter_; -}; - -template <typename Executor> -class co_spawn_handler : public awaiter_task<Executor> -{ -public: - using awaiter_task<Executor>::awaiter_task; - - void operator()() - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - coroutine_handle<awaiter<Executor>>::from_promise(*ptr.get()).resume(); - } -}; - -template <typename Executor, typename T> -class await_handler_base : public awaiter_task<Executor> -{ -public: - typedef awaitable<T, Executor> awaitable_type; - - await_handler_base(await_token<Executor> token) - : awaiter_task<Executor>(token.awaiter_), - awaitee_(nullptr) - { - } - - await_handler_base(await_handler_base&& other) noexcept - : awaiter_task<Executor>(std::move(other)), - awaitee_(std::exchange(other.awaitee_, nullptr)) - { - } - - void attach_awaitee(const awaitable<T, Executor>& a) - { - awaitee_ = a.awaitee_; - } - -protected: - awaitee<T, Executor>* awaitee_; -}; - -template <typename, typename...> class await_handler; - -template <typename Executor> -class await_handler<Executor, void> - : public await_handler_base<Executor, void> -{ -public: - using await_handler_base<Executor, void>::await_handler_base; - - void operator()() - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - this->awaitee_->return_void(); - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename Executor> -class await_handler<Executor, boost::system::error_code> - : public await_handler_base<Executor, void> -{ -public: - typedef void return_type; - - using await_handler_base<Executor, void>::await_handler_base; - - void operator()(const boost::system::error_code& ec) - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - if (ec) - { - this->awaitee_->set_except( - std::make_exception_ptr(boost::system::system_error(ec))); - } - else - this->awaitee_->return_void(); - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename Executor> -class await_handler<Executor, std::exception_ptr> - : public await_handler_base<Executor, void> -{ -public: - using await_handler_base<Executor, void>::await_handler_base; - - void operator()(std::exception_ptr ex) - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - if (ex) - this->awaitee_->set_except(ex); - else - this->awaitee_->return_void(); - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename Executor, typename T> -class await_handler<Executor, T> - : public await_handler_base<Executor, T> -{ -public: - using await_handler_base<Executor, T>::await_handler_base; - - template <typename Arg> - void operator()(Arg&& arg) - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - this->awaitee_->return_value(std::forward<Arg>(arg)); - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename Executor, typename T> -class await_handler<Executor, boost::system::error_code, T> - : public await_handler_base<Executor, T> -{ -public: - using await_handler_base<Executor, T>::await_handler_base; - - template <typename Arg> - void operator()(const boost::system::error_code& ec, Arg&& arg) - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - if (ec) - { - this->awaitee_->set_except( - std::make_exception_ptr(boost::system::system_error(ec))); - } - else - this->awaitee_->return_value(std::forward<Arg>(arg)); - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename Executor, typename T> -class await_handler<Executor, std::exception_ptr, T> - : public await_handler_base<Executor, T> -{ -public: - using await_handler_base<Executor, T>::await_handler_base; - - template <typename Arg> - void operator()(std::exception_ptr ex, Arg&& arg) - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - if (ex) - this->awaitee_->set_except(ex); - else - this->awaitee_->return_value(std::forward<Arg>(arg)); - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename Executor, typename... Ts> -class await_handler - : public await_handler_base<Executor, std::tuple<Ts...>> -{ -public: - using await_handler_base<Executor, std::tuple<Ts...>>::await_handler_base; - - template <typename... Args> - void operator()(Args&&... args) - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - this->awaitee_->return_value( - std::forward_as_tuple(std::forward<Args>(args)...)); - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename Executor, typename... Ts> -class await_handler<Executor, boost::system::error_code, Ts...> - : public await_handler_base<Executor, std::tuple<Ts...>> -{ -public: - using await_handler_base<Executor, std::tuple<Ts...>>::await_handler_base; - - template <typename... Args> - void operator()(const boost::system::error_code& ec, Args&&... args) - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - if (ec) - { - this->awaitee_->set_except( - std::make_exception_ptr(boost::system::system_error(ec))); - } - else - { - this->awaitee_->return_value( - std::forward_as_tuple(std::forward<Args>(args)...)); - } - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename Executor, typename... Ts> -class await_handler<Executor, std::exception_ptr, Ts...> - : public await_handler_base<Executor, std::tuple<Ts...>> -{ -public: - using await_handler_base<Executor, std::tuple<Ts...>>::await_handler_base; - - template <typename... Args> - void operator()(std::exception_ptr ex, Args&&... args) - { - typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_)); - if (ex) - this->awaitee_->set_except(ex); - else - { - this->awaitee_->return_value( - std::forward_as_tuple(std::forward<Args>(args)...)); - } - this->awaitee_->wake_caller(); - ptr->rethrow_unhandled_exception(); - } -}; - -template <typename T> -struct awaitable_signature; - -template <typename T, typename Executor> -struct awaitable_signature<awaitable<T, Executor>> -{ - typedef void type(std::exception_ptr, T); -}; - -template <typename Executor> -struct awaitable_signature<awaitable<void, Executor>> -{ - typedef void type(std::exception_ptr); -}; - -template <typename T, typename Executor, typename F, typename Handler> -awaiter<Executor>* co_spawn_entry_point(awaitable<T, Executor>*, - executor_work_guard<Executor> work_guard, F f, Handler handler) -{ - bool done = false; - - try - { - T t = co_await f(); - - done = true; - - (dispatch)(work_guard.get_executor(), - [handler = std::move(handler), t = std::move(t)]() mutable - { - handler(std::exception_ptr(), std::move(t)); - }); - } - catch (...) - { - if (done) - throw; - - (dispatch)(work_guard.get_executor(), - [handler = std::move(handler), e = std::current_exception()]() mutable - { - handler(e, T()); - }); - } -} - -template <typename Executor, typename F, typename Handler> -awaiter<Executor>* co_spawn_entry_point(awaitable<void, Executor>*, - executor_work_guard<Executor> work_guard, F f, Handler handler) -{ - std::exception_ptr e = nullptr; - - try - { - co_await f(); - } - catch (...) - { - e = std::current_exception(); - } - - (dispatch)(work_guard.get_executor(), - [handler = std::move(handler), e]() mutable - { - handler(e); - }); -} - -template <typename Executor, typename F, typename CompletionToken> -auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token) -{ - typedef typename result_of<F()>::type awaitable_type; - typedef typename awaitable_type::executor_type executor_type; - typedef typename awaitable_signature<awaitable_type>::type signature_type; - - async_completion<CompletionToken, signature_type> completion(token); - - executor_type ex2(ex); - auto work_guard = make_work_guard(completion.completion_handler, ex2); - - auto* a = (co_spawn_entry_point)( - static_cast<awaitable_type*>(nullptr), std::move(work_guard), - std::forward<F>(f), std::move(completion.completion_handler)); - - a->set_executor(ex2); - (post)(co_spawn_handler<executor_type>(a)); - - return completion.result.get(); -} - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable:4033) -#endif // defined(_MSC_VER) - -#if defined(_MSC_VER) -template <typename T> T dummy_return() -{ - return std::move(*static_cast<T*>(nullptr)); -} - -template <> -inline void dummy_return() -{ -} -#endif // defined(_MSC_VER) - -template <typename Awaitable> -inline Awaitable make_dummy_awaitable() -{ - for (;;) co_await std::experimental::suspend_always(); -#if defined(_MSC_VER) - co_return dummy_return<typename Awaitable::value_type>(); -#endif // defined(_MSC_VER) -} - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif // defined(_MSC_VER) - -} // namespace detail -} // namespace experimental - -template <typename Executor, typename R, typename... Args> -class async_result<experimental::await_token<Executor>, R(Args...)> -{ -public: - typedef experimental::detail::await_handler< - Executor, typename decay<Args>::type...> completion_handler_type; - - typedef typename experimental::detail::await_handler< - Executor, Args...>::awaitable_type return_type; - - async_result(completion_handler_type& h) - : awaitable_(experimental::detail::make_dummy_awaitable<return_type>()) - { - h.attach_awaitee(awaitable_); - } - - return_type get() - { - return std::move(awaitable_); - } - -private: - return_type awaitable_; -}; - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - -template <typename Executor, typename R, typename... Args> -struct handler_type<experimental::await_token<Executor>, R(Args...)> -{ - typedef experimental::detail::await_handler< - Executor, typename decay<Args>::type...> type; -}; - -template <typename Executor, typename... Args> -class async_result<experimental::detail::await_handler<Executor, Args...>> -{ -public: - typedef typename experimental::detail::await_handler< - Executor, Args...>::awaitable_type type; - - async_result(experimental::detail::await_handler<Executor, Args...>& h) - : awaitable_(experimental::detail::make_dummy_awaitable<type>()) - { - h.attach_awaitee(awaitable_); - } - - type get() - { - return std::move(awaitable_); - } - -private: - type awaitable_; -}; - -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - -} // namespace asio -} // namespace boost - -namespace std { namespace experimental { - -template <typename Executor, typename... Args> -struct coroutine_traits< - boost::asio::experimental::detail::awaiter<Executor>*, Args...> -{ - typedef boost::asio::experimental::detail::awaiter<Executor> promise_type; -}; - -template <typename T, typename Executor, typename... Args> -struct coroutine_traits< - boost::asio::experimental::awaitable<T, Executor>, Args...> -{ - typedef boost::asio::experimental::detail::awaitee<T, Executor> promise_type; -}; - -}} // namespace std::experimental - -#include <boost/asio/detail/pop_options.hpp> - -#endif // BOOST_ASIO_EXPERIMENTAL_IMPL_CO_SPAWN_HPP diff --git a/boost/asio/experimental/impl/detached.hpp b/boost/asio/experimental/impl/detached.hpp deleted file mode 100644 index c3baf20299..0000000000 --- a/boost/asio/experimental/impl/detached.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// experimental/impl/detached.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_EXPERIMENTAL_IMPL_DETACHED_HPP -#define BOOST_ASIO_EXPERIMENTAL_IMPL_DETACHED_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/variadic_templates.hpp> -#include <boost/asio/handler_type.hpp> -#include <boost/system/system_error.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace experimental { -namespace detail { - - // Class to adapt a detached_t as a completion handler. - class detached_handler - { - public: - detached_handler(detached_t) - { - } - -#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename... Args> - void operator()(Args...) - { - } - -#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) - - void operator()() - { - } - -#define BOOST_ASIO_PRIVATE_DETACHED_DEF(n) \ - template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n)) \ - { \ - } \ - /**/ - BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_DETACHED_DEF) -#undef BOOST_ASIO_PRIVATE_DETACHED_DEF - -#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) - }; - -} // namespace detail -} // namespace experimental - -#if !defined(GENERATING_DOCUMENTATION) - -template <typename Signature> -struct async_result<experimental::detached_t, Signature> -{ - typedef boost::asio::experimental::detail::detached_handler - completion_handler_type; - - typedef void return_type; - - explicit async_result(completion_handler_type&) - { - } - - void get() - { - } -}; - -#endif // !defined(GENERATING_DOCUMENTATION) - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // BOOST_ASIO_EXPERIMENTAL_IMPL_DETACHED_HPP diff --git a/boost/asio/generic/basic_endpoint.hpp b/boost/asio/generic/basic_endpoint.hpp index fc1c0ba290..048a960aa2 100644 --- a/boost/asio/generic/basic_endpoint.hpp +++ b/boost/asio/generic/basic_endpoint.hpp @@ -2,7 +2,7 @@ // generic/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/generic/datagram_protocol.hpp b/boost/asio/generic/datagram_protocol.hpp index e9ef54f530..51e95b5f3a 100644 --- a/boost/asio/generic/datagram_protocol.hpp +++ b/boost/asio/generic/datagram_protocol.hpp @@ -2,7 +2,7 @@ // generic/datagram_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/generic/detail/endpoint.hpp b/boost/asio/generic/detail/endpoint.hpp index c338d78da2..84d320e940 100644 --- a/boost/asio/generic/detail/endpoint.hpp +++ b/boost/asio/generic/detail/endpoint.hpp @@ -2,7 +2,7 @@ // generic/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/generic/detail/impl/endpoint.ipp b/boost/asio/generic/detail/impl/endpoint.ipp index 97db811f2e..aee0377a55 100644 --- a/boost/asio/generic/detail/impl/endpoint.ipp +++ b/boost/asio/generic/detail/impl/endpoint.ipp @@ -2,7 +2,7 @@ // generic/detail/impl/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/generic/raw_protocol.hpp b/boost/asio/generic/raw_protocol.hpp index dca84e73f7..ae28faf689 100644 --- a/boost/asio/generic/raw_protocol.hpp +++ b/boost/asio/generic/raw_protocol.hpp @@ -2,7 +2,7 @@ // generic/raw_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/generic/seq_packet_protocol.hpp b/boost/asio/generic/seq_packet_protocol.hpp index e54f23e6d9..d9b719f993 100644 --- a/boost/asio/generic/seq_packet_protocol.hpp +++ b/boost/asio/generic/seq_packet_protocol.hpp @@ -2,7 +2,7 @@ // generic/seq_packet_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/generic/stream_protocol.hpp b/boost/asio/generic/stream_protocol.hpp index 599f095dd0..ca5fbb21a1 100644 --- a/boost/asio/generic/stream_protocol.hpp +++ b/boost/asio/generic/stream_protocol.hpp @@ -2,7 +2,7 @@ // generic/stream_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/handler_alloc_hook.hpp b/boost/asio/handler_alloc_hook.hpp index c9636b53ad..595e36bb0d 100644 --- a/boost/asio/handler_alloc_hook.hpp +++ b/boost/asio/handler_alloc_hook.hpp @@ -2,7 +2,7 @@ // handler_alloc_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/handler_continuation_hook.hpp b/boost/asio/handler_continuation_hook.hpp index 4f446b0953..05645cfddf 100644 --- a/boost/asio/handler_continuation_hook.hpp +++ b/boost/asio/handler_continuation_hook.hpp @@ -2,7 +2,7 @@ // handler_continuation_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/handler_invoke_hook.hpp b/boost/asio/handler_invoke_hook.hpp index a853bdfadd..7d3f0fd408 100644 --- a/boost/asio/handler_invoke_hook.hpp +++ b/boost/asio/handler_invoke_hook.hpp @@ -2,7 +2,7 @@ // handler_invoke_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/handler_type.hpp b/boost/asio/handler_type.hpp deleted file mode 100644 index 0c43189338..0000000000 --- a/boost/asio/handler_type.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// handler_type.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_HANDLER_TYPE_HPP -#define BOOST_ASIO_HANDLER_TYPE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> -#include <boost/asio/detail/type_traits.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// (Deprecated: Use two-parameter version of async_result.) Default handler -/// type traits provided for all completion token types. -/** - * The handler_type traits class is used for determining the concrete handler - * type to be used for an asynchronous operation. It allows the handler type to - * be determined at the point where the specific completion handler signature - * is known. - * - * This template may be specialised for user-defined completion token types. - */ -template <typename CompletionToken, typename Signature, typename = void> -struct handler_type -{ - /// The handler type for the specific signature. - typedef typename conditional< - is_same<CompletionToken, typename decay<CompletionToken>::type>::value, - decay<CompletionToken>, - handler_type<typename decay<CompletionToken>::type, Signature> - >::type::type type; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // BOOST_ASIO_HANDLER_TYPE_HPP diff --git a/boost/asio/high_resolution_timer.hpp b/boost/asio/high_resolution_timer.hpp index f7383b7cc9..6050405401 100644 --- a/boost/asio/high_resolution_timer.hpp +++ b/boost/asio/high_resolution_timer.hpp @@ -2,7 +2,7 @@ // high_resolution_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/awaitable.hpp b/boost/asio/impl/awaitable.hpp new file mode 100644 index 0000000000..b8cf5373a1 --- /dev/null +++ b/boost/asio/impl/awaitable.hpp @@ -0,0 +1,424 @@ +// +// impl/awaitable.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IMPL_AWAITABLE_HPP +#define BOOST_ASIO_IMPL_AWAITABLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <exception> +#include <new> +#include <tuple> +#include <utility> +#include <boost/asio/detail/thread_context.hpp> +#include <boost/asio/detail/thread_info_base.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/post.hpp> +#include <boost/system/system_error.hpp> +#include <boost/asio/this_coro.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// An awaitable_thread represents a thread-of-execution that is composed of one +// or more "stack frames", with each frame represented by an awaitable_frame. +// All execution occurs in the context of the awaitable_thread's executor. An +// awaitable_thread continues to "pump" the stack frames by repeatedly resuming +// the top stack frame until the stack is empty, or until ownership of the +// stack is transferred to another awaitable_thread object. +// +// +------------------------------------+ +// | top_of_stack_ | +// | V +// +--------------+---+ +-----------------+ +// | | | | +// | awaitable_thread |<---------------------------+ awaitable_frame | +// | | attached_thread_ | | +// +--------------+---+ (Set only when +---+-------------+ +// | frames are being | +// | actively pumped | caller_ +// | by a thread, and | +// | then only for V +// | the top frame.) +-----------------+ +// | | | +// | | awaitable_frame | +// | | | +// | +---+-------------+ +// | | +// | | caller_ +// | : +// | : +// | | +// | V +// | +-----------------+ +// | bottom_of_stack_ | | +// +------------------------------->| awaitable_frame | +// | | +// +-----------------+ + +template <typename Executor> +class awaitable_frame_base +{ +public: +#if !defined(BOOST_ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING) + void* operator new(std::size_t size) + { + return boost::asio::detail::thread_info_base::allocate( + boost::asio::detail::thread_info_base::awaitable_frame_tag(), + boost::asio::detail::thread_context::thread_call_stack::top(), + size); + } + + void operator delete(void* pointer, std::size_t size) + { + boost::asio::detail::thread_info_base::deallocate( + boost::asio::detail::thread_info_base::awaitable_frame_tag(), + boost::asio::detail::thread_context::thread_call_stack::top(), + pointer, size); + } +#endif // !defined(BOOST_ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING) + + // The frame starts in a suspended state until the awaitable_thread object + // pumps the stack. + auto initial_suspend() noexcept + { + return suspend_always(); + } + + // On final suspension the frame is popped from the top of the stack. + auto final_suspend() noexcept + { + struct result + { + awaitable_frame_base* this_; + + bool await_ready() const noexcept + { + return false; + } + + void await_suspend(coroutine_handle<void>) noexcept + { + this_->pop_frame(); + } + + void await_resume() const noexcept + { + } + }; + + return result{this}; + } + + void set_except(std::exception_ptr e) noexcept + { + pending_exception_ = e; + } + + void set_error(const boost::system::error_code& ec) + { + this->set_except(std::make_exception_ptr(boost::system::system_error(ec))); + } + + void unhandled_exception() + { + set_except(std::current_exception()); + } + + void rethrow_exception() + { + if (pending_exception_) + { + std::exception_ptr ex = std::exchange(pending_exception_, nullptr); + std::rethrow_exception(ex); + } + } + + template <typename T> + auto await_transform(awaitable<T, Executor> a) const + { + return a; + } + + // This await transformation obtains the associated executor of the thread of + // execution. + auto await_transform(this_coro::executor_t) noexcept + { + struct result + { + awaitable_frame_base* this_; + + bool await_ready() const noexcept + { + return true; + } + + void await_suspend(coroutine_handle<void>) noexcept + { + } + + auto await_resume() const noexcept + { + return this_->attached_thread_->get_executor(); + } + }; + + return result{this}; + } + + // This await transformation is used to run an async operation's initiation + // function object after the coroutine has been suspended. This ensures that + // immediate resumption of the coroutine in another thread does not cause a + // race condition. + template <typename Function> + auto await_transform(Function f, + typename enable_if< + is_convertible< + typename result_of<Function(awaitable_frame_base*)>::type, + awaitable_thread<Executor>* + >::value + >::type* = 0) + { + struct result + { + Function function_; + awaitable_frame_base* this_; + + bool await_ready() const noexcept + { + return false; + } + + void await_suspend(coroutine_handle<void>) noexcept + { + function_(this_); + } + + void await_resume() const noexcept + { + } + }; + + return result{std::move(f), this}; + } + + void attach_thread(awaitable_thread<Executor>* handler) noexcept + { + attached_thread_ = handler; + } + + awaitable_thread<Executor>* detach_thread() noexcept + { + return std::exchange(attached_thread_, nullptr); + } + + void push_frame(awaitable_frame_base<Executor>* caller) noexcept + { + caller_ = caller; + attached_thread_ = caller_->attached_thread_; + attached_thread_->top_of_stack_ = this; + caller_->attached_thread_ = nullptr; + } + + void pop_frame() noexcept + { + if (caller_) + caller_->attached_thread_ = attached_thread_; + attached_thread_->top_of_stack_ = caller_; + attached_thread_ = nullptr; + caller_ = nullptr; + } + + void resume() + { + coro_.resume(); + } + + void destroy() + { + coro_.destroy(); + } + +protected: + coroutine_handle<void> coro_ = nullptr; + awaitable_thread<Executor>* attached_thread_ = nullptr; + awaitable_frame_base<Executor>* caller_ = nullptr; + std::exception_ptr pending_exception_ = nullptr; +}; + +template <typename T, typename Executor> +class awaitable_frame + : public awaitable_frame_base<Executor> +{ +public: + awaitable_frame() noexcept + { + } + + awaitable_frame(awaitable_frame&& other) noexcept + : awaitable_frame_base<Executor>(std::move(other)) + { + } + + ~awaitable_frame() + { + if (has_result_) + static_cast<T*>(static_cast<void*>(result_))->~T(); + } + + awaitable<T, Executor> get_return_object() noexcept + { + this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this); + return awaitable<T, Executor>(this); + }; + + template <typename U> + void return_value(U&& u) + { + new (&result_) T(std::forward<U>(u)); + has_result_ = true; + } + + template <typename... Us> + void return_values(Us&&... us) + { + this->return_value(std::forward_as_tuple(std::forward<Us>(us)...)); + } + + T get() + { + this->caller_ = nullptr; + this->rethrow_exception(); + return std::move(*static_cast<T*>(static_cast<void*>(result_))); + } + +private: + alignas(T) unsigned char result_[sizeof(T)]; + bool has_result_ = false; +}; + +template <typename Executor> +class awaitable_frame<void, Executor> + : public awaitable_frame_base<Executor> +{ +public: + awaitable<void, Executor> get_return_object() + { + this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this); + return awaitable<void, Executor>(this); + }; + + void return_void() + { + } + + void get() + { + this->caller_ = nullptr; + this->rethrow_exception(); + } +}; + +template <typename Executor> +class awaitable_thread +{ +public: + typedef Executor executor_type; + + // Construct from the entry point of a new thread of execution. + awaitable_thread(awaitable<void, Executor> p, const Executor& ex) + : bottom_of_stack_(std::move(p)), + top_of_stack_(bottom_of_stack_.frame_), + executor_(ex) + { + } + + // Transfer ownership from another awaitable_thread. + awaitable_thread(awaitable_thread&& other) noexcept + : bottom_of_stack_(std::move(other.bottom_of_stack_)), + top_of_stack_(std::exchange(other.top_of_stack_, nullptr)), + executor_(std::move(other.executor_)) + { + } + + // Clean up with a last ditch effort to ensure the thread is unwound within + // the context of the executor. + ~awaitable_thread() + { + if (bottom_of_stack_.valid()) + { + // Coroutine "stack unwinding" must be performed through the executor. + (post)(executor_, + [a = std::move(bottom_of_stack_)]() mutable + { + awaitable<void, Executor>(std::move(a)); + }); + } + } + + executor_type get_executor() const noexcept + { + return executor_; + } + + // Launch a new thread of execution. + void launch() + { + top_of_stack_->attach_thread(this); + pump(); + } + +protected: + template <typename> friend class awaitable_frame_base; + + // Repeatedly resume the top stack frame until the stack is empty or until it + // has been transferred to another resumable_thread object. + void pump() + { + do top_of_stack_->resume(); while (top_of_stack_); + if (bottom_of_stack_.valid()) + { + awaitable<void, Executor> a(std::move(bottom_of_stack_)); + a.frame_->rethrow_exception(); + } + } + + awaitable<void, Executor> bottom_of_stack_; + awaitable_frame_base<Executor>* top_of_stack_; + executor_type executor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#if !defined(GENERATING_DOCUMENTATION) + +namespace std { namespace experimental { + +template <typename T, typename Executor, typename... Args> +struct coroutine_traits<boost::asio::awaitable<T, Executor>, Args...> +{ + typedef boost::asio::detail::awaitable_frame<T, Executor> promise_type; +}; + +}} // namespace std::experimental + +#endif // !defined(GENERATING_DOCUMENTATION) + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_IMPL_AWAITABLE_HPP diff --git a/boost/asio/impl/buffered_read_stream.hpp b/boost/asio/impl/buffered_read_stream.hpp index 2e1c55842b..6a51d8ee56 100644 --- a/boost/asio/impl/buffered_read_stream.hpp +++ b/boost/asio/impl/buffered_read_stream.hpp @@ -2,7 +2,7 @@ // impl/buffered_read_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,6 +21,7 @@ #include <boost/asio/detail/handler_cont_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/push_options.hpp> @@ -138,6 +139,28 @@ namespace detail boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_buffered_fill + { + template <typename ReadHandler, typename Stream> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> 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<typename decay<ReadHandler>::type>( + *storage, previous_size, handler2.value)); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -177,24 +200,9 @@ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, buffered_read_stream<Stream>::async_fill( BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> 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<BOOST_ASIO_HANDLER_TYPE( - ReadHandler, void (boost::system::error_code, std::size_t))>( - storage_, previous_size, init.completion_handler)); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_buffered_fill(), handler, &storage_, &next_layer_); } template <typename Stream> @@ -327,6 +335,38 @@ namespace detail boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_buffered_read_some + { + template <typename ReadHandler, typename Stream, + typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + using boost::asio::buffer_size; + non_const_lvalue<ReadHandler> handler2(handler); + if (buffer_size(buffers) == 0 || !storage->empty()) + { + next_layer->async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0), + buffered_read_some_handler<MutableBufferSequence, + typename decay<ReadHandler>::type>( + *storage, buffers, handler2.value)); + } + else + { + initiate_async_buffered_fill()( + buffered_read_some_handler<MutableBufferSequence, + typename decay<ReadHandler>::type>( + *storage, buffers, handler2.value), + storage, next_layer); + } + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -375,31 +415,10 @@ buffered_read_stream<Stream>::async_read_some( const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - using boost::asio::buffer_size; - if (buffer_size(buffers) == 0 || !storage_.empty()) - { - next_layer_.async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0), - detail::buffered_read_some_handler< - MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE( - ReadHandler, void (boost::system::error_code, std::size_t))>( - storage_, buffers, init.completion_handler)); - } - else - { - this->async_fill(detail::buffered_read_some_handler< - MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE( - ReadHandler, void (boost::system::error_code, std::size_t))>( - storage_, buffers, init.completion_handler)); - } - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_buffered_read_some(), + handler, &storage_, &next_layer_, buffers); } template <typename Stream> diff --git a/boost/asio/impl/buffered_write_stream.hpp b/boost/asio/impl/buffered_write_stream.hpp index c5ebf7537b..05d4406347 100644 --- a/boost/asio/impl/buffered_write_stream.hpp +++ b/boost/asio/impl/buffered_write_stream.hpp @@ -2,7 +2,7 @@ // impl/buffered_write_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -21,6 +21,7 @@ #include <boost/asio/detail/handler_cont_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/push_options.hpp> @@ -124,6 +125,23 @@ namespace detail boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_buffered_flush + { + template <typename WriteHandler, typename Stream> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue<WriteHandler> handler2(handler); + async_write(*next_layer, buffer(storage->data(), storage->size()), + buffered_flush_handler<typename decay<WriteHandler>::type>( + *storage, handler2.value)); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -163,19 +181,10 @@ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, buffered_write_stream<Stream>::async_flush( BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - async_write(next_layer_, buffer(storage_.data(), storage_.size()), - detail::buffered_flush_handler<BOOST_ASIO_HANDLER_TYPE( - WriteHandler, void (boost::system::error_code, std::size_t))>( - storage_, init.completion_handler)); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_buffered_flush(), + handler, &storage_, &next_layer_); } template <typename Stream> @@ -314,6 +323,38 @@ namespace detail boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_buffered_write_some + { + template <typename WriteHandler, typename Stream, + typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + using boost::asio::buffer_size; + non_const_lvalue<WriteHandler> handler2(handler); + if (buffer_size(buffers) == 0 || storage->size() < storage->capacity()) + { + next_layer->async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0), + buffered_write_some_handler<ConstBufferSequence, + typename decay<WriteHandler>::type>( + *storage, buffers, handler2.value)); + } + else + { + initiate_async_buffered_flush()( + buffered_write_some_handler<ConstBufferSequence, + typename decay<WriteHandler>::type>( + *storage, buffers, handler2.value), + storage, next_layer); + } + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -362,32 +403,10 @@ buffered_write_stream<Stream>::async_write_some( const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - using boost::asio::buffer_size; - if (buffer_size(buffers) == 0 - || storage_.size() < storage_.capacity()) - { - next_layer_.async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0), - detail::buffered_write_some_handler< - ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE( - WriteHandler, void (boost::system::error_code, std::size_t))>( - storage_, buffers, init.completion_handler)); - } - else - { - this->async_flush(detail::buffered_write_some_handler< - ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE( - WriteHandler, void (boost::system::error_code, std::size_t))>( - storage_, buffers, init.completion_handler)); - } - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_buffered_write_some(), + handler, &storage_, &next_layer_, buffers); } template <typename Stream> diff --git a/boost/asio/impl/co_spawn.hpp b/boost/asio/impl/co_spawn.hpp new file mode 100644 index 0000000000..19770cd865 --- /dev/null +++ b/boost/asio/impl/co_spawn.hpp @@ -0,0 +1,140 @@ +// +// impl/co_spawn.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IMPL_CO_SPAWN_HPP +#define BOOST_ASIO_IMPL_CO_SPAWN_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/awaitable.hpp> +#include <boost/asio/dispatch.hpp> +#include <boost/asio/post.hpp> +#include <boost/asio/use_awaitable.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename T, typename Executor, typename F, typename Handler> +awaitable<void, Executor> co_spawn_entry_point( + awaitable<T, Executor>*, Executor ex, F f, Handler handler) +{ + auto spawn_work = make_work_guard(ex); + auto handler_work = make_work_guard(handler, ex); + + (void) co_await (post)(spawn_work.get_executor(), + use_awaitable_t<Executor>{}); + + bool done = false; + try + { + T t = co_await f(); + + done = true; + + (dispatch)(handler_work.get_executor(), + [handler = std::move(handler), t = std::move(t)]() mutable + { + handler(std::exception_ptr(), std::move(t)); + }); + } + catch (...) + { + if (done) + throw; + + (dispatch)(handler_work.get_executor(), + [handler = std::move(handler), e = std::current_exception()]() mutable + { + handler(e, T()); + }); + } +} + +template <typename Executor, typename F, typename Handler> +awaitable<void, Executor> co_spawn_entry_point( + awaitable<void, Executor>*, Executor ex, F f, Handler handler) +{ + auto spawn_work = make_work_guard(ex); + auto handler_work = make_work_guard(handler, ex); + + (void) co_await (post)(spawn_work.get_executor(), + use_awaitable_t<Executor>{}); + + std::exception_ptr e = nullptr; + try + { + co_await f(); + } + catch (...) + { + e = std::current_exception(); + } + + (dispatch)(handler_work.get_executor(), + [handler = std::move(handler), e]() mutable + { + handler(e); + }); +} + +struct initiate_co_spawn +{ + template <typename Handler, typename Executor, typename F> + void operator()(Handler&& handler, const Executor& ex, F&& f) const + { + typedef typename result_of<F()>::type awaitable_type; + typedef typename awaitable_type::executor_type executor_type; + + executor_type ex2(ex); + auto a = (co_spawn_entry_point)(static_cast<awaitable_type*>(nullptr), + ex2, std::forward<F>(f), std::forward<Handler>(handler)); + awaitable_handler<executor_type, void>(std::move(a), ex2).launch(); + } +}; + +} // namespace detail + +template <typename Executor, typename F, typename CompletionToken> +inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, + typename detail::awaitable_signature<typename result_of<F()>::type>::type) +co_spawn(const Executor& ex, F&& f, CompletionToken&& token, + typename enable_if< + is_executor<Executor>::value + >::type*) +{ + return async_initiate<CompletionToken, + typename detail::awaitable_signature<typename result_of<F()>::type>>( + detail::initiate_co_spawn(), token, ex, std::forward<F>(f)); +} + +template <typename ExecutionContext, typename F, typename CompletionToken> +inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, + typename detail::awaitable_signature<typename result_of<F()>::type>::type) +co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type*) +{ + return (co_spawn)(ctx.get_executor(), std::forward<F>(f), + std::forward<CompletionToken>(token)); +} + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_IMPL_CO_SPAWN_HPP diff --git a/boost/asio/impl/compose.hpp b/boost/asio/impl/compose.hpp new file mode 100644 index 0000000000..76fe54d066 --- /dev/null +++ b/boost/asio/impl/compose.hpp @@ -0,0 +1,421 @@ +// +// impl/compose.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IMPL_COMPOSE_HPP +#define BOOST_ASIO_IMPL_COMPOSE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/handler_alloc_helpers.hpp> +#include <boost/asio/detail/handler_cont_helpers.hpp> +#include <boost/asio/detail/handler_invoke_helpers.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/detail/variadic_templates.hpp> +#include <boost/asio/executor_work_guard.hpp> +#include <boost/asio/is_executor.hpp> +#include <boost/asio/system_executor.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +namespace detail +{ + template <typename> + struct composed_work; + + template <> + struct composed_work<void()> + { + composed_work() BOOST_ASIO_NOEXCEPT + : head_(system_executor()) + { + } + + void reset() + { + head_.reset(); + } + + typedef system_executor head_type; + executor_work_guard<system_executor> head_; + }; + + inline composed_work<void()> make_composed_work() + { + return composed_work<void()>(); + } + + template <typename Head> + struct composed_work<void(Head)> + { + explicit composed_work(const Head& ex) BOOST_ASIO_NOEXCEPT + : head_(ex) + { + } + + void reset() + { + head_.reset(); + } + + typedef Head head_type; + executor_work_guard<Head> head_; + }; + + template <typename Head> + inline composed_work<void(Head)> make_composed_work(const Head& head) + { + return composed_work<void(Head)>(head); + } + +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename Head, typename... Tail> + struct composed_work<void(Head, Tail...)> + { + explicit composed_work(const Head& head, + const Tail&... tail) BOOST_ASIO_NOEXCEPT + : head_(head), + tail_(tail...) + { + } + + void reset() + { + head_.reset(); + tail_.reset(); + } + + typedef Head head_type; + executor_work_guard<Head> head_; + composed_work<void(Tail...)> tail_; + }; + + template <typename Head, typename... Tail> + inline composed_work<void(Head, Tail...)> + make_composed_work(const Head& head, const Tail&... tail) + { + return composed_work<void(Head, Tail...)>(head, tail...); + } + +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +#define BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \ + template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + struct composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \ + { \ + explicit composed_work(const Head& head, \ + BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) BOOST_ASIO_NOEXCEPT \ + : head_(head), \ + tail_(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) \ + { \ + } \ + \ + void reset() \ + { \ + head_.reset(); \ + tail_.reset(); \ + } \ + \ + typedef Head head_type; \ + executor_work_guard<Head> head_; \ + composed_work<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \ + }; \ + \ + template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + inline composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \ + make_composed_work(const Head& head, BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) \ + { \ + return composed_work< \ + void(Head, BOOST_ASIO_VARIADIC_TARGS(n))>( \ + head, BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)); \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF) +#undef BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + template <typename Impl, typename Work, typename Handler, typename Signature> + class composed_op; + + template <typename Impl, typename Work, typename Handler, + typename R, typename... Args> + class composed_op<Impl, Work, Handler, R(Args...)> +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + template <typename Impl, typename Work, typename Handler, typename Signature> + class composed_op +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + { + public: + composed_op(BOOST_ASIO_MOVE_ARG(Impl) impl, + BOOST_ASIO_MOVE_ARG(Work) work, + BOOST_ASIO_MOVE_ARG(Handler) handler) + : impl_(BOOST_ASIO_MOVE_CAST(Impl)(impl)), + work_(BOOST_ASIO_MOVE_CAST(Work)(work)), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + invocations_(0) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + composed_op(composed_op&& other) + : impl_(BOOST_ASIO_MOVE_CAST(Impl)(other.impl_)), + work_(BOOST_ASIO_MOVE_CAST(Work)(other.work_)), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)), + invocations_(other.invocations_) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + typedef typename associated_executor<Handler, + typename Work::head_type>::type executor_type; + + executor_type get_executor() const BOOST_ASIO_NOEXCEPT + { + return (get_associated_executor)(handler_, work_.head_.get_executor()); + } + + typedef typename associated_allocator<Handler, + std::allocator<void> >::type allocator_type; + + allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT + { + return (get_associated_allocator)(handler_, std::allocator<void>()); + } + +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + template<typename... T> + void operator()(BOOST_ASIO_MOVE_ARG(T)... t) + { + if (invocations_ < ~unsigned(0)) + ++invocations_; + impl_(*this, BOOST_ASIO_MOVE_CAST(T)(t)...); + } + + void complete(Args... args) + { + this->work_.reset(); + this->handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...); + } + +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + void operator()() + { + if (invocations_ < ~unsigned(0)) + ++invocations_; + impl_(*this); + } + + void complete() + { + this->work_.reset(); + this->handler_(); + } + +#define BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF(n) \ + template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + if (invocations_ < ~unsigned(0)) \ + ++invocations_; \ + impl_(*this, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + \ + template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + void complete(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + this->work_.reset(); \ + this->handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF) +#undef BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + //private: + Impl impl_; + Work work_; + Handler handler_; + unsigned invocations_; + }; + + template <typename Impl, typename Work, typename Handler, typename Signature> + inline void* asio_handler_allocate(std::size_t size, + composed_op<Impl, Work, Handler, Signature>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename Impl, typename Work, typename Handler, typename Signature> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + composed_op<Impl, Work, Handler, Signature>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename Impl, typename Work, typename Handler, typename Signature> + inline bool asio_handler_is_continuation( + composed_op<Impl, Work, Handler, Signature>* this_handler) + { + return this_handler->invocations_ > 1 ? true + : boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename Impl, + typename Work, typename Handler, typename Signature> + inline void asio_handler_invoke(Function& function, + composed_op<Impl, Work, Handler, Signature>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename Impl, + typename Work, typename Handler, typename Signature> + inline void asio_handler_invoke(const Function& function, + composed_op<Impl, Work, Handler, Signature>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Signature> + struct initiate_composed_op + { + template <typename Handler, typename Impl, typename Work> + void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler, + BOOST_ASIO_MOVE_ARG(Impl) impl, + BOOST_ASIO_MOVE_ARG(Work) work) const + { + composed_op<typename decay<Impl>::type, typename decay<Work>::type, + typename decay<Handler>::type, Signature>( + BOOST_ASIO_MOVE_CAST(Impl)(impl), BOOST_ASIO_MOVE_CAST(Work)(work), + BOOST_ASIO_MOVE_CAST(Handler)(handler))(); + } + }; + + template <typename IoObject> + inline typename IoObject::executor_type + get_composed_io_executor(IoObject& io_object) + { + return io_object.get_executor(); + } + + template <typename Executor> + inline const Executor& get_composed_io_executor(const Executor& ex, + typename enable_if<is_executor<Executor>::value>::type* = 0) + { + return ex; + } +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename CompletionToken, typename Signature, + typename Implementation, typename... IoObjectsOrExecutors> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) +async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors) +{ + return async_initiate<CompletionToken, Signature>( + detail::initiate_composed_op<Signature>(), token, + BOOST_ASIO_MOVE_CAST(Implementation)(implementation), + detail::make_composed_work( + detail::get_composed_io_executor( + BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)( + io_objects_or_executors))...)); +} + +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename CompletionToken, typename Signature, typename Implementation> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) +async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) +{ + return async_initiate<CompletionToken, Signature>( + detail::initiate_composed_op<Signature>(), token, + BOOST_ASIO_MOVE_CAST(Implementation)(implementation), + detail::make_composed_work()); +} + +# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \ + BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n + +# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)) +# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)) +# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)) +# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)) +# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \ + detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5)) + +#define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \ + template <typename CompletionToken, typename Signature, \ + typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) \ + async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \ + BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ + BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + return async_initiate<CompletionToken, Signature>( \ + detail::initiate_composed_op<Signature>(), token, \ + BOOST_ASIO_MOVE_CAST(Implementation)(implementation), \ + detail::make_composed_work( \ + BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))); \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF) +#undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF + +#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR +#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 +#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 +#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 +#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 +#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_IMPL_COMPOSE_HPP diff --git a/boost/asio/impl/connect.hpp b/boost/asio/impl/connect.hpp index 497f25884c..51e5e6cb16 100644 --- a/boost/asio/impl/connect.hpp +++ b/boost/asio/impl/connect.hpp @@ -2,7 +2,7 @@ // impl/connect.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -23,6 +23,7 @@ #include <boost/asio/detail/handler_cont_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> #include <boost/asio/post.hpp> @@ -101,9 +102,8 @@ namespace detail } } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence> -typename Protocol::endpoint connect( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename EndpointSequence> +typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, typename enable_if<is_endpoint_sequence< EndpointSequence>::value>::type*) @@ -114,9 +114,8 @@ typename Protocol::endpoint connect( return result; } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence> -typename Protocol::endpoint connect( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename EndpointSequence> +typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, boost::system::error_code& ec, typename enable_if<is_endpoint_sequence< EndpointSequence>::value>::type*) @@ -127,8 +126,8 @@ typename Protocol::endpoint connect( } #if !defined(BOOST_ASIO_NO_DEPRECATED) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, +template <typename Protocol, typename Executor, typename Iterator> +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) { boost::system::error_code ec; @@ -137,8 +136,8 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin, return result; } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator> -inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename Iterator> +inline Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, boost::system::error_code& ec, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) { @@ -146,8 +145,8 @@ inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename Iterator> +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end) { boost::system::error_code ec; @@ -156,17 +155,16 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, return result; } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator> -inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +template <typename Protocol, typename Executor, typename Iterator> +inline Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, boost::system::error_code& ec) { return connect(s, begin, end, detail::default_connect_condition(), ec); } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition> -typename Protocol::endpoint connect( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, typename enable_if<is_endpoint_sequence< EndpointSequence>::value>::type*) @@ -178,10 +176,9 @@ typename Protocol::endpoint connect( return result; } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition> -typename Protocol::endpoint connect( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, boost::system::error_code& ec, typename enable_if<is_endpoint_sequence< @@ -193,9 +190,9 @@ typename Protocol::endpoint connect( } #if !defined(BOOST_ASIO_NO_DEPRECATED) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) { @@ -205,9 +202,9 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, return result; } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> -inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +inline Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, boost::system::error_code& ec, typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) @@ -216,10 +213,10 @@ inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, Iterator end, ConnectCondition connect_condition) +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, + Iterator end, ConnectCondition connect_condition) { boost::system::error_code ec; Iterator result = connect(s, begin, end, connect_condition, ec); @@ -227,10 +224,10 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, return result; } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> -Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, Iterator end, ConnectCondition connect_condition, +Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, + Iterator end, ConnectCondition connect_condition, boost::system::error_code& ec) { ec = boost::system::error_code(); @@ -295,13 +292,12 @@ namespace detail } }; - template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename EndpointSequence, typename ConnectCondition, - typename RangeConnectHandler> + template <typename Protocol, typename Executor, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler> class range_connect_op : base_from_connect_condition<ConnectCondition> { public: - range_connect_op(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& sock, + range_connect_op(basic_socket<Protocol, Executor>& sock, const EndpointSequence& endpoints, const ConnectCondition& connect_condition, RangeConnectHandler& handler) @@ -338,10 +334,18 @@ namespace detail void operator()(boost::system::error_code ec, int start = 0) { - typename EndpointSequence::const_iterator begin = endpoints_.begin(); - typename EndpointSequence::const_iterator iter = begin; + this->process(ec, start, + const_cast<const EndpointSequence&>(endpoints_).begin(), + const_cast<const EndpointSequence&>(endpoints_).end()); + } + + //private: + template <typename Iterator> + void process(boost::system::error_code ec, + int start, Iterator begin, Iterator end) + { + Iterator iter = begin; std::advance(iter, index_); - typename EndpointSequence::const_iterator end = endpoints_.end(); switch (start_ = start) { @@ -392,75 +396,92 @@ namespace detail } } - //private: - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket_; + basic_socket<Protocol, Executor>& socket_; EndpointSequence endpoints_; std::size_t index_; int start_; RangeConnectHandler handler_; }; - template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename EndpointSequence, typename ConnectCondition, - typename RangeConnectHandler> + template <typename Protocol, typename Executor, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler> inline void* asio_handler_allocate(std::size_t size, - range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence, + range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, RangeConnectHandler>* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } - template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename EndpointSequence, typename ConnectCondition, - typename RangeConnectHandler> + template <typename Protocol, typename Executor, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence, + range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, RangeConnectHandler>* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } - template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename EndpointSequence, typename ConnectCondition, - typename RangeConnectHandler> + template <typename Protocol, typename Executor, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler> inline bool asio_handler_is_continuation( - range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence, + range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, RangeConnectHandler>* this_handler) { return boost_asio_handler_cont_helpers::is_continuation( this_handler->handler_); } - template <typename Function, typename Protocol - BOOST_ASIO_SVC_TPARAM, typename EndpointSequence, - typename ConnectCondition, typename RangeConnectHandler> + template <typename Function, typename Executor, typename Protocol, + typename EndpointSequence, typename ConnectCondition, + typename RangeConnectHandler> inline void asio_handler_invoke(Function& function, - range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence, + range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, RangeConnectHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } - template <typename Function, typename Protocol - BOOST_ASIO_SVC_TPARAM, typename EndpointSequence, - typename ConnectCondition, typename RangeConnectHandler> + template <typename Function, typename Executor, typename Protocol, + typename EndpointSequence, typename ConnectCondition, + typename RangeConnectHandler> inline void asio_handler_invoke(const Function& function, - range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence, + range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, RangeConnectHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } - template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator, + struct initiate_async_range_connect + { + template <typename RangeConnectHandler, typename Protocol, + typename Executor, typename EndpointSequence, typename ConnectCondition> + void operator()(BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler, + basic_socket<Protocol, Executor>* 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. + BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler, + handler, typename Protocol::endpoint) type_check; + + non_const_lvalue<RangeConnectHandler> handler2(handler); + range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, + typename decay<RangeConnectHandler>::type>(*s, endpoints, + connect_condition, handler2.value)(boost::system::error_code(), 1); + } + }; + + template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> class iterator_connect_op : base_from_connect_condition<ConnectCondition> { public: - iterator_connect_op(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& sock, + iterator_connect_op(basic_socket<Protocol, Executor>& sock, const Iterator& begin, const Iterator& end, const ConnectCondition& connect_condition, IteratorConnectHandler& handler) @@ -544,82 +565,101 @@ namespace detail } //private: - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket_; + basic_socket<Protocol, Executor>& socket_; Iterator iter_; Iterator end_; int start_; IteratorConnectHandler handler_; }; - template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator, + template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> inline void* asio_handler_allocate(std::size_t size, - iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, + iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } - template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator, + template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, + iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } - template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator, + template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> inline bool asio_handler_is_continuation( - iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, + iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>* this_handler) { return boost_asio_handler_cont_helpers::is_continuation( this_handler->handler_); } - template <typename Function, typename Protocol - BOOST_ASIO_SVC_TPARAM, typename Iterator, - typename ConnectCondition, typename IteratorConnectHandler> + template <typename Function, typename Executor, typename Protocol, + typename Iterator, typename ConnectCondition, + typename IteratorConnectHandler> inline void asio_handler_invoke(Function& function, - iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, + iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } - template <typename Function, typename Protocol - BOOST_ASIO_SVC_TPARAM, typename Iterator, - typename ConnectCondition, typename IteratorConnectHandler> + template <typename Function, typename Executor, typename Protocol, + typename Iterator, typename ConnectCondition, + typename IteratorConnectHandler> inline void asio_handler_invoke(const Function& function, - iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, + iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_iterator_connect + { + template <typename IteratorConnectHandler, typename Protocol, + typename Executor, typename Iterator, typename ConnectCondition> + void operator()(BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, + basic_socket<Protocol, Executor>* 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. + BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( + IteratorConnectHandler, handler, Iterator) type_check; + + non_const_lvalue<IteratorConnectHandler> handler2(handler); + iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, + typename decay<IteratorConnectHandler>::type>(*s, begin, end, + connect_condition, handler2.value)(boost::system::error_code(), 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename EndpointSequence, typename ConnectCondition, - typename RangeConnectHandler, typename Allocator> +template <typename Protocol, typename Executor, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler, typename Allocator> struct associated_allocator< - detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, - EndpointSequence, ConnectCondition, RangeConnectHandler>, - Allocator> + detail::range_connect_op<Protocol, Executor, EndpointSequence, + ConnectCondition, RangeConnectHandler>, Allocator> { typedef typename associated_allocator< RangeConnectHandler, Allocator>::type type; static type get( - const detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, - EndpointSequence, ConnectCondition, RangeConnectHandler>& h, + const detail::range_connect_op<Protocol, Executor, EndpointSequence, + ConnectCondition, RangeConnectHandler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator<RangeConnectHandler, @@ -627,40 +667,38 @@ struct associated_allocator< } }; -template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename EndpointSequence, typename ConnectCondition, - typename RangeConnectHandler, typename Executor> +template <typename Protocol, typename Executor, typename EndpointSequence, + typename ConnectCondition, typename RangeConnectHandler, typename Executor1> struct associated_executor< - detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, - EndpointSequence, ConnectCondition, RangeConnectHandler>, - Executor> + detail::range_connect_op<Protocol, Executor, EndpointSequence, + ConnectCondition, RangeConnectHandler>, Executor1> { typedef typename associated_executor< - RangeConnectHandler, Executor>::type type; + RangeConnectHandler, Executor1>::type type; static type get( - const detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, - EndpointSequence, ConnectCondition, RangeConnectHandler>& h, - const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + const detail::range_connect_op<Protocol, Executor, EndpointSequence, + ConnectCondition, RangeConnectHandler>& h, + const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT { return associated_executor<RangeConnectHandler, - Executor>::get(h.handler_, ex); + Executor1>::get(h.handler_, ex); } }; -template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename Iterator, typename ConnectCondition, - typename IteratorConnectHandler, typename Allocator> +template <typename Protocol, typename Executor, typename Iterator, + typename ConnectCondition, typename IteratorConnectHandler, + typename Allocator> struct associated_allocator< - detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, - ConnectCondition, IteratorConnectHandler>, + detail::iterator_connect_op<Protocol, Executor, + Iterator, ConnectCondition, IteratorConnectHandler>, Allocator> { typedef typename associated_allocator< IteratorConnectHandler, Allocator>::type type; static type get( - const detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, + const detail::iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { @@ -669,189 +707,119 @@ struct associated_allocator< } }; -template <typename Protocol BOOST_ASIO_SVC_TPARAM, - typename Iterator, typename ConnectCondition, - typename IteratorConnectHandler, typename Executor> +template <typename Protocol, typename Executor, typename Iterator, + typename ConnectCondition, typename IteratorConnectHandler, + typename Executor1> struct associated_executor< - detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, - ConnectCondition, IteratorConnectHandler>, - Executor> + detail::iterator_connect_op<Protocol, Executor, + Iterator, ConnectCondition, IteratorConnectHandler>, + Executor1> { typedef typename associated_executor< - IteratorConnectHandler, Executor>::type type; + IteratorConnectHandler, Executor1>::type type; static type get( - const detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, + const detail::iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>& h, - const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT { return associated_executor<IteratorConnectHandler, - Executor>::get(h.handler_, ex); + Executor1>::get(h.handler_, ex); } }; #endif // !defined(GENERATING_DOCUMENTATION) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename EndpointSequence, typename RangeConnectHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler, void (boost::system::error_code, typename Protocol::endpoint)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler, typename enable_if<is_endpoint_sequence< EndpointSequence>::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. - BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( - RangeConnectHandler, handler, typename Protocol::endpoint) type_check; - - async_completion<RangeConnectHandler, - void (boost::system::error_code, typename Protocol::endpoint)> - init(handler); - - detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence, - detail::default_connect_condition, - BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler, - void (boost::system::error_code, typename Protocol::endpoint))>(s, - endpoints, detail::default_connect_condition(), - init.completion_handler)(boost::system::error_code(), 1); - - return init.result.get(); + return async_initiate<RangeConnectHandler, + void (boost::system::error_code, typename Protocol::endpoint)>( + detail::initiate_async_range_connect(), handler, + &s, endpoints, detail::default_connect_condition()); } #if !defined(BOOST_ASIO_NO_DEPRECATED) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename IteratorConnectHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (boost::system::error_code, Iterator)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, +async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, + BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, typename enable_if<!is_endpoint_sequence<Iterator>::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. - BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( - IteratorConnectHandler, handler, Iterator) type_check; - - async_completion<IteratorConnectHandler, - void (boost::system::error_code, Iterator)> init(handler); - - detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, - detail::default_connect_condition, BOOST_ASIO_HANDLER_TYPE( - IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s, - begin, Iterator(), detail::default_connect_condition(), - init.completion_handler)(boost::system::error_code(), 1); - - return init.result.get(); + return async_initiate<IteratorConnectHandler, + void (boost::system::error_code, Iterator)>( + detail::initiate_async_iterator_connect(), handler, + &s, begin, Iterator(), detail::default_connect_condition()); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, +template <typename Protocol, typename Executor, typename Iterator, typename IteratorConnectHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (boost::system::error_code, Iterator)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, Iterator end, +async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, BOOST_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. - BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( - IteratorConnectHandler, handler, Iterator) type_check; - - async_completion<IteratorConnectHandler, - void (boost::system::error_code, Iterator)> init(handler); - - detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, - detail::default_connect_condition, BOOST_ASIO_HANDLER_TYPE( - IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s, - begin, end, detail::default_connect_condition(), - init.completion_handler)(boost::system::error_code(), 1); - - return init.result.get(); + return async_initiate<IteratorConnectHandler, + void (boost::system::error_code, Iterator)>( + detail::initiate_async_iterator_connect(), handler, + &s, begin, end, detail::default_connect_condition()); } -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence, +template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition, typename RangeConnectHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler, void (boost::system::error_code, typename Protocol::endpoint)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, +async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler, typename enable_if<is_endpoint_sequence< EndpointSequence>::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. - BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( - RangeConnectHandler, handler, typename Protocol::endpoint) type_check; - - async_completion<RangeConnectHandler, - void (boost::system::error_code, typename Protocol::endpoint)> - init(handler); - - detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence, - ConnectCondition, BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler, - void (boost::system::error_code, typename Protocol::endpoint))>(s, - endpoints, connect_condition, init.completion_handler)( - boost::system::error_code(), 1); - - return init.result.get(); + return async_initiate<RangeConnectHandler, + void (boost::system::error_code, typename Protocol::endpoint)>( + detail::initiate_async_range_connect(), + handler, &s, endpoints, connect_condition); } #if !defined(BOOST_ASIO_NO_DEPRECATED) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (boost::system::error_code, Iterator)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, ConnectCondition connect_condition, +async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, + ConnectCondition connect_condition, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, typename enable_if<!is_endpoint_sequence<Iterator>::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. - BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( - IteratorConnectHandler, handler, Iterator) type_check; - - async_completion<IteratorConnectHandler, - void (boost::system::error_code, Iterator)> init(handler); - - detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, - ConnectCondition, BOOST_ASIO_HANDLER_TYPE( - IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s, - begin, Iterator(), connect_condition, init.completion_handler)( - boost::system::error_code(), 1); - - return init.result.get(); + return async_initiate<IteratorConnectHandler, + void (boost::system::error_code, Iterator)>( + detail::initiate_async_iterator_connect(), + handler, &s, begin, Iterator(), connect_condition); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator, +template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler, void (boost::system::error_code, Iterator)) -async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, - Iterator begin, Iterator end, ConnectCondition connect_condition, +async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, + Iterator end, ConnectCondition connect_condition, BOOST_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. - BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( - IteratorConnectHandler, handler, Iterator) type_check; - - async_completion<IteratorConnectHandler, - void (boost::system::error_code, Iterator)> init(handler); - - detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator, - ConnectCondition, BOOST_ASIO_HANDLER_TYPE( - IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s, - begin, end, connect_condition, init.completion_handler)( - boost::system::error_code(), 1); - - return init.result.get(); + return async_initiate<IteratorConnectHandler, + void (boost::system::error_code, Iterator)>( + detail::initiate_async_iterator_connect(), + handler, &s, begin, end, connect_condition); } } // namespace asio diff --git a/boost/asio/impl/defer.hpp b/boost/asio/impl/defer.hpp index 7cc86da45c..856a33c788 100644 --- a/boost/asio/impl/defer.hpp +++ b/boost/asio/impl/defer.hpp @@ -2,7 +2,7 @@ // impl/defer.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -24,24 +24,46 @@ namespace boost { namespace asio { +namespace detail { -template <typename CompletionToken> -BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer( - BOOST_ASIO_MOVE_ARG(CompletionToken) token) +struct initiate_defer { - typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler; + template <typename CompletionHandler> + void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const + { + typedef typename decay<CompletionHandler>::type DecayedHandler; + + typename associated_executor<DecayedHandler>::type ex( + (get_associated_executor)(handler)); - async_completion<CompletionToken, void()> init(token); + typename associated_allocator<DecayedHandler>::type alloc( + (get_associated_allocator)(handler)); - typename associated_executor<handler>::type ex( - (get_associated_executor)(init.completion_handler)); + ex.defer(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc); + } - typename associated_allocator<handler>::type alloc( - (get_associated_allocator)(init.completion_handler)); + template <typename CompletionHandler, typename Executor> + void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, + BOOST_ASIO_MOVE_ARG(Executor) ex) const + { + typedef typename decay<CompletionHandler>::type DecayedHandler; - ex.defer(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc); + typename associated_allocator<DecayedHandler>::type alloc( + (get_associated_allocator)(handler)); - return init.result.get(); + ex.defer(detail::work_dispatcher<DecayedHandler>( + BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); + } +}; + +} // namespace detail + +template <typename CompletionToken> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer( + BOOST_ASIO_MOVE_ARG(CompletionToken) token) +{ + return async_initiate<CompletionToken, void()>( + detail::initiate_defer(), token); } template <typename Executor, typename CompletionToken> @@ -49,16 +71,8 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer( const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token, typename enable_if<is_executor<Executor>::value>::type*) { - typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion<CompletionToken, void()> init(token); - - typename associated_allocator<handler>::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.defer(detail::work_dispatcher<handler>(init.completion_handler), alloc); - - return init.result.get(); + return async_initiate<CompletionToken, void()>( + detail::initiate_defer(), token, ex); } template <typename ExecutionContext, typename CompletionToken> diff --git a/boost/asio/impl/detached.hpp b/boost/asio/impl/detached.hpp new file mode 100644 index 0000000000..ae2c882fba --- /dev/null +++ b/boost/asio/impl/detached.hpp @@ -0,0 +1,132 @@ +// +// impl/detached.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IMPL_DETACHED_HPP +#define BOOST_ASIO_IMPL_DETACHED_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/async_result.hpp> +#include <boost/asio/detail/variadic_templates.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + + // Class to adapt a detached_t as a completion handler. + class detached_handler + { + public: + typedef void result_type; + + detached_handler(detached_t) + { + } + +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename... Args> + void operator()(Args...) + { + } + +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + void operator()() + { + } + +#define BOOST_ASIO_PRIVATE_DETACHED_DEF(n) \ + template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + void operator()(BOOST_ASIO_VARIADIC_TARGS(n)) \ + { \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_DETACHED_DEF) +#undef BOOST_ASIO_PRIVATE_DETACHED_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + }; + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename Signature> +struct async_result<detached_t, Signature> +{ + typedef boost::asio::detail::detached_handler completion_handler_type; + + typedef void return_type; + + explicit async_result(completion_handler_type&) + { + } + + void get() + { + } + +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static return_type initiate( + BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_MOVE_ARG(RawCompletionToken), + BOOST_ASIO_MOVE_ARG(Args)... args) + { + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( + detail::detached_handler(detached_t()), + BOOST_ASIO_MOVE_CAST(Args)(args)...); + } + +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename Initiation, typename RawCompletionToken> + static return_type initiate( + BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_MOVE_ARG(RawCompletionToken)) + { + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( + detail::detached_handler(detached_t())); + } + +#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \ + template <typename Initiation, typename RawCompletionToken, \ + BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + static return_type initiate( \ + BOOST_ASIO_MOVE_ARG(Initiation) initiation, \ + BOOST_ASIO_MOVE_ARG(RawCompletionToken), \ + BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( \ + detail::detached_handler(detached_t()), \ + BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF) +#undef BOOST_ASIO_PRIVATE_INITIATE_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_IMPL_DETACHED_HPP diff --git a/boost/asio/impl/dispatch.hpp b/boost/asio/impl/dispatch.hpp index 8bdce85180..bcba2ee401 100644 --- a/boost/asio/impl/dispatch.hpp +++ b/boost/asio/impl/dispatch.hpp @@ -2,7 +2,7 @@ // impl/dispatch.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -24,24 +24,46 @@ namespace boost { namespace asio { +namespace detail { -template <typename CompletionToken> -BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch( - BOOST_ASIO_MOVE_ARG(CompletionToken) token) +struct initiate_dispatch { - typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler; + template <typename CompletionHandler> + void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const + { + typedef typename decay<CompletionHandler>::type DecayedHandler; + + typename associated_executor<DecayedHandler>::type ex( + (get_associated_executor)(handler)); - async_completion<CompletionToken, void()> init(token); + typename associated_allocator<DecayedHandler>::type alloc( + (get_associated_allocator)(handler)); - typename associated_executor<handler>::type ex( - (get_associated_executor)(init.completion_handler)); + ex.dispatch(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc); + } - typename associated_allocator<handler>::type alloc( - (get_associated_allocator)(init.completion_handler)); + template <typename CompletionHandler, typename Executor> + void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, + BOOST_ASIO_MOVE_ARG(Executor) ex) const + { + typedef typename decay<CompletionHandler>::type DecayedHandler; - ex.dispatch(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc); + typename associated_allocator<DecayedHandler>::type alloc( + (get_associated_allocator)(handler)); - return init.result.get(); + ex.dispatch(detail::work_dispatcher<DecayedHandler>( + BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); + } +}; + +} // namespace detail + +template <typename CompletionToken> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch( + BOOST_ASIO_MOVE_ARG(CompletionToken) token) +{ + return async_initiate<CompletionToken, void()>( + detail::initiate_dispatch(), token); } template <typename Executor, typename CompletionToken> @@ -49,17 +71,8 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch( const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token, typename enable_if<is_executor<Executor>::value>::type*) { - typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion<CompletionToken, void()> init(token); - - typename associated_allocator<handler>::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.dispatch(detail::work_dispatcher<handler>( - init.completion_handler), alloc); - - return init.result.get(); + return async_initiate<CompletionToken, void()>( + detail::initiate_dispatch(), token, ex); } template <typename ExecutionContext, typename CompletionToken> diff --git a/boost/asio/impl/error.ipp b/boost/asio/impl/error.ipp index 49a10462bd..0dcb1257c7 100644 --- a/boost/asio/impl/error.ipp +++ b/boost/asio/impl/error.ipp @@ -2,7 +2,7 @@ // impl/error.ipp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/execution_context.hpp b/boost/asio/impl/execution_context.hpp index eadf36b145..a1617f8c9c 100644 --- a/boost/asio/impl/execution_context.hpp +++ b/boost/asio/impl/execution_context.hpp @@ -2,7 +2,7 @@ // impl/execution_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -24,6 +24,8 @@ namespace boost { namespace asio { +#if !defined(GENERATING_DOCUMENTATION) + template <typename Service> inline Service& use_service(execution_context& e) { @@ -33,8 +35,7 @@ inline Service& use_service(execution_context& e) return e.service_registry_->template use_service<Service>(); } -#if !defined(GENERATING_DOCUMENTATION) -# if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template <typename Service, typename... Args> Service& make_service(execution_context& e, BOOST_ASIO_MOVE_ARG(Args)... args) @@ -47,7 +48,7 @@ Service& make_service(execution_context& e, BOOST_ASIO_MOVE_ARG(Args)... args) return result; } -# else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template <typename Service> Service& make_service(execution_context& e) @@ -75,8 +76,7 @@ Service& make_service(execution_context& e) BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF) #undef BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF -# endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) -#endif // !defined(GENERATING_DOCUMENTATION) +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) template <typename Service> inline void add_service(execution_context& e, Service* svc) @@ -96,6 +96,8 @@ inline bool has_service(execution_context& e) return e.service_registry_->template has_service<Service>(); } +#endif // !defined(GENERATING_DOCUMENTATION) + inline execution_context& execution_context::service::context() { return owner_; diff --git a/boost/asio/impl/execution_context.ipp b/boost/asio/impl/execution_context.ipp index 219a66113d..30e7bb926f 100644 --- a/boost/asio/impl/execution_context.ipp +++ b/boost/asio/impl/execution_context.ipp @@ -2,7 +2,7 @@ // impl/execution_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/executor.hpp b/boost/asio/impl/executor.hpp index 106763b042..b1c6cd748f 100644 --- a/boost/asio/impl/executor.hpp +++ b/boost/asio/impl/executor.hpp @@ -2,7 +2,7 @@ // impl/executor.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,7 +17,7 @@ #include <boost/asio/detail/config.hpp> #include <boost/asio/detail/atomic_count.hpp> -#include <boost/asio/detail/executor_op.hpp> +#include <boost/asio/detail/executor_function.hpp> #include <boost/asio/detail/global.hpp> #include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/recycling_allocator.hpp> @@ -41,36 +41,37 @@ public: explicit function(F f, const Alloc& a) { // Allocate and construct an operation to wrap the function. - typedef detail::executor_op<F, Alloc> op; - typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - op_ = new (p.v) op(BOOST_ASIO_MOVE_CAST(F)(f), a); + typedef detail::executor_function<F, Alloc> func_type; + typename func_type::ptr p = { + detail::addressof(a), func_type::ptr::allocate(a), 0 }; + func_ = new (p.v) func_type(BOOST_ASIO_MOVE_CAST(F)(f), a); p.v = 0; } - function(function&& other) - : op_(other.op_) + function(function&& other) BOOST_ASIO_NOEXCEPT + : func_(other.func_) { - other.op_ = 0; + other.func_ = 0; } ~function() { - if (op_) - op_->destroy(); + if (func_) + func_->destroy(); } void operator()() { - if (op_) + if (func_) { - detail::scheduler_operation* op = op_; - op_ = 0; - op->complete(this, boost::system::error_code(), 0); + detail::executor_function_base* func = func_; + func_ = 0; + func->complete(); } } private: - detail::scheduler_operation* op_; + detail::executor_function_base* func_; }; #else // defined(BOOST_ASIO_HAS_MOVE) diff --git a/boost/asio/impl/executor.ipp b/boost/asio/impl/executor.ipp index 86114d93f1..289265d706 100644 --- a/boost/asio/impl/executor.ipp +++ b/boost/asio/impl/executor.ipp @@ -2,7 +2,7 @@ // impl/executor.ipp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/handler_alloc_hook.ipp b/boost/asio/impl/handler_alloc_hook.ipp index 2b04ec104e..a580f71ffa 100644 --- a/boost/asio/impl/handler_alloc_hook.ipp +++ b/boost/asio/impl/handler_alloc_hook.ipp @@ -2,7 +2,7 @@ // impl/handler_alloc_hook.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/io_context.hpp b/boost/asio/impl/io_context.hpp index 37f8ace42a..2cf8c4bc8d 100644 --- a/boost/asio/impl/io_context.hpp +++ b/boost/asio/impl/io_context.hpp @@ -2,7 +2,7 @@ // impl/io_context.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -19,6 +19,7 @@ #include <boost/asio/detail/executor_op.hpp> #include <boost/asio/detail/fenced_block.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/recycling_allocator.hpp> #include <boost/asio/detail/service_registry.hpp> #include <boost/asio/detail/throw_error.hpp> @@ -26,6 +27,8 @@ #include <boost/asio/detail/push_options.hpp> +#if !defined(GENERATING_DOCUMENTATION) + namespace boost { namespace asio { @@ -49,6 +52,8 @@ inline detail::io_context_impl& use_service<detail::io_context_impl>( } // namespace asio } // namespace boost +#endif // !defined(GENERATING_DOCUMENTATION) + #include <boost/asio/detail/pop_options.hpp> #if defined(BOOST_ASIO_HAS_IOCP) @@ -130,70 +135,87 @@ inline void io_context::reset() restart(); } +struct io_context::initiate_dispatch +{ + template <typename LegacyCompletionHandler> + void operator()(BOOST_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. + BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( + LegacyCompletionHandler, handler) type_check; + + detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler); + if (self->impl_.can_dispatch()) + { + detail::fenced_block b(detail::fenced_block::full); + boost_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<LegacyCompletionHandler>::type> op; + typename op::ptr p = { detail::addressof(handler2.value), + op::ptr::allocate(handler2.value), 0 }; + p.p = new (p.v) op(handler2.value); + + BOOST_ASIO_HANDLER_CREATION((*self, *p.p, + "io_context", self, 0, "dispatch")); + + self->impl_.do_dispatch(p.p); + p.v = p.p = 0; + } + } +}; + template <typename LegacyCompletionHandler> BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ()) io_context::dispatch(BOOST_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. - BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( - LegacyCompletionHandler, handler) type_check; - - async_completion<LegacyCompletionHandler, void ()> init(handler); + return async_initiate<LegacyCompletionHandler, void ()>( + initiate_dispatch(), handler, this); +} - if (impl_.can_dispatch()) - { - detail::fenced_block b(detail::fenced_block::full); - boost_asio_handler_invoke_helpers::invoke( - init.completion_handler, init.completion_handler); - } - else +struct io_context::initiate_post +{ + template <typename LegacyCompletionHandler> + void operator()(BOOST_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. + BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( + LegacyCompletionHandler, handler) type_check; + + detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler); + + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler2.value); + // Allocate and construct an operation to wrap the handler. typedef detail::completion_handler< - typename handler_type<LegacyCompletionHandler, void ()>::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<LegacyCompletionHandler>::type> op; + typename op::ptr p = { detail::addressof(handler2.value), + op::ptr::allocate(handler2.value), 0 }; + p.p = new (p.v) op(handler2.value); - BOOST_ASIO_HANDLER_CREATION((*this, *p.p, - "io_context", this, 0, "dispatch")); + BOOST_ASIO_HANDLER_CREATION((*self, *p.p, + "io_context", self, 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 <typename LegacyCompletionHandler> BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ()) io_context::post(BOOST_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. - BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( - LegacyCompletionHandler, handler) type_check; - - async_completion<LegacyCompletionHandler, void ()> init(handler); - - bool is_continuation = - boost_asio_handler_cont_helpers::is_continuation(init.completion_handler); - - // Allocate and construct an operation to wrap the handler. - typedef detail::completion_handler< - typename handler_type<LegacyCompletionHandler, void ()>::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); - - BOOST_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<LegacyCompletionHandler, void ()>( + initiate_post(), handler, this); } template <typename Handler> @@ -320,11 +342,6 @@ inline boost::asio::io_context& io_context::work::get_io_context() { return static_cast<boost::asio::io_context&>(io_context_impl_.context()); } - -inline boost::asio::io_context& io_context::work::get_io_service() -{ - return static_cast<boost::asio::io_context&>(io_context_impl_.context()); -} #endif // !defined(BOOST_ASIO_NO_DEPRECATED) inline boost::asio::io_context& io_context::service::get_io_context() @@ -332,13 +349,6 @@ inline boost::asio::io_context& io_context::service::get_io_context() return static_cast<boost::asio::io_context&>(context()); } -#if !defined(BOOST_ASIO_NO_DEPRECATED) -inline boost::asio::io_context& io_context::service::get_io_service() -{ - return static_cast<boost::asio::io_context&>(context()); -} -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - } // namespace asio } // namespace boost diff --git a/boost/asio/impl/io_context.ipp b/boost/asio/impl/io_context.ipp index 96a7de7415..5de07181d4 100644 --- a/boost/asio/impl/io_context.ipp +++ b/boost/asio/impl/io_context.ipp @@ -2,7 +2,7 @@ // impl/io_context.ipp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,13 +35,14 @@ namespace boost { namespace asio { io_context::io_context() - : impl_(add_impl(new impl_type(*this, BOOST_ASIO_CONCURRENCY_HINT_DEFAULT))) + : impl_(add_impl(new impl_type(*this, + BOOST_ASIO_CONCURRENCY_HINT_DEFAULT, false))) { } io_context::io_context(int concurrency_hint) : impl_(add_impl(new impl_type(*this, concurrency_hint == 1 - ? BOOST_ASIO_CONCURRENCY_HINT_1 : concurrency_hint))) + ? BOOST_ASIO_CONCURRENCY_HINT_1 : concurrency_hint, false))) { } diff --git a/boost/asio/impl/post.hpp b/boost/asio/impl/post.hpp index d318f890ff..ac0831e532 100644 --- a/boost/asio/impl/post.hpp +++ b/boost/asio/impl/post.hpp @@ -2,7 +2,7 @@ // impl/post.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -24,24 +24,46 @@ namespace boost { namespace asio { +namespace detail { -template <typename CompletionToken> -BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post( - BOOST_ASIO_MOVE_ARG(CompletionToken) token) +struct initiate_post { - typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler; + template <typename CompletionHandler> + void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const + { + typedef typename decay<CompletionHandler>::type DecayedHandler; + + typename associated_executor<DecayedHandler>::type ex( + (get_associated_executor)(handler)); - async_completion<CompletionToken, void()> init(token); + typename associated_allocator<DecayedHandler>::type alloc( + (get_associated_allocator)(handler)); - typename associated_executor<handler>::type ex( - (get_associated_executor)(init.completion_handler)); + ex.post(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc); + } - typename associated_allocator<handler>::type alloc( - (get_associated_allocator)(init.completion_handler)); + template <typename CompletionHandler, typename Executor> + void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, + BOOST_ASIO_MOVE_ARG(Executor) ex) const + { + typedef typename decay<CompletionHandler>::type DecayedHandler; - ex.post(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc); + typename associated_allocator<DecayedHandler>::type alloc( + (get_associated_allocator)(handler)); - return init.result.get(); + ex.post(detail::work_dispatcher<DecayedHandler>( + BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); + } +}; + +} // namespace detail + +template <typename CompletionToken> +BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post( + BOOST_ASIO_MOVE_ARG(CompletionToken) token) +{ + return async_initiate<CompletionToken, void()>( + detail::initiate_post(), token); } template <typename Executor, typename CompletionToken> @@ -49,16 +71,8 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post( const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token, typename enable_if<is_executor<Executor>::value>::type*) { - typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler; - - async_completion<CompletionToken, void()> init(token); - - typename associated_allocator<handler>::type alloc( - (get_associated_allocator)(init.completion_handler)); - - ex.post(detail::work_dispatcher<handler>(init.completion_handler), alloc); - - return init.result.get(); + return async_initiate<CompletionToken, void()>( + detail::initiate_post(), token, ex); } template <typename ExecutionContext, typename CompletionToken> diff --git a/boost/asio/impl/read.hpp b/boost/asio/impl/read.hpp index 9fbddc964e..6eabf0f616 100644 --- a/boost/asio/impl/read.hpp +++ b/boost/asio/impl/read.hpp @@ -2,7 +2,7 @@ // impl/read.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -29,6 +29,7 @@ #include <boost/asio/detail/handler_cont_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> @@ -69,7 +70,8 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, >::type*) { return detail::read_buffer_sequence(s, buffers, - boost::asio::buffer_sequence_begin(buffers), completion_condition, ec); + boost::asio::buffer_sequence_begin(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); } template <typename SyncReadStream, typename MutableBufferSequence> @@ -103,22 +105,26 @@ inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, >::type*) { boost::system::error_code ec; - std::size_t bytes_transferred = read(s, buffers, completion_condition, ec); + std::size_t bytes_transferred = read(s, buffers, + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); boost::asio::detail::throw_error(ec, "read"); return bytes_transferred; } -template <typename SyncReadStream, typename DynamicBuffer, +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +template <typename SyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t read(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, boost::system::error_code& ec, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { - typename decay<DynamicBuffer>::type b( - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers)); + typename decay<DynamicBuffer_v1>::type b( + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); ec = boost::system::error_code(); std::size_t total_transferred = 0; @@ -141,45 +147,48 @@ std::size_t read(SyncReadStream& s, return total_transferred; } -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { boost::system::error_code ec; std::size_t bytes_transferred = read(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), transfer_all(), ec); + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec); boost::asio::detail::throw_error(ec, "read"); return bytes_transferred; } -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, boost::system::error_code& ec, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { - return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), + return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec); } -template <typename SyncReadStream, typename DynamicBuffer, +template <typename SyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition> inline std::size_t read(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { boost::system::error_code ec; std::size_t bytes_transferred = read(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), - completion_condition, ec); + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); boost::asio::detail::throw_error(ec, "read"); return bytes_transferred; } @@ -193,7 +202,8 @@ inline std::size_t read(SyncReadStream& s, boost::asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition, boost::system::error_code& ec) { - return read(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec); + return read(s, basic_streambuf_ref<Allocator>(b), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); } template <typename SyncReadStream, typename Allocator> @@ -217,11 +227,87 @@ inline std::size_t read(SyncReadStream& s, boost::asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition) { - return read(s, basic_streambuf_ref<Allocator>(b), completion_condition); + return read(s, basic_streambuf_ref<Allocator>(b), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +template <typename SyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition> +std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + DynamicBuffer_v2& b = buffers; + + ec = boost::system::error_code(); + std::size_t total_transferred = 0; + std::size_t max_size = detail::adapt_completion_condition_result( + completion_condition(ec, total_transferred)); + std::size_t bytes_available = std::min<std::size_t>( + std::max<std::size_t>(512, b.capacity() - b.size()), + std::min<std::size_t>(max_size, b.max_size() - b.size())); + while (bytes_available > 0) + { + std::size_t pos = b.size(); + b.grow(bytes_available); + std::size_t bytes_transferred = s.read_some( + b.data(pos, bytes_available), ec); + b.shrink(bytes_available - bytes_transferred); + total_transferred += bytes_transferred; + max_size = detail::adapt_completion_condition_result( + completion_condition(ec, total_transferred)); + bytes_available = std::min<std::size_t>( + std::max<std::size_t>(512, b.capacity() - b.size()), + std::min<std::size_t>(max_size, b.max_size() - b.size())); + } + return total_transferred; +} + +template <typename SyncReadStream, typename DynamicBuffer_v2> +inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec); + boost::asio::detail::throw_error(ec, "read"); + return bytes_transferred; +} + +template <typename SyncReadStream, typename DynamicBuffer_v2> +inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, + boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + transfer_all(), ec); +} + +template <typename SyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition> +inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + boost::asio::detail::throw_error(ec, "read"); + return bytes_transferred; +} namespace detail { @@ -233,7 +319,7 @@ namespace detail { public: read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, ReadHandler& handler) + CompletionCondition& completion_condition, ReadHandler& handler) : detail::base_from_completion_cond< CompletionCondition>(completion_condition), stream_(stream), @@ -254,9 +340,11 @@ namespace detail } read_op(read_op&& other) - : detail::base_from_completion_cond<CompletionCondition>(other), + : detail::base_from_completion_cond<CompletionCondition>( + BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< + CompletionCondition>)(other)), stream_(other.stream_), - buffers_(other.buffers_), + buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)), start_(other.start_), handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) { @@ -287,9 +375,11 @@ namespace detail } //private: + typedef boost::asio::detail::consuming_buffers<mutable_buffer, + MutableBufferSequence, MutableBufferIterator> buffers_type; + AsyncReadStream& stream_; - boost::asio::detail::consuming_buffers<mutable_buffer, - MutableBufferSequence, MutableBufferIterator> buffers_; + buffers_type buffers_; int start_; ReadHandler handler_; }; @@ -355,13 +445,33 @@ namespace detail typename ReadHandler> inline void start_read_buffer_sequence_op(AsyncReadStream& stream, const MutableBufferSequence& buffers, const MutableBufferIterator&, - CompletionCondition completion_condition, ReadHandler& handler) + CompletionCondition& completion_condition, ReadHandler& handler) { detail::read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>( stream, buffers, completion_condition, handler)( boost::system::error_code(), 0, 1); } + + struct initiate_async_read_buffer_sequence + { + template <typename ReadHandler, typename AsyncReadStream, + typename MutableBufferSequence, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + start_read_buffer_sequence_op(*s, buffers, + boost::asio::buffer_sequence_begin(buffers), + completion_cond2.value, handler2.value); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -417,18 +527,10 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, is_mutable_buffer_sequence<MutableBufferSequence>::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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::start_read_buffer_sequence_op(s, buffers, - boost::asio::buffer_sequence_begin(buffers), completion_condition, - init.completion_handler); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_buffer_sequence(), handler, &s, buffers, + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncReadStream, typename MutableBufferSequence, @@ -441,32 +543,26 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, is_mutable_buffer_sequence<MutableBufferSequence>::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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::start_read_buffer_sequence_op(s, buffers, - boost::asio::buffer_sequence_begin(buffers), transfer_all(), - init.completion_handler); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_buffer_sequence(), + handler, &s, buffers, transfer_all()); } +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + namespace detail { - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> - class read_dynbuf_op + class read_dynbuf_v1_op : detail::base_from_completion_cond<CompletionCondition> { public: template <typename BufferSequence> - read_dynbuf_op(AsyncReadStream& stream, + read_dynbuf_v1_op(AsyncReadStream& stream, BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, - CompletionCondition completion_condition, ReadHandler& handler) + CompletionCondition& completion_condition, ReadHandler& handler) : detail::base_from_completion_cond< CompletionCondition>(completion_condition), stream_(stream), @@ -478,7 +574,7 @@ namespace detail } #if defined(BOOST_ASIO_HAS_MOVE) - read_dynbuf_op(const read_dynbuf_op& other) + read_dynbuf_v1_op(const read_dynbuf_v1_op& other) : detail::base_from_completion_cond<CompletionCondition>(other), stream_(other.stream_), buffers_(other.buffers_), @@ -488,10 +584,12 @@ namespace detail { } - read_dynbuf_op(read_dynbuf_op&& other) - : detail::base_from_completion_cond<CompletionCondition>(other), + read_dynbuf_v1_op(read_dynbuf_v1_op&& other) + : detail::base_from_completion_cond<CompletionCondition>( + BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< + CompletionCondition>)(other)), stream_(other.stream_), - buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), start_(other.start_), total_transferred_(other.total_transferred_), handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) @@ -515,7 +613,7 @@ namespace detail for (;;) { stream_.async_read_some(buffers_.prepare(bytes_available), - BOOST_ASIO_MOVE_CAST(read_dynbuf_op)(*this)); + BOOST_ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this)); return; default: total_transferred_ += bytes_transferred; buffers_.commit(bytes_transferred); @@ -535,36 +633,36 @@ namespace detail //private: AsyncReadStream& stream_; - DynamicBuffer buffers_; + DynamicBuffer_v1 buffers_; int start_; std::size_t total_transferred_; ReadHandler handler_; }; - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> inline void* asio_handler_allocate(std::size_t size, - read_dynbuf_op<AsyncReadStream, DynamicBuffer, + read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_dynbuf_op<AsyncReadStream, DynamicBuffer, + read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> inline bool asio_handler_is_continuation( - read_dynbuf_op<AsyncReadStream, DynamicBuffer, + read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>* this_handler) { return this_handler->start_ == 0 ? true @@ -573,10 +671,10 @@ namespace detail } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename CompletionCondition, + typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> inline void asio_handler_invoke(Function& function, - read_dynbuf_op<AsyncReadStream, DynamicBuffer, + read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( @@ -584,49 +682,71 @@ namespace detail } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename CompletionCondition, + typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> inline void asio_handler_invoke(const Function& function, - read_dynbuf_op<AsyncReadStream, DynamicBuffer, + read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_dynbuf_v1 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v1, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type, + CompletionCondition, typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + completion_cond2.value, handler2.value)( + boost::system::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler, typename Allocator> struct associated_allocator< - detail::read_dynbuf_op<AsyncReadStream, - DynamicBuffer, CompletionCondition, ReadHandler>, + detail::read_dynbuf_v1_op<AsyncReadStream, + DynamicBuffer_v1, CompletionCondition, ReadHandler>, Allocator> { typedef typename associated_allocator<ReadHandler, Allocator>::type type; static type get( - const detail::read_dynbuf_op<AsyncReadStream, - DynamicBuffer, CompletionCondition, ReadHandler>& h, + const detail::read_dynbuf_v1_op<AsyncReadStream, + DynamicBuffer_v1, CompletionCondition, ReadHandler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); } }; -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler, typename Executor> struct associated_executor< - detail::read_dynbuf_op<AsyncReadStream, - DynamicBuffer, CompletionCondition, ReadHandler>, + detail::read_dynbuf_v1_op<AsyncReadStream, + DynamicBuffer_v1, CompletionCondition, ReadHandler>, Executor> { typedef typename associated_executor<ReadHandler, Executor>::type type; static type get( - const detail::read_dynbuf_op<AsyncReadStream, - DynamicBuffer, CompletionCondition, ReadHandler>& h, + const detail::read_dynbuf_v1_op<AsyncReadStream, + DynamicBuffer_v1, CompletionCondition, ReadHandler>& h, const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT { return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); @@ -636,49 +756,44 @@ struct associated_executor< #endif // !defined(GENERATING_DOCUMENTATION) template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { return async_read(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); } -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::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 ReadHandler. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::read_dynbuf_op<AsyncReadStream, - typename decay<DynamicBuffer>::type, - CompletionCondition, BOOST_ASIO_HANDLER_TYPE( - ReadHandler, void (boost::system::error_code, std::size_t))>( - s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), - completion_condition, init.completion_handler)( - boost::system::error_code(), 0, 1); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_dynbuf_v1(), handler, &s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -703,11 +818,260 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) { return async_read(s, basic_streambuf_ref<Allocator>(b), - completion_condition, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); } #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +namespace detail +{ + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename ReadHandler> + class read_dynbuf_v2_op + : detail::base_from_completion_cond<CompletionCondition> + { + public: + template <typename BufferSequence> + read_dynbuf_v2_op(AsyncReadStream& stream, + BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, + CompletionCondition& completion_condition, ReadHandler& handler) + : detail::base_from_completion_cond< + CompletionCondition>(completion_condition), + stream_(stream), + buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), + start_(0), + total_transferred_(0), + bytes_available_(0), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + read_dynbuf_v2_op(const read_dynbuf_v2_op& other) + : detail::base_from_completion_cond<CompletionCondition>(other), + stream_(other.stream_), + buffers_(other.buffers_), + start_(other.start_), + total_transferred_(other.total_transferred_), + bytes_available_(other.bytes_available_), + handler_(other.handler_) + { + } + + read_dynbuf_v2_op(read_dynbuf_v2_op&& other) + : detail::base_from_completion_cond<CompletionCondition>( + BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< + CompletionCondition>)(other)), + stream_(other.stream_), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + start_(other.start_), + total_transferred_(other.total_transferred_), + bytes_available_(other.bytes_available_), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + std::size_t max_size, pos; + switch (start_ = start) + { + case 1: + max_size = this->check_for_completion(ec, total_transferred_); + bytes_available_ = std::min<std::size_t>( + std::max<std::size_t>(512, + buffers_.capacity() - buffers_.size()), + std::min<std::size_t>(max_size, + buffers_.max_size() - buffers_.size())); + for (;;) + { + pos = buffers_.size(); + buffers_.grow(bytes_available_); + stream_.async_read_some(buffers_.data(pos, bytes_available_), + BOOST_ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this)); + return; default: + total_transferred_ += bytes_transferred; + buffers_.shrink(bytes_available_ - bytes_transferred); + max_size = this->check_for_completion(ec, total_transferred_); + bytes_available_ = std::min<std::size_t>( + std::max<std::size_t>(512, + buffers_.capacity() - buffers_.size()), + std::min<std::size_t>(max_size, + buffers_.max_size() - buffers_.size())); + if ((!ec && bytes_transferred == 0) || bytes_available_ == 0) + break; + } + + handler_(ec, static_cast<const std::size_t&>(total_transferred_)); + } + } + + //private: + AsyncReadStream& stream_; + DynamicBuffer_v2 buffers_; + int start_; + std::size_t total_transferred_; + std::size_t bytes_available_; + ReadHandler handler_; + }; + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename ReadHandler> + inline void* asio_handler_allocate(std::size_t size, + read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, + CompletionCondition, ReadHandler>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename ReadHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, + CompletionCondition, ReadHandler>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename ReadHandler> + inline bool asio_handler_is_continuation( + read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, + CompletionCondition, ReadHandler>* this_handler) + { + return this_handler->start_ == 0 ? true + : boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename CompletionCondition, + typename ReadHandler> + inline void asio_handler_invoke(Function& function, + read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, + CompletionCondition, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename CompletionCondition, + typename ReadHandler> + inline void asio_handler_invoke(const Function& function, + read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, + CompletionCondition, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + struct initiate_async_read_dynbuf_v2 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v2, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type, + CompletionCondition, typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + completion_cond2.value, handler2.value)( + boost::system::error_code(), 0, 1); + } + }; +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename ReadHandler, typename Allocator> +struct associated_allocator< + detail::read_dynbuf_v2_op<AsyncReadStream, + DynamicBuffer_v2, CompletionCondition, ReadHandler>, + Allocator> +{ + typedef typename associated_allocator<ReadHandler, Allocator>::type type; + + static type get( + const detail::read_dynbuf_v2_op<AsyncReadStream, + DynamicBuffer_v2, CompletionCondition, ReadHandler>& h, + const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT + { + return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); + } +}; + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename ReadHandler, typename Executor> +struct associated_executor< + detail::read_dynbuf_v2_op<AsyncReadStream, + DynamicBuffer_v2, CompletionCondition, ReadHandler>, + Executor> +{ + typedef typename associated_executor<ReadHandler, Executor>::type type; + + static type get( + const detail::read_dynbuf_v2_op<AsyncReadStream, + DynamicBuffer_v2, CompletionCondition, ReadHandler>& h, + const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + { + return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> +inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return async_read(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); +} + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename ReadHandler> +inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_dynbuf_v2(), handler, &s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); +} } // namespace asio } // namespace boost diff --git a/boost/asio/impl/read_at.hpp b/boost/asio/impl/read_at.hpp index e3c31c543e..8152ef99a4 100644 --- a/boost/asio/impl/read_at.hpp +++ b/boost/asio/impl/read_at.hpp @@ -2,7 +2,7 @@ // impl/read_at.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -29,6 +29,7 @@ #include <boost/asio/detail/handler_cont_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> @@ -71,7 +72,8 @@ std::size_t read_at(SyncRandomAccessReadDevice& d, CompletionCondition completion_condition, boost::system::error_code& ec) { return detail::read_at_buffer_sequence(d, offset, buffers, - boost::asio::buffer_sequence_begin(buffers), completion_condition, ec); + boost::asio::buffer_sequence_begin(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); } template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence> @@ -100,8 +102,8 @@ inline std::size_t read_at(SyncRandomAccessReadDevice& d, CompletionCondition completion_condition) { boost::system::error_code ec; - std::size_t bytes_transferred = read_at( - d, offset, buffers, completion_condition, ec); + std::size_t bytes_transferred = read_at(d, offset, buffers, + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); boost::asio::detail::throw_error(ec, "read_at"); return bytes_transferred; } @@ -159,8 +161,8 @@ inline std::size_t read_at(SyncRandomAccessReadDevice& d, CompletionCondition completion_condition) { boost::system::error_code ec; - std::size_t bytes_transferred = read_at( - d, offset, b, completion_condition, ec); + std::size_t bytes_transferred = read_at(d, offset, b, + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); boost::asio::detail::throw_error(ec, "read_at"); return bytes_transferred; } @@ -179,7 +181,7 @@ namespace detail public: read_at_op(AsyncRandomAccessReadDevice& device, uint64_t offset, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, ReadHandler& handler) + CompletionCondition& completion_condition, ReadHandler& handler) : detail::base_from_completion_cond< CompletionCondition>(completion_condition), device_(device), @@ -202,10 +204,12 @@ namespace detail } read_at_op(read_at_op&& other) - : detail::base_from_completion_cond<CompletionCondition>(other), + : detail::base_from_completion_cond<CompletionCondition>( + BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< + CompletionCondition>)(other)), device_(other.device_), offset_(other.offset_), - buffers_(other.buffers_), + buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)), start_(other.start_), handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) { @@ -237,10 +241,12 @@ namespace detail } //private: + typedef boost::asio::detail::consuming_buffers<mutable_buffer, + MutableBufferSequence, MutableBufferIterator> buffers_type; + AsyncRandomAccessReadDevice& device_; uint64_t offset_; - boost::asio::detail::consuming_buffers<mutable_buffer, - MutableBufferSequence, MutableBufferIterator> buffers_; + buffers_type buffers_; int start_; ReadHandler handler_; }; @@ -306,7 +312,7 @@ namespace detail typename CompletionCondition, typename ReadHandler> inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers, - const MutableBufferIterator&, CompletionCondition completion_condition, + const MutableBufferIterator&, CompletionCondition& completion_condition, ReadHandler& handler) { detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, @@ -314,6 +320,27 @@ namespace detail d, offset, buffers, completion_condition, handler)( boost::system::error_code(), 0, 1); } + + struct initiate_async_read_at_buffer_sequence + { + template <typename ReadHandler, typename AsyncRandomAccessReadDevice, + typename MutableBufferSequence, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncRandomAccessReadDevice* d, uint64_t offset, + const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + start_read_at_buffer_sequence_op(*d, offset, buffers, + boost::asio::buffer_sequence_begin(buffers), + completion_cond2.value, handler2.value); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -369,18 +396,10 @@ async_read_at(AsyncRandomAccessReadDevice& d, CompletionCondition completion_condition, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::start_read_at_buffer_sequence_op(d, offset, buffers, - boost::asio::buffer_sequence_begin(buffers), completion_condition, - init.completion_handler); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_at_buffer_sequence(), handler, &d, offset, + buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, @@ -391,18 +410,10 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::start_read_at_buffer_sequence_op(d, offset, buffers, - boost::asio::buffer_sequence_begin(buffers), transfer_all(), - init.completion_handler); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_at_buffer_sequence(), + handler, &d, offset, buffers, transfer_all()); } #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -418,7 +429,7 @@ namespace detail public: read_at_streambuf_op(AsyncRandomAccessReadDevice& device, uint64_t offset, basic_streambuf<Allocator>& streambuf, - CompletionCondition completion_condition, ReadHandler& handler) + CompletionCondition& completion_condition, ReadHandler& handler) : detail::base_from_completion_cond< CompletionCondition>(completion_condition), device_(device), @@ -443,7 +454,9 @@ namespace detail } read_at_streambuf_op(read_at_streambuf_op&& other) - : detail::base_from_completion_cond<CompletionCondition>(other), + : detail::base_from_completion_cond<CompletionCondition>( + BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< + CompletionCondition>)(other)), device_(other.device_), offset_(other.offset_), streambuf_(other.streambuf_), @@ -540,6 +553,28 @@ namespace detail boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_at_streambuf + { + template <typename ReadHandler, typename AsyncRandomAccessReadDevice, + typename Allocator, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncRandomAccessReadDevice* d, uint64_t offset, + basic_streambuf<Allocator>* b, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, + CompletionCondition, typename decay<ReadHandler>::type>( + *d, offset, *b, completion_cond2.value, handler2.value)( + boost::system::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -591,20 +626,10 @@ async_read_at(AsyncRandomAccessReadDevice& d, CompletionCondition completion_condition, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, - CompletionCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t))>( - d, offset, b, completion_condition, init.completion_handler)( - boost::system::error_code(), 0, 1); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_at_streambuf(), handler, &d, offset, + &b, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncRandomAccessReadDevice, typename Allocator, @@ -615,20 +640,10 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, - detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t))>( - d, offset, b, transfer_all(), init.completion_handler)( - boost::system::error_code(), 0, 1); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_at_streambuf(), + handler, &d, offset, &b, transfer_all()); } #endif // !defined(BOOST_ASIO_NO_IOSTREAM) diff --git a/boost/asio/impl/read_until.hpp b/boost/asio/impl/read_until.hpp index 8bc959557a..63b86f8f2e 100644 --- a/boost/asio/impl/read_until.hpp +++ b/boost/asio/impl/read_until.hpp @@ -2,7 +2,7 @@ // impl/read_until.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -29,6 +29,7 @@ #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> #include <boost/asio/detail/limits.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/detail/push_options.hpp> @@ -36,30 +37,75 @@ namespace boost { namespace asio { -template <typename SyncReadStream, typename DynamicBuffer> +namespace detail +{ + // Algorithm that finds a subsequence of equal values in a sequence. Returns + // (iterator,true) if a full match was found, in which case the iterator + // points to the beginning of the match. Returns (iterator,false) if a + // partial match was found at the end of the first sequence, in which case + // the iterator points to the beginning of the partial match. Returns + // (last1,false) if no full or partial match was found. + template <typename Iterator1, typename Iterator2> + std::pair<Iterator1, bool> partial_search( + Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) + { + for (Iterator1 iter1 = first1; iter1 != last1; ++iter1) + { + Iterator1 test_iter1 = iter1; + Iterator2 test_iter2 = first2; + for (;; ++test_iter1, ++test_iter2) + { + if (test_iter2 == last2) + return std::make_pair(iter1, true); + if (test_iter1 == last1) + { + if (test_iter2 != first2) + return std::make_pair(iter1, false); + else + break; + } + if (*test_iter1 != *test_iter2) + break; + } + } + return std::make_pair(last1, false); + } +} // namespace detail + +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, char delim) + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type*) { boost::system::error_code ec; std::size_t bytes_transferred = read_until(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim, ec); + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec); boost::asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - char delim, boost::system::error_code& ec) + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + char delim, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type*) { - typename decay<DynamicBuffer>::type b( - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers)); + typename decay<DynamicBuffer_v1>::type b( + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); std::size_t search_position = 0; for (;;) { // Determine the range of the data to be searched. - typedef typename DynamicBuffer::const_buffers_type buffers_type; + typedef typename DynamicBuffer_v1::const_buffers_type buffers_type; typedef buffers_iterator<buffers_type> iterator; buffers_type data_buffers = b.data(); iterator begin = iterator::begin(data_buffers); @@ -97,66 +143,39 @@ std::size_t read_until(SyncReadStream& s, } } -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - BOOST_ASIO_STRING_VIEW_PARAM delim) + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + BOOST_ASIO_STRING_VIEW_PARAM delim, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type*) { boost::system::error_code ec; std::size_t bytes_transferred = read_until(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim, ec); + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec); boost::asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } -namespace detail -{ - // Algorithm that finds a subsequence of equal values in a sequence. Returns - // (iterator,true) if a full match was found, in which case the iterator - // points to the beginning of the match. Returns (iterator,false) if a - // partial match was found at the end of the first sequence, in which case - // the iterator points to the beginning of the partial match. Returns - // (last1,false) if no full or partial match was found. - template <typename Iterator1, typename Iterator2> - std::pair<Iterator1, bool> partial_search( - Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) - { - for (Iterator1 iter1 = first1; iter1 != last1; ++iter1) - { - Iterator1 test_iter1 = iter1; - Iterator2 test_iter2 = first2; - for (;; ++test_iter1, ++test_iter2) - { - if (test_iter2 == last2) - return std::make_pair(iter1, true); - if (test_iter1 == last1) - { - if (test_iter2 != first2) - return std::make_pair(iter1, false); - else - break; - } - if (*test_iter1 != *test_iter2) - break; - } - } - return std::make_pair(last1, false); - } -} // namespace detail - -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec) + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type*) { - typename decay<DynamicBuffer>::type b( - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers)); + typename decay<DynamicBuffer_v1>::type b( + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); std::size_t search_position = 0; for (;;) { // Determine the range of the data to be searched. - typedef typename DynamicBuffer::const_buffers_type buffers_type; + typedef typename DynamicBuffer_v1::const_buffers_type buffers_type; typedef buffers_iterator<buffers_type> iterator; buffers_type data_buffers = b.data(); iterator begin = iterator::begin(data_buffers); @@ -206,31 +225,39 @@ std::size_t read_until(SyncReadStream& s, #if !defined(BOOST_ASIO_NO_EXTENSIONS) #if defined(BOOST_ASIO_HAS_BOOST_REGEX) -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - const boost::regex& expr) + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + const boost::regex& expr, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type*) { boost::system::error_code ec; std::size_t bytes_transferred = read_until(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), expr, ec); + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr, ec); boost::asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - const boost::regex& expr, boost::system::error_code& ec) + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + const boost::regex& expr, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type*) { - typename decay<DynamicBuffer>::type b( - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers)); + typename decay<DynamicBuffer_v1>::type b( + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); std::size_t search_position = 0; for (;;) { // Determine the range of the data to be searched. - typedef typename DynamicBuffer::const_buffers_type buffers_type; + typedef typename DynamicBuffer_v1::const_buffers_type buffers_type; typedef buffers_iterator<buffers_type> iterator; buffers_type data_buffers = b.data(); iterator begin = iterator::begin(data_buffers); @@ -282,35 +309,43 @@ std::size_t read_until(SyncReadStream& s, #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX) template <typename SyncReadStream, - typename DynamicBuffer, typename MatchCondition> + typename DynamicBuffer_v1, typename MatchCondition> inline std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition, - typename enable_if<is_match_condition<MatchCondition>::value>::type*) + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type*) { boost::system::error_code ec; std::size_t bytes_transferred = read_until(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition, ec); boost::asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } template <typename SyncReadStream, - typename DynamicBuffer, typename MatchCondition> + typename DynamicBuffer_v1, typename MatchCondition> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition, boost::system::error_code& ec, - typename enable_if<is_match_condition<MatchCondition>::value>::type*) + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type*) { - typename decay<DynamicBuffer>::type b( - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers)); + typename decay<DynamicBuffer_v1>::type b( + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); std::size_t search_position = 0; for (;;) { // Determine the range of the data to be searched. - typedef typename DynamicBuffer::const_buffers_type buffers_type; + typedef typename DynamicBuffer_v1::const_buffers_type buffers_type; typedef buffers_iterator<buffers_type> iterator; buffers_type data_buffers = b.data(); iterator begin = iterator::begin(data_buffers); @@ -424,16 +459,332 @@ inline std::size_t read_until(SyncReadStream& s, #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +template <typename SyncReadStream, typename DynamicBuffer_v2> +inline std::size_t read_until(SyncReadStream& s, + DynamicBuffer_v2 buffers, char delim, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec); + boost::asio::detail::throw_error(ec, "read_until"); + return bytes_transferred; +} + +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + char delim, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + DynamicBuffer_v2& b = buffers; + + std::size_t search_position = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename DynamicBuffer_v2::const_buffers_type buffers_type; + typedef buffers_iterator<buffers_type> iterator; + buffers_type data_buffers = + const_cast<const DynamicBuffer_v2&>(b).data(0, b.size()); + iterator begin = iterator::begin(data_buffers); + iterator start_pos = begin + search_position; + iterator end = iterator::end(data_buffers); + + // Look for a match. + iterator iter = std::find(start_pos, end, delim); + if (iter != end) + { + // Found a match. We're done. + ec = boost::system::error_code(); + return iter - begin + 1; + } + else + { + // No match. Next search can start with the new data. + search_position = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_to_read = std::min<std::size_t>( + std::max<std::size_t>(512, b.capacity() - b.size()), + std::min<std::size_t>(65536, b.max_size() - b.size())); + std::size_t pos = b.size(); + b.grow(bytes_to_read); + std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec); + b.shrink(bytes_to_read - bytes_transferred); + if (ec) + return 0; + } +} + +template <typename SyncReadStream, typename DynamicBuffer_v2> +inline std::size_t read_until(SyncReadStream& s, + DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec); + boost::asio::detail::throw_error(ec, "read_until"); + return bytes_transferred; +} + +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + DynamicBuffer_v2& b = buffers; + + std::size_t search_position = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename DynamicBuffer_v2::const_buffers_type buffers_type; + typedef buffers_iterator<buffers_type> iterator; + buffers_type data_buffers = + const_cast<const DynamicBuffer_v2&>(b).data(0, b.size()); + iterator begin = iterator::begin(data_buffers); + iterator start_pos = begin + search_position; + iterator end = iterator::end(data_buffers); + + // Look for a match. + std::pair<iterator, bool> result = detail::partial_search( + start_pos, end, delim.begin(), delim.end()); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + ec = boost::system::error_code(); + return result.first - begin + delim.length(); + } + else + { + // Partial match. Next search needs to start from beginning of match. + search_position = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + search_position = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_to_read = std::min<std::size_t>( + std::max<std::size_t>(512, b.capacity() - b.size()), + std::min<std::size_t>(65536, b.max_size() - b.size())); + std::size_t pos = b.size(); + b.grow(bytes_to_read); + std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec); + b.shrink(bytes_to_read - bytes_transferred); + if (ec) + return 0; + } +} + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) +#if defined(BOOST_ASIO_HAS_BOOST_REGEX) + +template <typename SyncReadStream, typename DynamicBuffer_v2> +inline std::size_t read_until(SyncReadStream& s, + DynamicBuffer_v2 buffers, const boost::regex& expr, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr, ec); + boost::asio::detail::throw_error(ec, "read_until"); + return bytes_transferred; +} + +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + const boost::regex& expr, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + DynamicBuffer_v2& b = buffers; + + std::size_t search_position = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename DynamicBuffer_v2::const_buffers_type buffers_type; + typedef buffers_iterator<buffers_type> iterator; + buffers_type data_buffers = + const_cast<const DynamicBuffer_v2&>(b).data(0, b.size()); + iterator begin = iterator::begin(data_buffers); + iterator start_pos = begin + search_position; + iterator end = iterator::end(data_buffers); + + // Look for a match. + boost::match_results<iterator, + typename std::vector<boost::sub_match<iterator> >::allocator_type> + match_results; + if (regex_search(start_pos, end, match_results, expr, + boost::match_default | boost::match_partial)) + { + if (match_results[0].matched) + { + // Full match. We're done. + ec = boost::system::error_code(); + return match_results[0].second - begin; + } + else + { + // Partial match. Next search needs to start from beginning of match. + search_position = match_results[0].first - begin; + } + } + else + { + // No match. Next search can start with the new data. + search_position = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_to_read = std::min<std::size_t>( + std::max<std::size_t>(512, b.capacity() - b.size()), + std::min<std::size_t>(65536, b.max_size() - b.size())); + std::size_t pos = b.size(); + b.grow(bytes_to_read); + std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec); + b.shrink(bytes_to_read - bytes_transferred); + if (ec) + return 0; + } +} + +#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX) + +template <typename SyncReadStream, + typename DynamicBuffer_v2, typename MatchCondition> +inline std::size_t read_until(SyncReadStream& s, + DynamicBuffer_v2 buffers, MatchCondition match_condition, + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + match_condition, ec); + boost::asio::detail::throw_error(ec, "read_until"); + return bytes_transferred; +} + +template <typename SyncReadStream, + typename DynamicBuffer_v2, typename MatchCondition> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + MatchCondition match_condition, boost::system::error_code& ec, + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + DynamicBuffer_v2& b = buffers; + + std::size_t search_position = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename DynamicBuffer_v2::const_buffers_type buffers_type; + typedef buffers_iterator<buffers_type> iterator; + buffers_type data_buffers = + const_cast<const DynamicBuffer_v2&>(b).data(0, b.size()); + iterator begin = iterator::begin(data_buffers); + iterator start_pos = begin + search_position; + iterator end = iterator::end(data_buffers); + + // Look for a match. + std::pair<iterator, bool> result = match_condition(start_pos, end); + if (result.second) + { + // Full match. We're done. + ec = boost::system::error_code(); + return result.first - begin; + } + else if (result.first != end) + { + // Partial match. Next search needs to start from beginning of match. + search_position = result.first - begin; + } + else + { + // No match. Next search can start with the new data. + search_position = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_to_read = std::min<std::size_t>( + std::max<std::size_t>(512, b.capacity() - b.size()), + std::min<std::size_t>(65536, b.max_size() - b.size())); + std::size_t pos = b.size(); + b.grow(bytes_to_read); + std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec); + b.shrink(bytes_to_read - bytes_transferred); + if (ec) + return 0; + } +} + +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) + +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) namespace detail { template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> - class read_until_delim_op + typename DynamicBuffer_v1, typename ReadHandler> + class read_until_delim_op_v1 { public: template <typename BufferSequence> - read_until_delim_op(AsyncReadStream& stream, + read_until_delim_op_v1(AsyncReadStream& stream, BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, char delim, ReadHandler& handler) : stream_(stream), @@ -446,7 +797,7 @@ namespace detail } #if defined(BOOST_ASIO_HAS_MOVE) - read_until_delim_op(const read_until_delim_op& other) + read_until_delim_op_v1(const read_until_delim_op_v1& other) : stream_(other.stream_), buffers_(other.buffers_), delim_(other.delim_), @@ -456,9 +807,9 @@ namespace detail { } - read_until_delim_op(read_until_delim_op&& other) + read_until_delim_op_v1(read_until_delim_op_v1&& other) : stream_(other.stream_), - buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), delim_(other.delim_), start_(other.start_), search_position_(other.search_position_), @@ -479,7 +830,7 @@ namespace detail { { // Determine the range of the data to be searched. - typedef typename DynamicBuffer::const_buffers_type + typedef typename DynamicBuffer_v1::const_buffers_type buffers_type; typedef buffers_iterator<buffers_type> iterator; buffers_type data_buffers = buffers_.data(); @@ -520,9 +871,9 @@ namespace detail if (!start && bytes_to_read == 0) break; - // Start a new asynchronous read operation to obtain more data. + // Start a new asynchronous read op_v1eration to obtain more data. stream_.async_read_some(buffers_.prepare(bytes_to_read), - BOOST_ASIO_MOVE_CAST(read_until_delim_op)(*this)); + BOOST_ASIO_MOVE_CAST(read_until_delim_op_v1)(*this)); return; default: buffers_.commit(bytes_transferred); if (ec || bytes_transferred == 0) @@ -543,7 +894,7 @@ namespace detail //private: AsyncReadStream& stream_; - DynamicBuffer buffers_; + DynamicBuffer_v1 buffers_; char delim_; int start_; std::size_t search_position_; @@ -551,30 +902,30 @@ namespace detail }; template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline void* asio_handler_allocate(std::size_t size, - read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline bool asio_handler_is_continuation( - read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { return this_handler->start_ == 0 ? true : boost_asio_handler_cont_helpers::is_continuation( @@ -582,58 +933,79 @@ namespace detail } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline void asio_handler_invoke(Function& function, - read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline void asio_handler_invoke(const Function& function, - read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_until_delim_v1 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v1> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + read_until_delim_op_v1<AsyncReadStream, + typename decay<DynamicBuffer_v1>::type, + typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + delim, handler2.value)(boost::system::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename ReadHandler, typename Allocator> struct associated_allocator< - detail::read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>, + detail::read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>, Allocator> { typedef typename associated_allocator<ReadHandler, Allocator>::type type; static type get( - const detail::read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>& h, + const detail::read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); } }; -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename ReadHandler, typename Executor> struct associated_executor< - detail::read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>, + detail::read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>, Executor> { typedef typename associated_executor<ReadHandler, Executor>::type type; static type get( - const detail::read_until_delim_op<AsyncReadStream, - DynamicBuffer, ReadHandler>& h, + const detail::read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>& h, const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT { return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); @@ -643,39 +1015,32 @@ struct associated_executor< #endif // !defined(GENERATING_DOCUMENTATION) template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read_until(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::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 ReadHandler. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::read_until_delim_op<AsyncReadStream, - typename decay<DynamicBuffer>::type, - BOOST_ASIO_HANDLER_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t))>( - s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), - delim, init.completion_handler)(boost::system::error_code(), 0, 1); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_until_delim_v1(), handler, + &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim); } namespace detail { template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> - class read_until_delim_string_op + typename DynamicBuffer_v1, typename ReadHandler> + class read_until_delim_string_op_v1 { public: template <typename BufferSequence> - read_until_delim_string_op(AsyncReadStream& stream, + read_until_delim_string_op_v1(AsyncReadStream& stream, BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, const std::string& delim, ReadHandler& handler) : stream_(stream), @@ -688,7 +1053,7 @@ namespace detail } #if defined(BOOST_ASIO_HAS_MOVE) - read_until_delim_string_op(const read_until_delim_string_op& other) + read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other) : stream_(other.stream_), buffers_(other.buffers_), delim_(other.delim_), @@ -698,9 +1063,9 @@ namespace detail { } - read_until_delim_string_op(read_until_delim_string_op&& other) + read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other) : stream_(other.stream_), - buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)), start_(other.start_), search_position_(other.search_position_), @@ -721,7 +1086,7 @@ namespace detail { { // Determine the range of the data to be searched. - typedef typename DynamicBuffer::const_buffers_type + typedef typename DynamicBuffer_v1::const_buffers_type buffers_type; typedef buffers_iterator<buffers_type> iterator; buffers_type data_buffers = buffers_.data(); @@ -773,9 +1138,9 @@ namespace detail if (!start && bytes_to_read == 0) break; - // Start a new asynchronous read operation to obtain more data. + // Start a new asynchronous read op_v1eration to obtain more data. stream_.async_read_some(buffers_.prepare(bytes_to_read), - BOOST_ASIO_MOVE_CAST(read_until_delim_string_op)(*this)); + BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v1)(*this)); return; default: buffers_.commit(bytes_transferred); if (ec || bytes_transferred == 0) @@ -796,7 +1161,7 @@ namespace detail //private: AsyncReadStream& stream_; - DynamicBuffer buffers_; + DynamicBuffer_v1 buffers_; std::string delim_; int start_; std::size_t search_position_; @@ -804,30 +1169,30 @@ namespace detail }; template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline void* asio_handler_allocate(std::size_t size, - read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline bool asio_handler_is_continuation( - read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { return this_handler->start_ == 0 ? true : boost_asio_handler_cont_helpers::is_continuation( @@ -835,58 +1200,79 @@ namespace detail } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline void asio_handler_invoke(Function& function, - read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> inline void asio_handler_invoke(const Function& function, - read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>* this_handler) + read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_until_delim_string_v1 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v1> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + read_until_delim_string_op_v1<AsyncReadStream, + typename decay<DynamicBuffer_v1>::type, + typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + delim, handler2.value)(boost::system::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename ReadHandler, typename Allocator> struct associated_allocator< - detail::read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>, + detail::read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>, Allocator> { typedef typename associated_allocator<ReadHandler, Allocator>::type type; static type get( - const detail::read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>& h, + const detail::read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); } }; -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename ReadHandler, typename Executor> struct associated_executor< - detail::read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>, + detail::read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>, Executor> { typedef typename associated_executor<ReadHandler, Executor>::type type; static type get( - const detail::read_until_delim_string_op<AsyncReadStream, - DynamicBuffer, ReadHandler>& h, + const detail::read_until_delim_string_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>& h, const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT { return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); @@ -896,30 +1282,23 @@ struct associated_executor< #endif // !defined(GENERATING_DOCUMENTATION) template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read_until(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, BOOST_ASIO_STRING_VIEW_PARAM delim, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::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 ReadHandler. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::read_until_delim_string_op<AsyncReadStream, - typename decay<DynamicBuffer>::type, - BOOST_ASIO_HANDLER_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t))>( - s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), - static_cast<std::string>(delim), - init.completion_handler)(boost::system::error_code(), 0, 1); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_until_delim_string_v1(), + handler, &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + static_cast<std::string>(delim)); } #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -927,13 +1306,13 @@ async_read_until(AsyncReadStream& s, namespace detail { - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> - class read_until_expr_op + class read_until_expr_op_v1 { public: template <typename BufferSequence> - read_until_expr_op(AsyncReadStream& stream, + read_until_expr_op_v1(AsyncReadStream& stream, BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, const boost::regex& expr, ReadHandler& handler) : stream_(stream), @@ -946,7 +1325,7 @@ namespace detail } #if defined(BOOST_ASIO_HAS_MOVE) - read_until_expr_op(const read_until_expr_op& other) + read_until_expr_op_v1(const read_until_expr_op_v1& other) : stream_(other.stream_), buffers_(other.buffers_), expr_(other.expr_), @@ -956,9 +1335,9 @@ namespace detail { } - read_until_expr_op(read_until_expr_op&& other) + read_until_expr_op_v1(read_until_expr_op_v1&& other) : stream_(other.stream_), - buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), expr_(other.expr_), start_(other.start_), search_position_(other.search_position_), @@ -979,7 +1358,7 @@ namespace detail { { // Determine the range of the data to be searched. - typedef typename DynamicBuffer::const_buffers_type + typedef typename DynamicBuffer_v1::const_buffers_type buffers_type; typedef buffers_iterator<buffers_type> iterator; buffers_type data_buffers = buffers_.data(); @@ -1034,9 +1413,9 @@ namespace detail if (!start && bytes_to_read == 0) break; - // Start a new asynchronous read operation to obtain more data. + // Start a new asynchronous read op_v1eration to obtain more data. stream_.async_read_some(buffers_.prepare(bytes_to_read), - BOOST_ASIO_MOVE_CAST(read_until_expr_op)(*this)); + BOOST_ASIO_MOVE_CAST(read_until_expr_op_v1)(*this)); return; default: buffers_.commit(bytes_transferred); if (ec || bytes_transferred == 0) @@ -1057,38 +1436,38 @@ namespace detail //private: AsyncReadStream& stream_; - DynamicBuffer buffers_; + DynamicBuffer_v1 buffers_; RegEx expr_; int start_; std::size_t search_position_; ReadHandler handler_; }; - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> inline void* asio_handler_allocate(std::size_t size, - read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>* this_handler) + read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>* this_handler) + read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> inline bool asio_handler_is_continuation( - read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>* this_handler) + read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) { return this_handler->start_ == 0 ? true : boost_asio_handler_cont_helpers::is_continuation( @@ -1096,58 +1475,79 @@ namespace detail } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename RegEx, typename ReadHandler> + typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> inline void asio_handler_invoke(Function& function, - read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>* this_handler) + read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename RegEx, typename ReadHandler> + typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> inline void asio_handler_invoke(const Function& function, - read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>* this_handler) + read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_until_expr_v1 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v1, typename RegEx> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + read_until_expr_op_v1<AsyncReadStream, + typename decay<DynamicBuffer_v1>::type, + RegEx, typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + expr, handler2.value)(boost::system::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename RegEx, typename ReadHandler, typename Allocator> struct associated_allocator< - detail::read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>, + detail::read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>, Allocator> { typedef typename associated_allocator<ReadHandler, Allocator>::type type; static type get( - const detail::read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>& h, + const detail::read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); } }; -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename RegEx, typename ReadHandler, typename Executor> struct associated_executor< - detail::read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>, + detail::read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>, Executor> { typedef typename associated_executor<ReadHandler, Executor>::type type; static type get( - const detail::read_until_expr_op<AsyncReadStream, - DynamicBuffer, RegEx, ReadHandler>& h, + const detail::read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>& h, const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT { return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); @@ -1157,42 +1557,35 @@ struct associated_executor< #endif // !defined(GENERATING_DOCUMENTATION) template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read_until(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const boost::regex& expr, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::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 ReadHandler. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::read_until_expr_op<AsyncReadStream, - typename decay<DynamicBuffer>::type, - boost::regex, BOOST_ASIO_HANDLER_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t))>( - s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), - expr, init.completion_handler)(boost::system::error_code(), 0, 1); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_until_expr_v1(), handler, + &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr); } #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX) namespace detail { - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> - class read_until_match_op + class read_until_match_op_v1 { public: template <typename BufferSequence> - read_until_match_op(AsyncReadStream& stream, + read_until_match_op_v1(AsyncReadStream& stream, BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, MatchCondition match_condition, ReadHandler& handler) : stream_(stream), @@ -1205,7 +1598,7 @@ namespace detail } #if defined(BOOST_ASIO_HAS_MOVE) - read_until_match_op(const read_until_match_op& other) + read_until_match_op_v1(const read_until_match_op_v1& other) : stream_(other.stream_), buffers_(other.buffers_), match_condition_(other.match_condition_), @@ -1215,9 +1608,9 @@ namespace detail { } - read_until_match_op(read_until_match_op&& other) + read_until_match_op_v1(read_until_match_op_v1&& other) : stream_(other.stream_), - buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), match_condition_(other.match_condition_), start_(other.start_), search_position_(other.search_position_), @@ -1238,7 +1631,7 @@ namespace detail { { // Determine the range of the data to be searched. - typedef typename DynamicBuffer::const_buffers_type + typedef typename DynamicBuffer_v1::const_buffers_type buffers_type; typedef buffers_iterator<buffers_type> iterator; buffers_type data_buffers = buffers_.data(); @@ -1289,9 +1682,9 @@ namespace detail if (!start && bytes_to_read == 0) break; - // Start a new asynchronous read operation to obtain more data. + // Start a new asynchronous read op_v1eration to obtain more data. stream_.async_read_some(buffers_.prepare(bytes_to_read), - BOOST_ASIO_MOVE_CAST(read_until_match_op)(*this)); + BOOST_ASIO_MOVE_CAST(read_until_match_op_v1)(*this)); return; default: buffers_.commit(bytes_transferred); if (ec || bytes_transferred == 0) @@ -1312,37 +1705,37 @@ namespace detail //private: AsyncReadStream& stream_; - DynamicBuffer buffers_; + DynamicBuffer_v1 buffers_; MatchCondition match_condition_; int start_; std::size_t search_position_; ReadHandler handler_; }; - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> inline void* asio_handler_allocate(std::size_t size, - read_until_match_op<AsyncReadStream, DynamicBuffer, + read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_match_op<AsyncReadStream, DynamicBuffer, + read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } - template <typename AsyncReadStream, typename DynamicBuffer, + template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> inline bool asio_handler_is_continuation( - read_until_match_op<AsyncReadStream, DynamicBuffer, + read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>* this_handler) { return this_handler->start_ == 0 ? true @@ -1351,10 +1744,10 @@ namespace detail } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename MatchCondition, + typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> inline void asio_handler_invoke(Function& function, - read_until_match_op<AsyncReadStream, DynamicBuffer, + read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( @@ -1362,49 +1755,70 @@ namespace detail } template <typename Function, typename AsyncReadStream, - typename DynamicBuffer, typename MatchCondition, + typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> inline void asio_handler_invoke(const Function& function, - read_until_match_op<AsyncReadStream, DynamicBuffer, + read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_read_until_match_v1 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v1, typename MatchCondition> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + read_until_match_op_v1<AsyncReadStream, + typename decay<DynamicBuffer_v1>::type, + MatchCondition, typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + match_condition, handler2.value)(boost::system::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler, typename Allocator> struct associated_allocator< - detail::read_until_match_op<AsyncReadStream, - DynamicBuffer, MatchCondition, ReadHandler>, + detail::read_until_match_op_v1<AsyncReadStream, + DynamicBuffer_v1, MatchCondition, ReadHandler>, Allocator> { typedef typename associated_allocator<ReadHandler, Allocator>::type type; static type get( - const detail::read_until_match_op<AsyncReadStream, - DynamicBuffer, MatchCondition, ReadHandler>& h, + const detail::read_until_match_op_v1<AsyncReadStream, + DynamicBuffer_v1, MatchCondition, ReadHandler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); } }; -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler, typename Executor> struct associated_executor< - detail::read_until_match_op<AsyncReadStream, - DynamicBuffer, MatchCondition, ReadHandler>, + detail::read_until_match_op_v1<AsyncReadStream, + DynamicBuffer_v1, MatchCondition, ReadHandler>, Executor> { typedef typename associated_executor<ReadHandler, Executor>::type type; static type get( - const detail::read_until_match_op<AsyncReadStream, - DynamicBuffer, MatchCondition, ReadHandler>& h, + const detail::read_until_match_op_v1<AsyncReadStream, + DynamicBuffer_v1, MatchCondition, ReadHandler>& h, const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT { return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); @@ -1413,31 +1827,23 @@ struct associated_executor< #endif // !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read_until(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, - typename enable_if<is_match_condition<MatchCondition>::value>::type*) + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::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 ReadHandler. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::read_until_match_op<AsyncReadStream, - typename decay<DynamicBuffer>::type, - MatchCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t))>( - s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), - match_condition, init.completion_handler)( - boost::system::error_code(), 0, 1); - - return init.result.get(); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_until_match_v1(), handler, + &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition); } #if !defined(BOOST_ASIO_NO_IOSTREAM) @@ -1495,6 +1901,1102 @@ async_read_until(AsyncReadStream& s, #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +namespace detail +{ + template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + class read_until_delim_op_v2 + { + public: + template <typename BufferSequence> + read_until_delim_op_v2(AsyncReadStream& stream, + BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, + char delim, ReadHandler& handler) + : stream_(stream), + buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), + delim_(delim), + start_(0), + search_position_(0), + bytes_to_read_(0), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + read_until_delim_op_v2(const read_until_delim_op_v2& other) + : stream_(other.stream_), + buffers_(other.buffers_), + delim_(other.delim_), + start_(other.start_), + search_position_(other.search_position_), + bytes_to_read_(other.bytes_to_read_), + handler_(other.handler_) + { + } + + read_until_delim_op_v2(read_until_delim_op_v2&& other) + : stream_(other.stream_), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + delim_(other.delim_), + start_(other.start_), + search_position_(other.search_position_), + bytes_to_read_(other.bytes_to_read_), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + const std::size_t not_found = (std::numeric_limits<std::size_t>::max)(); + std::size_t pos; + switch (start_ = start) + { + case 1: + for (;;) + { + { + // Determine the range of the data to be searched. + typedef typename DynamicBuffer_v2::const_buffers_type + buffers_type; + typedef buffers_iterator<buffers_type> iterator; + buffers_type data_buffers = + const_cast<const DynamicBuffer_v2&>(buffers_).data( + 0, buffers_.size()); + iterator begin = iterator::begin(data_buffers); + iterator start_pos = begin + search_position_; + iterator end = iterator::end(data_buffers); + + // Look for a match. + iterator iter = std::find(start_pos, end, delim_); + if (iter != end) + { + // Found a match. We're done. + search_position_ = iter - begin + 1; + bytes_to_read_ = 0; + } + + // No match yet. Check if buffer is full. + else if (buffers_.size() == buffers_.max_size()) + { + search_position_ = not_found; + bytes_to_read_ = 0; + } + + // Need to read some more data. + else + { + // Next search can start with the new data. + search_position_ = end - begin; + bytes_to_read_ = std::min<std::size_t>( + std::max<std::size_t>(512, + buffers_.capacity() - buffers_.size()), + std::min<std::size_t>(65536, + buffers_.max_size() - buffers_.size())); + } + } + + // Check if we're done. + if (!start && bytes_to_read_ == 0) + break; + + // Start a new asynchronous read op_v2eration to obtain more data. + pos = buffers_.size(); + buffers_.grow(bytes_to_read_); + stream_.async_read_some(buffers_.data(pos, bytes_to_read_), + BOOST_ASIO_MOVE_CAST(read_until_delim_op_v2)(*this)); + return; default: + buffers_.shrink(bytes_to_read_ - bytes_transferred); + if (ec || bytes_transferred == 0) + break; + } + + const boost::system::error_code result_ec = + (search_position_ == not_found) + ? error::not_found : ec; + + const std::size_t result_n = + (ec || search_position_ == not_found) + ? 0 : search_position_; + + handler_(result_ec, result_n); + } + } + + //private: + AsyncReadStream& stream_; + DynamicBuffer_v2 buffers_; + char delim_; + int start_; + std::size_t search_position_; + std::size_t bytes_to_read_; + ReadHandler handler_; + }; + + template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline void* asio_handler_allocate(std::size_t size, + read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline bool asio_handler_is_continuation( + read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + return this_handler->start_ == 0 ? true + : boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline void asio_handler_invoke(Function& function, + read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline void asio_handler_invoke(const Function& function, + read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + struct initiate_async_read_until_delim_v2 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v2> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + read_until_delim_op_v2<AsyncReadStream, + typename decay<DynamicBuffer_v2>::type, + typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + delim, handler2.value)(boost::system::error_code(), 0, 1); + } + }; +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename ReadHandler, typename Allocator> +struct associated_allocator< + detail::read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>, + Allocator> +{ + typedef typename associated_allocator<ReadHandler, Allocator>::type type; + + static type get( + const detail::read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>& h, + const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT + { + return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); + } +}; + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename ReadHandler, typename Executor> +struct associated_executor< + detail::read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>, + Executor> +{ + typedef typename associated_executor<ReadHandler, Executor>::type type; + + static type get( + const detail::read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>& h, + const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + { + return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_until_delim_v2(), handler, + &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim); +} + +namespace detail +{ + template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + class read_until_delim_string_op_v2 + { + public: + template <typename BufferSequence> + read_until_delim_string_op_v2(AsyncReadStream& stream, + BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, + const std::string& delim, ReadHandler& handler) + : stream_(stream), + buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), + delim_(delim), + start_(0), + search_position_(0), + bytes_to_read_(0), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other) + : stream_(other.stream_), + buffers_(other.buffers_), + delim_(other.delim_), + start_(other.start_), + search_position_(other.search_position_), + bytes_to_read_(other.bytes_to_read_), + handler_(other.handler_) + { + } + + read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other) + : stream_(other.stream_), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)), + start_(other.start_), + search_position_(other.search_position_), + bytes_to_read_(other.bytes_to_read_), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + const std::size_t not_found = (std::numeric_limits<std::size_t>::max)(); + std::size_t pos; + switch (start_ = start) + { + case 1: + for (;;) + { + { + // Determine the range of the data to be searched. + typedef typename DynamicBuffer_v2::const_buffers_type + buffers_type; + typedef buffers_iterator<buffers_type> iterator; + buffers_type data_buffers = + const_cast<const DynamicBuffer_v2&>(buffers_).data( + 0, buffers_.size()); + iterator begin = iterator::begin(data_buffers); + iterator start_pos = begin + search_position_; + iterator end = iterator::end(data_buffers); + + // Look for a match. + std::pair<iterator, bool> result = detail::partial_search( + start_pos, end, delim_.begin(), delim_.end()); + if (result.first != end && result.second) + { + // Full match. We're done. + search_position_ = result.first - begin + delim_.length(); + bytes_to_read_ = 0; + } + + // No match yet. Check if buffer is full. + else if (buffers_.size() == buffers_.max_size()) + { + search_position_ = not_found; + bytes_to_read_ = 0; + } + + // Need to read some more data. + else + { + if (result.first != end) + { + // Partial match. Next search needs to start from beginning of + // match. + search_position_ = result.first - begin; + } + else + { + // Next search can start with the new data. + search_position_ = end - begin; + } + + bytes_to_read_ = std::min<std::size_t>( + std::max<std::size_t>(512, + buffers_.capacity() - buffers_.size()), + std::min<std::size_t>(65536, + buffers_.max_size() - buffers_.size())); + } + } + + // Check if we're done. + if (!start && bytes_to_read_ == 0) + break; + + // Start a new asynchronous read op_v2eration to obtain more data. + pos = buffers_.size(); + buffers_.grow(bytes_to_read_); + stream_.async_read_some(buffers_.data(pos, bytes_to_read_), + BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v2)(*this)); + return; default: + buffers_.shrink(bytes_to_read_ - bytes_transferred); + if (ec || bytes_transferred == 0) + break; + } + + const boost::system::error_code result_ec = + (search_position_ == not_found) + ? error::not_found : ec; + + const std::size_t result_n = + (ec || search_position_ == not_found) + ? 0 : search_position_; + + handler_(result_ec, result_n); + } + } + + //private: + AsyncReadStream& stream_; + DynamicBuffer_v2 buffers_; + std::string delim_; + int start_; + std::size_t search_position_; + std::size_t bytes_to_read_; + ReadHandler handler_; + }; + + template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline void* asio_handler_allocate(std::size_t size, + read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline bool asio_handler_is_continuation( + read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + return this_handler->start_ == 0 ? true + : boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline void asio_handler_invoke(Function& function, + read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> + inline void asio_handler_invoke(const Function& function, + read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + struct initiate_async_read_until_delim_string_v2 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v2> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + read_until_delim_string_op_v2<AsyncReadStream, + typename decay<DynamicBuffer_v2>::type, + typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + delim, handler2.value)(boost::system::error_code(), 0, 1); + } + }; +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename ReadHandler, typename Allocator> +struct associated_allocator< + detail::read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>, + Allocator> +{ + typedef typename associated_allocator<ReadHandler, Allocator>::type type; + + static type get( + const detail::read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>& h, + const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT + { + return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); + } +}; + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename ReadHandler, typename Executor> +struct associated_executor< + detail::read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>, + Executor> +{ + typedef typename associated_executor<ReadHandler, Executor>::type type; + + static type get( + const detail::read_until_delim_string_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>& h, + const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + { + return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read_until(AsyncReadStream& s, + DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_until_delim_string_v2(), + handler, &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + static_cast<std::string>(delim)); +} + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) +#if defined(BOOST_ASIO_HAS_BOOST_REGEX) + +namespace detail +{ + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename RegEx, typename ReadHandler> + class read_until_expr_op_v2 + { + public: + template <typename BufferSequence> + read_until_expr_op_v2(AsyncReadStream& stream, + BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, + const boost::regex& expr, ReadHandler& handler) + : stream_(stream), + buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), + expr_(expr), + start_(0), + search_position_(0), + bytes_to_read_(0), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + read_until_expr_op_v2(const read_until_expr_op_v2& other) + : stream_(other.stream_), + buffers_(other.buffers_), + expr_(other.expr_), + start_(other.start_), + search_position_(other.search_position_), + bytes_to_read_(other.bytes_to_read_), + handler_(other.handler_) + { + } + + read_until_expr_op_v2(read_until_expr_op_v2&& other) + : stream_(other.stream_), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + expr_(other.expr_), + start_(other.start_), + search_position_(other.search_position_), + bytes_to_read_(other.bytes_to_read_), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + const std::size_t not_found = (std::numeric_limits<std::size_t>::max)(); + std::size_t pos; + switch (start_ = start) + { + case 1: + for (;;) + { + { + // Determine the range of the data to be searched. + typedef typename DynamicBuffer_v2::const_buffers_type + buffers_type; + typedef buffers_iterator<buffers_type> iterator; + buffers_type data_buffers = + const_cast<const DynamicBuffer_v2&>(buffers_).data( + 0, buffers_.size()); + iterator begin = iterator::begin(data_buffers); + iterator start_pos = begin + search_position_; + iterator end = iterator::end(data_buffers); + + // Look for a match. + boost::match_results<iterator, + typename std::vector<boost::sub_match<iterator> >::allocator_type> + match_results; + bool match = regex_search(start_pos, end, match_results, expr_, + boost::match_default | boost::match_partial); + if (match && match_results[0].matched) + { + // Full match. We're done. + search_position_ = match_results[0].second - begin; + bytes_to_read_ = 0; + } + + // No match yet. Check if buffer is full. + else if (buffers_.size() == buffers_.max_size()) + { + search_position_ = not_found; + bytes_to_read_ = 0; + } + + // Need to read some more data. + else + { + if (match) + { + // Partial match. Next search needs to start from beginning of + // match. + search_position_ = match_results[0].first - begin; + } + else + { + // Next search can start with the new data. + search_position_ = end - begin; + } + + bytes_to_read_ = std::min<std::size_t>( + std::max<std::size_t>(512, + buffers_.capacity() - buffers_.size()), + std::min<std::size_t>(65536, + buffers_.max_size() - buffers_.size())); + } + } + + // Check if we're done. + if (!start && bytes_to_read_ == 0) + break; + + // Start a new asynchronous read op_v2eration to obtain more data. + pos = buffers_.size(); + buffers_.grow(bytes_to_read_); + stream_.async_read_some(buffers_.data(pos, bytes_to_read_), + BOOST_ASIO_MOVE_CAST(read_until_expr_op_v2)(*this)); + return; default: + buffers_.shrink(bytes_to_read_ - bytes_transferred); + if (ec || bytes_transferred == 0) + break; + } + + const boost::system::error_code result_ec = + (search_position_ == not_found) + ? error::not_found : ec; + + const std::size_t result_n = + (ec || search_position_ == not_found) + ? 0 : search_position_; + + handler_(result_ec, result_n); + } + } + + //private: + AsyncReadStream& stream_; + DynamicBuffer_v2 buffers_; + RegEx expr_; + int start_; + std::size_t search_position_; + std::size_t bytes_to_read_; + ReadHandler handler_; + }; + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename RegEx, typename ReadHandler> + inline void* asio_handler_allocate(std::size_t size, + read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename RegEx, typename ReadHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename RegEx, typename ReadHandler> + inline bool asio_handler_is_continuation( + read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) + { + return this_handler->start_ == 0 ? true + : boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename RegEx, typename ReadHandler> + inline void asio_handler_invoke(Function& function, + read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename RegEx, typename ReadHandler> + inline void asio_handler_invoke(const Function& function, + read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + struct initiate_async_read_until_expr_v2 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v2, typename RegEx> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + read_until_expr_op_v2<AsyncReadStream, + typename decay<DynamicBuffer_v2>::type, + RegEx, typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + expr, handler2.value)(boost::system::error_code(), 0, 1); + } + }; +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename RegEx, typename ReadHandler, typename Allocator> +struct associated_allocator< + detail::read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>, + Allocator> +{ + typedef typename associated_allocator<ReadHandler, Allocator>::type type; + + static type get( + const detail::read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>& h, + const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT + { + return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); + } +}; + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename RegEx, typename ReadHandler, typename Executor> +struct associated_executor< + detail::read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>, + Executor> +{ + typedef typename associated_executor<ReadHandler, Executor>::type type; + + static type get( + const detail::read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>& h, + const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + { + return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + const boost::regex& expr, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_until_expr_v2(), handler, + &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr); +} + +#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX) + +namespace detail +{ + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename MatchCondition, typename ReadHandler> + class read_until_match_op_v2 + { + public: + template <typename BufferSequence> + read_until_match_op_v2(AsyncReadStream& stream, + BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, + MatchCondition match_condition, ReadHandler& handler) + : stream_(stream), + buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), + match_condition_(match_condition), + start_(0), + search_position_(0), + bytes_to_read_(0), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + read_until_match_op_v2(const read_until_match_op_v2& other) + : stream_(other.stream_), + buffers_(other.buffers_), + match_condition_(other.match_condition_), + start_(other.start_), + search_position_(other.search_position_), + bytes_to_read_(other.bytes_to_read_), + handler_(other.handler_) + { + } + + read_until_match_op_v2(read_until_match_op_v2&& other) + : stream_(other.stream_), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + match_condition_(other.match_condition_), + start_(other.start_), + search_position_(other.search_position_), + bytes_to_read_(other.bytes_to_read_), + handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + const std::size_t not_found = (std::numeric_limits<std::size_t>::max)(); + std::size_t pos; + switch (start_ = start) + { + case 1: + for (;;) + { + { + // Determine the range of the data to be searched. + typedef typename DynamicBuffer_v2::const_buffers_type + buffers_type; + typedef buffers_iterator<buffers_type> iterator; + buffers_type data_buffers = + const_cast<const DynamicBuffer_v2&>(buffers_).data( + 0, buffers_.size()); + iterator begin = iterator::begin(data_buffers); + iterator start_pos = begin + search_position_; + iterator end = iterator::end(data_buffers); + + // Look for a match. + std::pair<iterator, bool> result = match_condition_(start_pos, end); + if (result.second) + { + // Full match. We're done. + search_position_ = result.first - begin; + bytes_to_read_ = 0; + } + + // No match yet. Check if buffer is full. + else if (buffers_.size() == buffers_.max_size()) + { + search_position_ = not_found; + bytes_to_read_ = 0; + } + + // Need to read some more data. + else + { + if (result.first != end) + { + // Partial match. Next search needs to start from beginning of + // match. + search_position_ = result.first - begin; + } + else + { + // Next search can start with the new data. + search_position_ = end - begin; + } + + bytes_to_read_ = std::min<std::size_t>( + std::max<std::size_t>(512, + buffers_.capacity() - buffers_.size()), + std::min<std::size_t>(65536, + buffers_.max_size() - buffers_.size())); + } + } + + // Check if we're done. + if (!start && bytes_to_read_ == 0) + break; + + // Start a new asynchronous read op_v2eration to obtain more data. + pos = buffers_.size(); + buffers_.grow(bytes_to_read_); + stream_.async_read_some(buffers_.data(pos, bytes_to_read_), + BOOST_ASIO_MOVE_CAST(read_until_match_op_v2)(*this)); + return; default: + buffers_.shrink(bytes_to_read_ - bytes_transferred); + if (ec || bytes_transferred == 0) + break; + } + + const boost::system::error_code result_ec = + (search_position_ == not_found) + ? error::not_found : ec; + + const std::size_t result_n = + (ec || search_position_ == not_found) + ? 0 : search_position_; + + handler_(result_ec, result_n); + } + } + + //private: + AsyncReadStream& stream_; + DynamicBuffer_v2 buffers_; + MatchCondition match_condition_; + int start_; + std::size_t search_position_; + std::size_t bytes_to_read_; + ReadHandler handler_; + }; + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename MatchCondition, typename ReadHandler> + inline void* asio_handler_allocate(std::size_t size, + read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, + MatchCondition, ReadHandler>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename MatchCondition, typename ReadHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, + MatchCondition, ReadHandler>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename MatchCondition, typename ReadHandler> + inline bool asio_handler_is_continuation( + read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, + MatchCondition, ReadHandler>* this_handler) + { + return this_handler->start_ == 0 ? true + : boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename MatchCondition, + typename ReadHandler> + inline void asio_handler_invoke(Function& function, + read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, + MatchCondition, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename AsyncReadStream, + typename DynamicBuffer_v2, typename MatchCondition, + typename ReadHandler> + inline void asio_handler_invoke(const Function& function, + read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, + MatchCondition, ReadHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + struct initiate_async_read_until_match_v2 + { + template <typename ReadHandler, typename AsyncReadStream, + typename DynamicBuffer_v2, typename MatchCondition> + void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) 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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + non_const_lvalue<ReadHandler> handler2(handler); + read_until_match_op_v2<AsyncReadStream, + typename decay<DynamicBuffer_v2>::type, + MatchCondition, typename decay<ReadHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + match_condition, handler2.value)(boost::system::error_code(), 0, 1); + } + }; +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename MatchCondition, typename ReadHandler, typename Allocator> +struct associated_allocator< + detail::read_until_match_op_v2<AsyncReadStream, + DynamicBuffer_v2, MatchCondition, ReadHandler>, + Allocator> +{ + typedef typename associated_allocator<ReadHandler, Allocator>::type type; + + static type get( + const detail::read_until_match_op_v2<AsyncReadStream, + DynamicBuffer_v2, MatchCondition, ReadHandler>& h, + const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT + { + return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a); + } +}; + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename MatchCondition, typename ReadHandler, typename Executor> +struct associated_executor< + detail::read_until_match_op_v2<AsyncReadStream, + DynamicBuffer_v2, MatchCondition, ReadHandler>, + Executor> +{ + typedef typename associated_executor<ReadHandler, Executor>::type type; + + static type get( + const detail::read_until_match_op_v2<AsyncReadStream, + DynamicBuffer_v2, MatchCondition, ReadHandler>& h, + const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + { + return associated_executor<ReadHandler, Executor>::get(h.handler_, ex); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename MatchCondition, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_read_until_match_v2(), handler, + &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), match_condition); +} + +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) } // namespace asio } // namespace boost diff --git a/boost/asio/experimental/impl/redirect_error.hpp b/boost/asio/impl/redirect_error.hpp index 00ffcc7848..eb0d82998a 100644 --- a/boost/asio/experimental/impl/redirect_error.hpp +++ b/boost/asio/impl/redirect_error.hpp @@ -1,15 +1,15 @@ + +// impl/redirect_error.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ // -// experimental/impl/redirect_error.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef BOOST_ASIO_EXPERIMENTAL_IMPL_REDIRECT_ERROR_HPP -#define BOOST_ASIO_EXPERIMENTAL_IMPL_REDIRECT_ERROR_HPP +#ifndef BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP +#define BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -24,14 +24,12 @@ #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/detail/variadic_templates.hpp> -#include <boost/asio/handler_type.hpp> #include <boost/system/system_error.hpp> #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { -namespace experimental { namespace detail { // Class to adapt a redirect_error_t as a completion handler. @@ -39,6 +37,8 @@ template <typename Handler> class redirect_error_handler { public: + typedef void result_type; + template <typename CompletionToken> redirect_error_handler(redirect_error_t<CompletionToken> e) : ec_(e.ec_), @@ -46,6 +46,14 @@ public: { } + template <typename RedirectedHandler> + redirect_error_handler(boost::system::error_code& ec, + BOOST_ASIO_MOVE_ARG(RedirectedHandler) h) + : ec_(ec), + handler_(BOOST_ASIO_MOVE_CAST(RedirectedHandler)(h)) + { + } + void operator()() { handler_(); @@ -212,60 +220,131 @@ struct redirect_error_signature<R(const boost::system::error_code&)> #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) } // namespace detail -} // namespace experimental #if !defined(GENERATING_DOCUMENTATION) template <typename CompletionToken, typename Signature> -struct async_result<experimental::redirect_error_t<CompletionToken>, Signature> - : async_result<CompletionToken, - typename experimental::detail::redirect_error_signature<Signature>::type> +struct async_result<redirect_error_t<CompletionToken>, Signature> { - typedef experimental::detail::redirect_error_handler< - typename async_result<CompletionToken, - typename experimental::detail::redirect_error_signature<Signature>::type> - ::completion_handler_type> completion_handler_type; - - explicit async_result(completion_handler_type& h) - : async_result<CompletionToken, - typename experimental::detail::redirect_error_signature< - Signature>::type>(h.handler_) + typedef typename async_result<CompletionToken, + typename detail::redirect_error_signature<Signature>::type> + ::return_type return_type; + + template <typename Initiation> + struct init_wrapper { - } -}; + template <typename Init> + init_wrapper(boost::system::error_code& ec, BOOST_ASIO_MOVE_ARG(Init) init) + : ec_(ec), + initiation_(BOOST_ASIO_MOVE_CAST(Init)(init)) + { + } -#if !defined(BOOST_ASIO_NO_DEPRECATED) +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) -template <typename CompletionToken, typename Signature> -struct handler_type<experimental::redirect_error_t<CompletionToken>, Signature> -{ - typedef experimental::detail::redirect_error_handler< - typename async_result<CompletionToken, - typename experimental::detail::redirect_error_signature<Signature>::type> - ::completion_handler_type> type; -}; + template <typename Handler, typename... Args> + void operator()( + BOOST_ASIO_MOVE_ARG(Handler) handler, + BOOST_ASIO_MOVE_ARG(Args)... args) + { + BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( + detail::redirect_error_handler< + typename decay<Handler>::type>( + ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), + BOOST_ASIO_MOVE_CAST(Args)(args)...); + } -template <typename Handler> -struct async_result<experimental::detail::redirect_error_handler<Handler> > - : async_result<Handler> -{ - explicit async_result( - experimental::detail::redirect_error_handler<Handler>& h) - : async_result<Handler>(h.handler_) +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename Handler> + void operator()( + BOOST_ASIO_MOVE_ARG(Handler) handler) + { + BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( + detail::redirect_error_handler< + typename decay<Handler>::type>( + ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler))); + } + +#define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \ + template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + void operator()( \ + BOOST_ASIO_MOVE_ARG(Handler) handler, \ + BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \ + detail::redirect_error_handler< \ + typename decay<Handler>::type>( \ + ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \ + BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF) +#undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + boost::system::error_code& ec_; + Initiation initiation_; + }; + +#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static return_type initiate( + BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, + BOOST_ASIO_MOVE_ARG(Args)... args) { + return async_initiate<CompletionToken, + typename detail::redirect_error_signature<Signature>::type>( + init_wrapper<typename decay<Initiation>::type>( + token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), + token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...); + } + +#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename Initiation, typename RawCompletionToken> + static return_type initiate( + BOOST_ASIO_MOVE_ARG(Initiation) initiation, + BOOST_ASIO_MOVE_ARG(RawCompletionToken) token) + { + return async_initiate<CompletionToken, + typename detail::redirect_error_signature<Signature>::type>( + init_wrapper<typename decay<Initiation>::type>( + token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), + token.token_); } -}; -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) +#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \ + template <typename Initiation, typename RawCompletionToken, \ + BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + static return_type initiate( \ + BOOST_ASIO_MOVE_ARG(Initiation) initiation, \ + BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \ + BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \ + { \ + return async_initiate<CompletionToken, \ + typename detail::redirect_error_signature<Signature>::type>( \ + init_wrapper<typename decay<Initiation>::type>( \ + token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \ + token.token_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ + } \ + /**/ + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF) +#undef BOOST_ASIO_PRIVATE_INITIATE_DEF + +#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +}; template <typename Handler, typename Executor> -struct associated_executor< - experimental::detail::redirect_error_handler<Handler>, Executor> +struct associated_executor<detail::redirect_error_handler<Handler>, Executor> { typedef typename associated_executor<Handler, Executor>::type type; static type get( - const experimental::detail::redirect_error_handler<Handler>& h, + const detail::redirect_error_handler<Handler>& h, const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT { return associated_executor<Handler, Executor>::get(h.handler_, ex); @@ -273,13 +352,12 @@ struct associated_executor< }; template <typename Handler, typename Allocator> -struct associated_allocator< - experimental::detail::redirect_error_handler<Handler>, Allocator> +struct associated_allocator<detail::redirect_error_handler<Handler>, Allocator> { typedef typename associated_allocator<Handler, Allocator>::type type; static type get( - const experimental::detail::redirect_error_handler<Handler>& h, + const detail::redirect_error_handler<Handler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator<Handler, Allocator>::get(h.handler_, a); @@ -293,4 +371,4 @@ struct associated_allocator< #include <boost/asio/detail/pop_options.hpp> -#endif // BOOST_ASIO_EXPERIMENTAL_IMPL_REDIRECT_ERROR_HPP +#endif // BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP diff --git a/boost/asio/impl/serial_port_base.hpp b/boost/asio/impl/serial_port_base.hpp index 7f2dfe88df..c456e30800 100644 --- a/boost/asio/impl/serial_port_base.hpp +++ b/boost/asio/impl/serial_port_base.hpp @@ -2,7 +2,7 @@ // impl/serial_port_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/impl/serial_port_base.ipp b/boost/asio/impl/serial_port_base.ipp index 9954f77d2e..c7ff51876a 100644 --- a/boost/asio/impl/serial_port_base.ipp +++ b/boost/asio/impl/serial_port_base.ipp @@ -2,7 +2,7 @@ // impl/serial_port_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/impl/spawn.hpp b/boost/asio/impl/spawn.hpp index c2da5ce09a..cf4ce5622f 100644 --- a/boost/asio/impl/spawn.hpp +++ b/boost/asio/impl/spawn.hpp @@ -2,7 +2,7 @@ // impl/spawn.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -278,51 +278,6 @@ public: } }; -#if !defined(BOOST_ASIO_NO_DEPRECATED) - -template <typename Handler, typename ReturnType> -struct handler_type<basic_yield_context<Handler>, ReturnType()> -{ - typedef detail::coro_handler<Handler, void> type; -}; - -template <typename Handler, typename ReturnType, typename Arg1> -struct handler_type<basic_yield_context<Handler>, ReturnType(Arg1)> -{ - typedef detail::coro_handler<Handler, typename decay<Arg1>::type> type; -}; - -template <typename Handler, typename ReturnType> -struct handler_type<basic_yield_context<Handler>, - ReturnType(boost::system::error_code)> -{ - typedef detail::coro_handler<Handler, void> type; -}; - -template <typename Handler, typename ReturnType, typename Arg2> -struct handler_type<basic_yield_context<Handler>, - ReturnType(boost::system::error_code, Arg2)> -{ - typedef detail::coro_handler<Handler, typename decay<Arg2>::type> type; -}; - -template <typename Handler, typename T> -class async_result<detail::coro_handler<Handler, T> > - : public detail::coro_async_result<Handler, T> -{ -public: - typedef typename detail::coro_async_result<Handler, T>::return_type type; - - explicit async_result( - typename detail::coro_async_result<Handler, - T>::completion_handler_type& h) - : detail::coro_async_result<Handler, T>(h) - { - } -}; - -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - template <typename Handler, typename T, typename Allocator> struct associated_allocator<detail::coro_handler<Handler, T>, Allocator> { diff --git a/boost/asio/impl/src.cpp b/boost/asio/impl/src.cpp index 3823acfaf3..8f43dbf0ca 100644 --- a/boost/asio/impl/src.cpp +++ b/boost/asio/impl/src.cpp @@ -2,7 +2,7 @@ // impl/src.cpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/src.hpp b/boost/asio/impl/src.hpp index b891a453fe..7f155ad25c 100644 --- a/boost/asio/impl/src.hpp +++ b/boost/asio/impl/src.hpp @@ -2,7 +2,7 @@ // impl/src.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/system_context.hpp b/boost/asio/impl/system_context.hpp index dab5d4d085..2a6b61f312 100644 --- a/boost/asio/impl/system_context.hpp +++ b/boost/asio/impl/system_context.hpp @@ -2,7 +2,7 @@ // impl/system_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/system_context.ipp b/boost/asio/impl/system_context.ipp index e56632c816..0ec6fad171 100644 --- a/boost/asio/impl/system_context.ipp +++ b/boost/asio/impl/system_context.ipp @@ -2,7 +2,7 @@ // impl/system_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,7 +35,7 @@ struct system_context::thread_function }; system_context::system_context() - : scheduler_(use_service<detail::scheduler>(*this)) + : scheduler_(add_scheduler(new detail::scheduler(*this, 0, false))) { scheduler_.work_started(); @@ -67,6 +67,13 @@ void system_context::join() threads_.join(); } +detail::scheduler& system_context::add_scheduler(detail::scheduler* s) +{ + detail::scoped_ptr<detail::scheduler> scoped_impl(s); + boost::asio::add_service<detail::scheduler>(*this, scoped_impl.get()); + return *scoped_impl.release(); +} + } // namespace asio } // namespace boost diff --git a/boost/asio/impl/system_executor.hpp b/boost/asio/impl/system_executor.hpp index c59e780d3f..25c51a6560 100644 --- a/boost/asio/impl/system_executor.hpp +++ b/boost/asio/impl/system_executor.hpp @@ -2,7 +2,7 @@ // impl/system_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/thread_pool.hpp b/boost/asio/impl/thread_pool.hpp index ed8d768cd0..31d8b37ee0 100644 --- a/boost/asio/impl/thread_pool.hpp +++ b/boost/asio/impl/thread_pool.hpp @@ -2,7 +2,7 @@ // impl/thread_pool.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/impl/thread_pool.ipp b/boost/asio/impl/thread_pool.ipp index e0952eb657..d59b6ef15f 100644 --- a/boost/asio/impl/thread_pool.ipp +++ b/boost/asio/impl/thread_pool.ipp @@ -2,7 +2,7 @@ // impl/thread_pool.ipp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -35,7 +35,7 @@ struct thread_pool::thread_function }; thread_pool::thread_pool() - : scheduler_(use_service<detail::scheduler>(*this)) + : scheduler_(add_scheduler(new detail::scheduler(*this, 0, false))) { scheduler_.work_started(); @@ -45,7 +45,8 @@ thread_pool::thread_pool() } thread_pool::thread_pool(std::size_t num_threads) - : scheduler_(use_service<detail::scheduler>(*this)) + : scheduler_(add_scheduler(new detail::scheduler( + *this, num_threads == 1 ? 1 : 0, false))) { scheduler_.work_started(); @@ -66,8 +67,18 @@ void thread_pool::stop() void thread_pool::join() { - scheduler_.work_finished(); - threads_.join(); + if (!threads_.empty()) + { + scheduler_.work_finished(); + threads_.join(); + } +} + +detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s) +{ + detail::scoped_ptr<detail::scheduler> scoped_impl(s); + boost::asio::add_service<detail::scheduler>(*this, scoped_impl.get()); + return *scoped_impl.release(); } } // namespace asio diff --git a/boost/asio/impl/use_awaitable.hpp b/boost/asio/impl/use_awaitable.hpp new file mode 100644 index 0000000000..0d7ad0a42b --- /dev/null +++ b/boost/asio/impl/use_awaitable.hpp @@ -0,0 +1,278 @@ +// +// impl/use_awaitable.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IMPL_USE_AWAITABLE_HPP +#define BOOST_ASIO_IMPL_USE_AWAITABLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/async_result.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Executor, typename T> +class awaitable_handler_base + : public awaitable_thread<Executor> +{ +public: + typedef void result_type; + typedef awaitable<T, Executor> awaitable_type; + + // Construct from the entry point of a new thread of execution. + awaitable_handler_base(awaitable<void, Executor> a, const Executor& ex) + : awaitable_thread<Executor>(std::move(a), ex) + { + } + + // Transfer ownership from another awaitable_thread. + explicit awaitable_handler_base(awaitable_thread<Executor>* h) + : awaitable_thread<Executor>(std::move(*h)) + { + } + +protected: + awaitable_frame<T, Executor>* frame() noexcept + { + return static_cast<awaitable_frame<T, Executor>*>(this->top_of_stack_); + } +}; + +template <typename, typename...> +class awaitable_handler; + +template <typename Executor> +class awaitable_handler<Executor, void> + : public awaitable_handler_base<Executor, void> +{ +public: + using awaitable_handler_base<Executor, void>::awaitable_handler_base; + + void operator()() + { + this->frame()->attach_thread(this); + this->frame()->return_void(); + this->frame()->pop_frame(); + this->pump(); + } +}; + +template <typename Executor> +class awaitable_handler<Executor, boost::system::error_code> + : public awaitable_handler_base<Executor, void> +{ +public: + using awaitable_handler_base<Executor, void>::awaitable_handler_base; + + void operator()(const boost::system::error_code& ec) + { + this->frame()->attach_thread(this); + if (ec) + this->frame()->set_error(ec); + else + this->frame()->return_void(); + this->frame()->pop_frame(); + this->pump(); + } +}; + +template <typename Executor> +class awaitable_handler<Executor, std::exception_ptr> + : public awaitable_handler_base<Executor, void> +{ +public: + using awaitable_handler_base<Executor, void>::awaitable_handler_base; + + void operator()(std::exception_ptr ex) + { + this->frame()->attach_thread(this); + if (ex) + this->frame()->set_except(ex); + else + this->frame()->return_void(); + this->frame()->pop_frame(); + this->pump(); + } +}; + +template <typename Executor, typename T> +class awaitable_handler<Executor, T> + : public awaitable_handler_base<Executor, T> +{ +public: + using awaitable_handler_base<Executor, T>::awaitable_handler_base; + + template <typename Arg> + void operator()(Arg&& arg) + { + this->frame()->attach_thread(this); + this->frame()->return_value(std::forward<Arg>(arg)); + this->frame()->pop_frame(); + this->pump(); + } +}; + +template <typename Executor, typename T> +class awaitable_handler<Executor, boost::system::error_code, T> + : public awaitable_handler_base<Executor, T> +{ +public: + using awaitable_handler_base<Executor, T>::awaitable_handler_base; + + template <typename Arg> + void operator()(const boost::system::error_code& ec, Arg&& arg) + { + this->frame()->attach_thread(this); + if (ec) + this->frame()->set_error(ec); + else + this->frame()->return_value(std::forward<Arg>(arg)); + this->frame()->pop_frame(); + this->pump(); + } +}; + +template <typename Executor, typename T> +class awaitable_handler<Executor, std::exception_ptr, T> + : public awaitable_handler_base<Executor, T> +{ +public: + using awaitable_handler_base<Executor, T>::awaitable_handler_base; + + template <typename Arg> + void operator()(std::exception_ptr ex, Arg&& arg) + { + this->frame()->attach_thread(this); + if (ex) + this->frame()->set_except(ex); + else + this->frame()->return_value(std::forward<Arg>(arg)); + this->frame()->pop_frame(); + this->pump(); + } +}; + +template <typename Executor, typename... Ts> +class awaitable_handler + : public awaitable_handler_base<Executor, std::tuple<Ts...>> +{ +public: + using awaitable_handler_base<Executor, + std::tuple<Ts...>>::awaitable_handler_base; + + template <typename... Args> + void operator()(Args&&... args) + { + this->frame()->attach_thread(this); + this->frame()->return_values(std::forward<Args>(args)...); + this->frame()->pop_frame(); + this->pump(); + } +}; + +template <typename Executor, typename... Ts> +class awaitable_handler<Executor, boost::system::error_code, Ts...> + : public awaitable_handler_base<Executor, std::tuple<Ts...>> +{ +public: + using awaitable_handler_base<Executor, + std::tuple<Ts...>>::awaitable_handler_base; + + template <typename... Args> + void operator()(const boost::system::error_code& ec, Args&&... args) + { + this->frame()->attach_thread(this); + if (ec) + this->frame()->set_error(ec); + else + this->frame()->return_values(std::forward<Args>(args)...); + this->frame()->pop_frame(); + this->pump(); + } +}; + +template <typename Executor, typename... Ts> +class awaitable_handler<Executor, std::exception_ptr, Ts...> + : public awaitable_handler_base<Executor, std::tuple<Ts...>> +{ +public: + using awaitable_handler_base<Executor, + std::tuple<Ts...>>::awaitable_handler_base; + + template <typename... Args> + void operator()(std::exception_ptr ex, Args&&... args) + { + this->frame()->attach_thread(this); + if (ex) + this->frame()->set_except(ex); + else + this->frame()->return_values(std::forward<Args>(args)...); + this->frame()->pop_frame(); + this->pump(); + } +}; + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename Executor, typename R, typename... Args> +class async_result<use_awaitable_t<Executor>, R(Args...)> +{ +public: + typedef typename detail::awaitable_handler< + Executor, typename decay<Args>::type...> handler_type; + typedef typename handler_type::awaitable_type return_type; + +#if defined(_MSC_VER) + template <typename T> + static T dummy_return() + { + return std::move(*static_cast<T*>(nullptr)); + } + + template <> + static void dummy_return() + { + } +#endif // defined(_MSC_VER) + + template <typename Initiation, typename... InitArgs> + static return_type initiate(Initiation initiation, + use_awaitable_t<Executor>, InitArgs... args) + { + co_await [&](auto* frame) + { + handler_type handler(frame->detach_thread()); + std::move(initiation)(std::move(handler), std::move(args)...); + return static_cast<handler_type*>(nullptr); + }; + + for (;;) {} // Never reached. +#if defined(_MSC_VER) + co_return dummy_return<typename return_type::value_type>(); +#endif // defined(_MSC_VER) + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_IMPL_USE_AWAITABLE_HPP diff --git a/boost/asio/impl/use_future.hpp b/boost/asio/impl/use_future.hpp index fd75a7c8e8..83fb74aecb 100644 --- a/boost/asio/impl/use_future.hpp +++ b/boost/asio/impl/use_future.hpp @@ -2,7 +2,7 @@ // impl/use_future.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -879,56 +879,6 @@ public: #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) -#if !defined(BOOST_ASIO_NO_DEPRECATED) - -template <typename Allocator, typename Signature> -struct handler_type<use_future_t<Allocator>, Signature> -{ - typedef typename async_result<use_future_t<Allocator>, - Signature>::completion_handler_type type; -}; - -template <typename Signature, typename Allocator> -class async_result<detail::promise_handler<Signature, Allocator> > - : public detail::promise_async_result<Signature, Allocator> -{ -public: - typedef typename detail::promise_async_result< - Signature, Allocator>::return_type type; - - explicit async_result( - typename detail::promise_async_result< - Signature, Allocator>::completion_handler_type& h) - : detail::promise_async_result<Signature, Allocator>(h) - { - } -}; - -template <typename Function, typename Allocator, typename Signature> -struct handler_type<detail::packaged_token<Function, Allocator>, Signature> -{ - typedef typename async_result<detail::packaged_token<Function, Allocator>, - Signature>::completion_handler_type type; -}; - -template <typename Function, typename Allocator, typename Result> -class async_result<detail::packaged_handler<Function, Allocator, Result> > - : public detail::packaged_async_result<Function, Allocator, Result> -{ -public: - typedef typename detail::packaged_async_result< - Function, Allocator, Result>::return_type type; - - explicit async_result( - typename detail::packaged_async_result< - Function, Allocator, Result>::completion_handler_type& h) - : detail::packaged_async_result<Function, Allocator, Result>(h) - { - } -}; - -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - #endif // !defined(GENERATING_DOCUMENTATION) } // namespace asio diff --git a/boost/asio/impl/write.hpp b/boost/asio/impl/write.hpp index 0be48b89f4..96243591ec 100644 --- a/boost/asio/impl/write.hpp +++ b/boost/asio/impl/write.hpp @@ -2,7 +2,7 @@ // impl/write.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,6 +28,7 @@ #include <boost/asio/detail/handler_cont_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/detail/push_options.hpp> @@ -67,7 +68,8 @@ inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, >::type*) { return detail::write_buffer_sequence(s, buffers, - boost::asio::buffer_sequence_begin(buffers), completion_condition, ec); + boost::asio::buffer_sequence_begin(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); } template <typename SyncWriteStream, typename ConstBufferSequence> @@ -101,68 +103,76 @@ inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, >::type*) { boost::system::error_code ec; - std::size_t bytes_transferred = write(s, buffers, completion_condition, ec); + std::size_t bytes_transferred = write(s, buffers, + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); boost::asio::detail::throw_error(ec, "write"); return bytes_transferred; } -template <typename SyncWriteStream, typename DynamicBuffer, +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +template <typename SyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t write(SyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, boost::system::error_code& ec, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { - typename decay<DynamicBuffer>::type b( - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers)); + typename decay<DynamicBuffer_v1>::type b( + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); - std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec); + std::size_t bytes_transferred = write(s, b.data(), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); b.consume(bytes_transferred); return bytes_transferred; } -template <typename SyncWriteStream, typename DynamicBuffer> +template <typename SyncWriteStream, typename DynamicBuffer_v1> inline std::size_t write(SyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { boost::system::error_code ec; std::size_t bytes_transferred = write(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec); boost::asio::detail::throw_error(ec, "write"); return bytes_transferred; } -template <typename SyncWriteStream, typename DynamicBuffer> +template <typename SyncWriteStream, typename DynamicBuffer_v1> inline std::size_t write(SyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, boost::system::error_code& ec, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { - return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), + return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec); } -template <typename SyncWriteStream, typename DynamicBuffer, +template <typename SyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { boost::system::error_code ec; std::size_t bytes_transferred = write(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), - completion_condition, ec); + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); boost::asio::detail::throw_error(ec, "write"); return bytes_transferred; } @@ -176,7 +186,8 @@ inline std::size_t write(SyncWriteStream& s, boost::asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition, boost::system::error_code& ec) { - return write(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec); + return write(s, basic_streambuf_ref<Allocator>(b), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); } template <typename SyncWriteStream, typename Allocator> @@ -200,11 +211,68 @@ inline std::size_t write(SyncWriteStream& s, boost::asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition) { - return write(s, basic_streambuf_ref<Allocator>(b), completion_condition); + return write(s, basic_streambuf_ref<Allocator>(b), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +template <typename SyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition> +std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + buffers.consume(bytes_transferred); + return bytes_transferred; +} + +template <typename SyncWriteStream, typename DynamicBuffer_v2> +inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + transfer_all(), ec); + boost::asio::detail::throw_error(ec, "write"); + return bytes_transferred; +} + +template <typename SyncWriteStream, typename DynamicBuffer_v2> +inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, + boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + transfer_all(), ec); +} + +template <typename SyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition> +inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + boost::asio::detail::throw_error(ec, "write"); + return bytes_transferred; +} namespace detail { @@ -216,7 +284,7 @@ namespace detail { public: write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, WriteHandler& handler) + CompletionCondition& completion_condition, WriteHandler& handler) : detail::base_from_completion_cond< CompletionCondition>(completion_condition), stream_(stream), @@ -237,9 +305,11 @@ namespace detail } write_op(write_op&& other) - : detail::base_from_completion_cond<CompletionCondition>(other), + : detail::base_from_completion_cond<CompletionCondition>( + BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< + CompletionCondition>)(other)), stream_(other.stream_), - buffers_(other.buffers_), + buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)), start_(other.start_), handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) { @@ -270,9 +340,11 @@ namespace detail } //private: + typedef boost::asio::detail::consuming_buffers<const_buffer, + ConstBufferSequence, ConstBufferIterator> buffers_type; + AsyncWriteStream& stream_; - boost::asio::detail::consuming_buffers<const_buffer, - ConstBufferSequence, ConstBufferIterator> buffers_; + buffers_type buffers_; int start_; WriteHandler handler_; }; @@ -338,7 +410,7 @@ namespace detail typename WriteHandler> inline void start_write_buffer_sequence_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers, const ConstBufferIterator&, - CompletionCondition completion_condition, WriteHandler& handler) + CompletionCondition& completion_condition, WriteHandler& handler) { detail::write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>( @@ -346,6 +418,25 @@ namespace detail boost::system::error_code(), 0, 1); } + struct initiate_async_write_buffer_sequence + { + template <typename WriteHandler, typename AsyncWriteStream, + typename ConstBufferSequence, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + AsyncWriteStream* s, const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue<WriteHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + start_write_buffer_sequence_op(*s, buffers, + boost::asio::buffer_sequence_begin(buffers), + completion_cond2.value, handler2.value); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -401,18 +492,10 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, is_const_buffer_sequence<ConstBufferSequence>::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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::start_write_buffer_sequence_op(s, buffers, - boost::asio::buffer_sequence_begin(buffers), completion_condition, - init.completion_handler); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_write_buffer_sequence(), handler, &s, buffers, + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncWriteStream, typename ConstBufferSequence, @@ -425,31 +508,25 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, is_const_buffer_sequence<ConstBufferSequence>::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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::start_write_buffer_sequence_op(s, buffers, - boost::asio::buffer_sequence_begin(buffers), transfer_all(), - init.completion_handler); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_write_buffer_sequence(), + handler, &s, buffers, transfer_all()); } +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + namespace detail { - template <typename AsyncWriteStream, typename DynamicBuffer, + template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> - class write_dynbuf_op + class write_dynbuf_v1_op { public: template <typename BufferSequence> - write_dynbuf_op(AsyncWriteStream& stream, + write_dynbuf_v1_op(AsyncWriteStream& stream, BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, - CompletionCondition completion_condition, WriteHandler& handler) + CompletionCondition& completion_condition, WriteHandler& handler) : stream_(stream), buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), completion_condition_( @@ -459,7 +536,7 @@ namespace detail } #if defined(BOOST_ASIO_HAS_MOVE) - write_dynbuf_op(const write_dynbuf_op& other) + write_dynbuf_v1_op(const write_dynbuf_v1_op& other) : stream_(other.stream_), buffers_(other.buffers_), completion_condition_(other.completion_condition_), @@ -467,9 +544,9 @@ namespace detail { } - write_dynbuf_op(write_dynbuf_op&& other) + write_dynbuf_v1_op(write_dynbuf_v1_op&& other) : stream_(other.stream_), - buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), completion_condition_( BOOST_ASIO_MOVE_CAST(CompletionCondition)( other.completion_condition_)), @@ -484,8 +561,9 @@ namespace detail switch (start) { case 1: - async_write(stream_, buffers_.data(), completion_condition_, - BOOST_ASIO_MOVE_CAST(write_dynbuf_op)(*this)); + async_write(stream_, buffers_.data(), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_), + BOOST_ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this)); return; default: buffers_.consume(bytes_transferred); handler_(ec, static_cast<const std::size_t&>(bytes_transferred)); @@ -494,35 +572,35 @@ namespace detail //private: AsyncWriteStream& stream_; - DynamicBuffer buffers_; + DynamicBuffer_v1 buffers_; CompletionCondition completion_condition_; WriteHandler handler_; }; - template <typename AsyncWriteStream, typename DynamicBuffer, + template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> inline void* asio_handler_allocate(std::size_t size, - write_dynbuf_op<AsyncWriteStream, DynamicBuffer, + write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>* this_handler) { return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); } - template <typename AsyncWriteStream, typename DynamicBuffer, + template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> inline void asio_handler_deallocate(void* pointer, std::size_t size, - write_dynbuf_op<AsyncWriteStream, DynamicBuffer, + write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); } - template <typename AsyncWriteStream, typename DynamicBuffer, + template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> inline bool asio_handler_is_continuation( - write_dynbuf_op<AsyncWriteStream, DynamicBuffer, + write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>* this_handler) { return boost_asio_handler_cont_helpers::is_continuation( @@ -530,10 +608,10 @@ namespace detail } template <typename Function, typename AsyncWriteStream, - typename DynamicBuffer, typename CompletionCondition, + typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> inline void asio_handler_invoke(Function& function, - write_dynbuf_op<AsyncWriteStream, DynamicBuffer, + write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( @@ -541,49 +619,72 @@ namespace detail } template <typename Function, typename AsyncWriteStream, - typename DynamicBuffer, typename CompletionCondition, + typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> inline void asio_handler_invoke(const Function& function, - write_dynbuf_op<AsyncWriteStream, DynamicBuffer, + write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); } + + struct initiate_async_write_dynbuf_v1 + { + template <typename WriteHandler, typename AsyncWriteStream, + typename DynamicBuffer_v1, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + AsyncWriteStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue<WriteHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + write_dynbuf_v1_op<AsyncWriteStream, + typename decay<DynamicBuffer_v1>::type, + CompletionCondition, typename decay<WriteHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + completion_cond2.value, handler2.value)( + boost::system::error_code(), 0, 1); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncWriteStream, typename DynamicBuffer, +template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler, typename Allocator> struct associated_allocator< - detail::write_dynbuf_op<AsyncWriteStream, - DynamicBuffer, CompletionCondition, WriteHandler>, + detail::write_dynbuf_v1_op<AsyncWriteStream, + DynamicBuffer_v1, CompletionCondition, WriteHandler>, Allocator> { typedef typename associated_allocator<WriteHandler, Allocator>::type type; static type get( - const detail::write_dynbuf_op<AsyncWriteStream, - DynamicBuffer, CompletionCondition, WriteHandler>& h, + const detail::write_dynbuf_v1_op<AsyncWriteStream, + DynamicBuffer_v1, CompletionCondition, WriteHandler>& h, const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT { return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a); } }; -template <typename AsyncWriteStream, typename DynamicBuffer, +template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler, typename Executor> struct associated_executor< - detail::write_dynbuf_op<AsyncWriteStream, - DynamicBuffer, CompletionCondition, WriteHandler>, + detail::write_dynbuf_v1_op<AsyncWriteStream, + DynamicBuffer_v1, CompletionCondition, WriteHandler>, Executor> { typedef typename associated_executor<WriteHandler, Executor>::type type; static type get( - const detail::write_dynbuf_op<AsyncWriteStream, - DynamicBuffer, CompletionCondition, WriteHandler>& h, + const detail::write_dynbuf_v1_op<AsyncWriteStream, + DynamicBuffer_v1, CompletionCondition, WriteHandler>& h, const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT { return associated_executor<WriteHandler, Executor>::get(h.handler_, ex); @@ -593,49 +694,40 @@ struct associated_executor< #endif // !defined(GENERATING_DOCUMENTATION) template <typename AsyncWriteStream, - typename DynamicBuffer, typename WriteHandler> + typename DynamicBuffer_v1, typename WriteHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) async_write(AsyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type*) { return async_write(s, - BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); } -template <typename AsyncWriteStream, typename DynamicBuffer, +template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) async_write(AsyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::write_dynbuf_op<AsyncWriteStream, - typename decay<DynamicBuffer>::type, - CompletionCondition, BOOST_ASIO_HANDLER_TYPE( - WriteHandler, void (boost::system::error_code, std::size_t))>( - s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), - completion_condition, init.completion_handler)( - boost::system::error_code(), 0, 1); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_write_dynbuf_v1(), handler, &s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -662,11 +754,223 @@ async_write(AsyncWriteStream& s, BOOST_ASIO_MOVE_ARG(WriteHandler) handler) { return async_write(s, basic_streambuf_ref<Allocator>(b), - completion_condition, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); } #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +namespace detail +{ + template <typename AsyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename WriteHandler> + class write_dynbuf_v2_op + { + public: + template <typename BufferSequence> + write_dynbuf_v2_op(AsyncWriteStream& stream, + BOOST_ASIO_MOVE_ARG(BufferSequence) buffers, + CompletionCondition& completion_condition, WriteHandler& handler) + : stream_(stream), + buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)), + completion_condition_( + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)), + handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) + write_dynbuf_v2_op(const write_dynbuf_v2_op& other) + : stream_(other.stream_), + buffers_(other.buffers_), + completion_condition_(other.completion_condition_), + handler_(other.handler_) + { + } + + write_dynbuf_v2_op(write_dynbuf_v2_op&& other) + : stream_(other.stream_), + buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + completion_condition_( + BOOST_ASIO_MOVE_CAST(CompletionCondition)( + other.completion_condition_)), + handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred, int start = 0) + { + switch (start) + { + case 1: + async_write(stream_, buffers_.data(0, buffers_.size()), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_), + BOOST_ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this)); + return; default: + buffers_.consume(bytes_transferred); + handler_(ec, static_cast<const std::size_t&>(bytes_transferred)); + } + } + + //private: + AsyncWriteStream& stream_; + DynamicBuffer_v2 buffers_; + CompletionCondition completion_condition_; + WriteHandler handler_; + }; + + template <typename AsyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename WriteHandler> + inline void* asio_handler_allocate(std::size_t size, + write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, + CompletionCondition, WriteHandler>* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); + } + + template <typename AsyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename WriteHandler> + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, + CompletionCondition, WriteHandler>* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); + } + + template <typename AsyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename WriteHandler> + inline bool asio_handler_is_continuation( + write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, + CompletionCondition, WriteHandler>* this_handler) + { + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); + } + + template <typename Function, typename AsyncWriteStream, + typename DynamicBuffer_v2, typename CompletionCondition, + typename WriteHandler> + inline void asio_handler_invoke(Function& function, + write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, + CompletionCondition, WriteHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + template <typename Function, typename AsyncWriteStream, + typename DynamicBuffer_v2, typename CompletionCondition, + typename WriteHandler> + inline void asio_handler_invoke(const Function& function, + write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, + CompletionCondition, WriteHandler>* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); + } + + struct initiate_async_write_dynbuf_v2 + { + template <typename WriteHandler, typename AsyncWriteStream, + typename DynamicBuffer_v2, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + AsyncWriteStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue<WriteHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + write_dynbuf_v2_op<AsyncWriteStream, + typename decay<DynamicBuffer_v2>::type, + CompletionCondition, typename decay<WriteHandler>::type>( + *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + completion_cond2.value, handler2.value)( + boost::system::error_code(), 0, 1); + } + }; +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename WriteHandler, typename Allocator> +struct associated_allocator< + detail::write_dynbuf_v2_op<AsyncWriteStream, + DynamicBuffer_v2, CompletionCondition, WriteHandler>, + Allocator> +{ + typedef typename associated_allocator<WriteHandler, Allocator>::type type; + + static type get( + const detail::write_dynbuf_v2_op<AsyncWriteStream, + DynamicBuffer_v2, CompletionCondition, WriteHandler>& h, + const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT + { + return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a); + } +}; + +template <typename AsyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename WriteHandler, typename Executor> +struct associated_executor< + detail::write_dynbuf_v2_op<AsyncWriteStream, + DynamicBuffer_v2, CompletionCondition, WriteHandler>, + Executor> +{ + typedef typename associated_executor<WriteHandler, Executor>::type type; + + static type get( + const detail::write_dynbuf_v2_op<AsyncWriteStream, + DynamicBuffer_v2, CompletionCondition, WriteHandler>& h, + const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + { + return associated_executor<WriteHandler, Executor>::get(h.handler_, ex); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +template <typename AsyncWriteStream, + typename DynamicBuffer_v2, typename WriteHandler> +inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) +async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return async_write(s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); +} + +template <typename AsyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename WriteHandler> +inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) +async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type*) +{ + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_write_dynbuf_v2(), handler, &s, + BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); +} } // namespace asio } // namespace boost diff --git a/boost/asio/impl/write_at.hpp b/boost/asio/impl/write_at.hpp index 6b597d2085..3cad9c5b50 100644 --- a/boost/asio/impl/write_at.hpp +++ b/boost/asio/impl/write_at.hpp @@ -2,7 +2,7 @@ // impl/write_at.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -28,6 +28,7 @@ #include <boost/asio/detail/handler_cont_helpers.hpp> #include <boost/asio/detail/handler_invoke_helpers.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/detail/push_options.hpp> @@ -69,7 +70,8 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, CompletionCondition completion_condition, boost::system::error_code& ec) { return detail::write_at_buffer_sequence(d, offset, buffers, - boost::asio::buffer_sequence_begin(buffers), completion_condition, ec); + boost::asio::buffer_sequence_begin(buffers), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); } template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence> @@ -98,8 +100,8 @@ inline std::size_t write_at(SyncRandomAccessWriteDevice& d, CompletionCondition completion_condition) { boost::system::error_code ec; - std::size_t bytes_transferred = write_at( - d, offset, buffers, completion_condition, ec); + std::size_t bytes_transferred = write_at(d, offset, buffers, + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); boost::asio::detail::throw_error(ec, "write_at"); return bytes_transferred; } @@ -113,8 +115,8 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition, boost::system::error_code& ec) { - std::size_t bytes_transferred = write_at( - d, offset, b.data(), completion_condition, ec); + std::size_t bytes_transferred = write_at(d, offset, b.data(), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); b.consume(bytes_transferred); return bytes_transferred; } @@ -144,8 +146,8 @@ inline std::size_t write_at(SyncRandomAccessWriteDevice& d, CompletionCondition completion_condition) { boost::system::error_code ec; - std::size_t bytes_transferred = write_at( - d, offset, b, completion_condition, ec); + std::size_t bytes_transferred = write_at(d, offset, b, + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); boost::asio::detail::throw_error(ec, "write_at"); return bytes_transferred; } @@ -164,7 +166,7 @@ namespace detail public: write_at_op(AsyncRandomAccessWriteDevice& device, uint64_t offset, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, WriteHandler& handler) + CompletionCondition& completion_condition, WriteHandler& handler) : detail::base_from_completion_cond< CompletionCondition>(completion_condition), device_(device), @@ -187,10 +189,12 @@ namespace detail } write_at_op(write_at_op&& other) - : detail::base_from_completion_cond<CompletionCondition>(other), + : detail::base_from_completion_cond<CompletionCondition>( + BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond< + CompletionCondition>)(other)), device_(other.device_), offset_(other.offset_), - buffers_(other.buffers_), + buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)), start_(other.start_), handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_)) { @@ -222,10 +226,12 @@ namespace detail } //private: + typedef boost::asio::detail::consuming_buffers<const_buffer, + ConstBufferSequence, ConstBufferIterator> buffers_type; + AsyncRandomAccessWriteDevice& device_; uint64_t offset_; - boost::asio::detail::consuming_buffers<const_buffer, - ConstBufferSequence, ConstBufferIterator> buffers_; + buffers_type buffers_; int start_; WriteHandler handler_; }; @@ -291,7 +297,7 @@ namespace detail typename CompletionCondition, typename WriteHandler> inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers, - const ConstBufferIterator&, CompletionCondition completion_condition, + const ConstBufferIterator&, CompletionCondition& completion_condition, WriteHandler& handler) { detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, @@ -299,6 +305,27 @@ namespace detail d, offset, buffers, completion_condition, handler)( boost::system::error_code(), 0, 1); } + + struct initiate_async_write_at_buffer_sequence + { + template <typename WriteHandler, typename AsyncRandomAccessWriteDevice, + typename ConstBufferSequence, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + AsyncRandomAccessWriteDevice* d, uint64_t offset, + const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue<WriteHandler> handler2(handler); + non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); + start_write_at_buffer_sequence_op(*d, offset, buffers, + boost::asio::buffer_sequence_begin(buffers), + completion_cond2.value, handler2.value); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -354,18 +381,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d, CompletionCondition completion_condition, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::start_write_at_buffer_sequence_op(d, offset, buffers, - boost::asio::buffer_sequence_begin(buffers), completion_condition, - init.completion_handler); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_write_at_buffer_sequence(), handler, &d, offset, + buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, @@ -376,18 +395,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::start_write_at_buffer_sequence_op(d, offset, buffers, - boost::asio::buffer_sequence_begin(buffers), transfer_all(), - init.completion_handler); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_write_at_buffer_sequence(), + handler, &d, offset, buffers, transfer_all()); } #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -473,13 +484,26 @@ namespace detail function, this_handler->handler_); } - template <typename Allocator, typename WriteHandler> - inline write_at_streambuf_op<Allocator, WriteHandler> - make_write_at_streambuf_op( - boost::asio::basic_streambuf<Allocator>& b, WriteHandler handler) + struct initiate_async_write_at_streambuf { - return write_at_streambuf_op<Allocator, WriteHandler>(b, handler); - } + template <typename WriteHandler, typename AsyncRandomAccessWriteDevice, + typename Allocator, typename CompletionCondition> + void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + AsyncRandomAccessWriteDevice* d, uint64_t offset, + basic_streambuf<Allocator>* b, + BOOST_ASIO_MOVE_ARG(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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + non_const_lvalue<WriteHandler> handler2(handler); + async_write_at(*d, offset, b->data(), + BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), + write_at_streambuf_op<Allocator, typename decay<WriteHandler>::type>( + *b, handler2.value)); + } + }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) @@ -525,19 +549,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d, CompletionCondition completion_condition, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - async_write_at(d, offset, b.data(), completion_condition, - detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE( - WriteHandler, void (boost::system::error_code, std::size_t))>( - b, init.completion_handler)); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_write_at_streambuf(), handler, &d, offset, + &b, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncRandomAccessWriteDevice, typename Allocator, @@ -548,19 +563,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, boost::asio::basic_streambuf<Allocator>& b, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - async_write_at(d, offset, b.data(), transfer_all(), - detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE( - WriteHandler, void (boost::system::error_code, std::size_t))>( - b, init.completion_handler)); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + detail::initiate_async_write_at_streambuf(), + handler, &d, offset, &b, transfer_all()); } #endif // !defined(BOOST_ASIO_NO_IOSTREAM) diff --git a/boost/asio/io_context.hpp b/boost/asio/io_context.hpp index 51377467ea..1fb3864451 100644 --- a/boost/asio/io_context.hpp +++ b/boost/asio/io_context.hpp @@ -2,7 +2,7 @@ // io_context.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -595,6 +595,11 @@ public: #endif // !defined(BOOST_ASIO_NO_DEPRECATED) private: +#if !defined(BOOST_ASIO_NO_DEPRECATED) + struct initiate_dispatch; + struct initiate_post; +#endif // !defined(BOOST_ASIO_NO_DEPRECATED) + // Helper function to add the implementation. BOOST_ASIO_DECL impl_type& add_impl(impl_type* impl); @@ -769,10 +774,6 @@ public: /// Get the io_context associated with the work. boost::asio::io_context& get_io_context(); - /// (Deprecated: Use get_io_context().) Get the io_context associated with the - /// work. - boost::asio::io_context& get_io_service(); - private: // Prevent assignment. void operator=(const work& other); @@ -790,11 +791,6 @@ public: /// Get the io_context object that owns the service. boost::asio::io_context& get_io_context(); -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// Get the io_context object that owns the service. - boost::asio::io_context& get_io_service(); -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - private: /// Destroy all user-defined handler objects owned by the service. BOOST_ASIO_DECL virtual void shutdown(); diff --git a/boost/asio/io_context_strand.hpp b/boost/asio/io_context_strand.hpp index 144e308a21..a9a9b522cd 100644 --- a/boost/asio/io_context_strand.hpp +++ b/boost/asio/io_context_strand.hpp @@ -2,7 +2,7 @@ // io_context_strand.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -114,36 +114,6 @@ public: { } -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use context().) Get the io_context associated with the - /// strand. - /** - * This function may be used to obtain the io_context object that the strand - * uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the strand will use to - * dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return service_.get_io_context(); - } - - /// (Deprecated: Use context().) Get the io_context associated with the - /// strand. - /** - * This function may be used to obtain the io_context object that the strand - * uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the strand will use to - * dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return service_.get_io_context(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Obtain the underlying execution context. boost::asio::io_context& context() const BOOST_ASIO_NOEXCEPT { @@ -216,16 +186,8 @@ public: BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ()) dispatch(BOOST_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. - BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( - LegacyCompletionHandler, handler) type_check; - - async_completion<LegacyCompletionHandler, void ()> init(handler); - - service_.dispatch(impl_, init.completion_handler); - - return init.result.get(); + return async_initiate<LegacyCompletionHandler, void ()>( + initiate_dispatch(), handler, this); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -271,16 +233,8 @@ public: BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ()) post(BOOST_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. - BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( - LegacyCompletionHandler, handler) type_check; - - async_completion<LegacyCompletionHandler, void ()> init(handler); - - service_.post(impl_, init.completion_handler); - - return init.result.get(); + return async_initiate<LegacyCompletionHandler, void ()>( + initiate_post(), handler, this); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -372,6 +326,42 @@ public: } private: +#if !defined(BOOST_ASIO_NO_DEPRECATED) + struct initiate_dispatch + { + template <typename LegacyCompletionHandler> + void operator()(BOOST_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. + BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( + LegacyCompletionHandler, handler) type_check; + + detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler); + self->service_.dispatch(self->impl_, handler2.value); + } + }; + + struct initiate_post + { + template <typename LegacyCompletionHandler> + void operator()(BOOST_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. + BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( + LegacyCompletionHandler, handler) type_check; + + detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler); + self->service_.post(self->impl_, handler2.value); + } + }; +#endif // !defined(BOOST_ASIO_NO_DEPRECATED) + boost::asio::detail::strand_service& service_; mutable boost::asio::detail::strand_service::implementation_type impl_; }; diff --git a/boost/asio/io_service.hpp b/boost/asio/io_service.hpp index 76af8e0cbd..31f9e9849d 100644 --- a/boost/asio/io_service.hpp +++ b/boost/asio/io_service.hpp @@ -2,7 +2,7 @@ // io_service.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/io_service_strand.hpp b/boost/asio/io_service_strand.hpp index bb38c276c6..93b811b2ec 100644 --- a/boost/asio/io_service_strand.hpp +++ b/boost/asio/io_service_strand.hpp @@ -2,7 +2,7 @@ // io_service_strand.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/address.hpp b/boost/asio/ip/address.hpp index 9b0cbdd3ee..fd6ce95850 100644 --- a/boost/asio/ip/address.hpp +++ b/boost/asio/ip/address.hpp @@ -2,7 +2,7 @@ // ip/address.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -48,46 +48,48 @@ class address { public: /// Default constructor. - BOOST_ASIO_DECL address(); + BOOST_ASIO_DECL address() BOOST_ASIO_NOEXCEPT; /// Construct an address from an IPv4 address. - BOOST_ASIO_DECL address(const boost::asio::ip::address_v4& ipv4_address); + BOOST_ASIO_DECL address( + const boost::asio::ip::address_v4& ipv4_address) BOOST_ASIO_NOEXCEPT; /// Construct an address from an IPv6 address. - BOOST_ASIO_DECL address(const boost::asio::ip::address_v6& ipv6_address); + BOOST_ASIO_DECL address( + const boost::asio::ip::address_v6& ipv6_address) BOOST_ASIO_NOEXCEPT; /// Copy constructor. - BOOST_ASIO_DECL address(const address& other); + BOOST_ASIO_DECL address(const address& other) BOOST_ASIO_NOEXCEPT; #if defined(BOOST_ASIO_HAS_MOVE) /// Move constructor. - BOOST_ASIO_DECL address(address&& other); + BOOST_ASIO_DECL address(address&& other) BOOST_ASIO_NOEXCEPT; #endif // defined(BOOST_ASIO_HAS_MOVE) /// Assign from another address. - BOOST_ASIO_DECL address& operator=(const address& other); + BOOST_ASIO_DECL address& operator=(const address& other) BOOST_ASIO_NOEXCEPT; #if defined(BOOST_ASIO_HAS_MOVE) /// Move-assign from another address. - BOOST_ASIO_DECL address& operator=(address&& other); + BOOST_ASIO_DECL address& operator=(address&& other) BOOST_ASIO_NOEXCEPT; #endif // defined(BOOST_ASIO_HAS_MOVE) /// Assign from an IPv4 address. BOOST_ASIO_DECL address& operator=( - const boost::asio::ip::address_v4& ipv4_address); + const boost::asio::ip::address_v4& ipv4_address) BOOST_ASIO_NOEXCEPT; /// Assign from an IPv6 address. BOOST_ASIO_DECL address& operator=( - const boost::asio::ip::address_v6& ipv6_address); + const boost::asio::ip::address_v6& ipv6_address) BOOST_ASIO_NOEXCEPT; /// Get whether the address is an IP version 4 address. - bool is_v4() const + bool is_v4() const BOOST_ASIO_NOEXCEPT { return type_ == ipv4; } /// Get whether the address is an IP version 6 address. - bool is_v6() const + bool is_v6() const BOOST_ASIO_NOEXCEPT { return type_ == ipv6; } @@ -128,40 +130,46 @@ public: #endif // !defined(BOOST_ASIO_NO_DEPRECATED) /// Determine whether the address is a loopback address. - BOOST_ASIO_DECL bool is_loopback() const; + BOOST_ASIO_DECL bool is_loopback() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is unspecified. - BOOST_ASIO_DECL bool is_unspecified() const; + BOOST_ASIO_DECL bool is_unspecified() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is a multicast address. - BOOST_ASIO_DECL bool is_multicast() const; + BOOST_ASIO_DECL bool is_multicast() const BOOST_ASIO_NOEXCEPT; /// Compare two addresses for equality. - BOOST_ASIO_DECL friend bool operator==(const address& a1, const address& a2); + BOOST_ASIO_DECL friend bool operator==(const address& a1, + const address& a2) BOOST_ASIO_NOEXCEPT; /// Compare two addresses for inequality. - friend bool operator!=(const address& a1, const address& a2) + friend bool operator!=(const address& a1, + const address& a2) BOOST_ASIO_NOEXCEPT { return !(a1 == a2); } /// Compare addresses for ordering. - BOOST_ASIO_DECL friend bool operator<(const address& a1, const address& a2); + BOOST_ASIO_DECL friend bool operator<(const address& a1, + const address& a2) BOOST_ASIO_NOEXCEPT; /// Compare addresses for ordering. - friend bool operator>(const address& a1, const address& a2) + friend bool operator>(const address& a1, + const address& a2) BOOST_ASIO_NOEXCEPT { return a2 < a1; } /// Compare addresses for ordering. - friend bool operator<=(const address& a1, const address& a2) + friend bool operator<=(const address& a1, + const address& a2) BOOST_ASIO_NOEXCEPT { return !(a2 < a1); } /// Compare addresses for ordering. - friend bool operator>=(const address& a1, const address& a2) + friend bool operator>=(const address& a1, + const address& a2) BOOST_ASIO_NOEXCEPT { return !(a1 < a2); } @@ -189,8 +197,8 @@ BOOST_ASIO_DECL address make_address(const char* str); /** * @relates address */ -BOOST_ASIO_DECL address make_address( - const char* str, boost::system::error_code& ec); +BOOST_ASIO_DECL address make_address(const char* str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; /// Create an address from an IPv4 address string in dotted decimal form, /// or from an IPv6 address in hexadecimal notation. @@ -204,8 +212,8 @@ BOOST_ASIO_DECL address make_address(const std::string& str); /** * @relates address */ -BOOST_ASIO_DECL address make_address( - const std::string& str, boost::system::error_code& ec); +BOOST_ASIO_DECL address make_address(const std::string& str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; #if defined(BOOST_ASIO_HAS_STRING_VIEW) \ || defined(GENERATING_DOCUMENTATION) @@ -222,8 +230,8 @@ BOOST_ASIO_DECL address make_address(string_view str); /** * @relates address */ -BOOST_ASIO_DECL address make_address( - string_view str, boost::system::error_code& ec); +BOOST_ASIO_DECL address make_address(string_view str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; #endif // defined(BOOST_ASIO_HAS_STRING_VIEW) // || defined(GENERATING_DOCUMENTATION) diff --git a/boost/asio/ip/address_v4.hpp b/boost/asio/ip/address_v4.hpp index 68d724085d..b612fa0cd7 100644 --- a/boost/asio/ip/address_v4.hpp +++ b/boost/asio/ip/address_v4.hpp @@ -2,7 +2,7 @@ // ip/address_v4.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -61,7 +61,7 @@ public: #endif /// Default constructor. - address_v4() + address_v4() BOOST_ASIO_NOEXCEPT { addr_.s_addr = 0; } @@ -73,21 +73,21 @@ public: BOOST_ASIO_DECL explicit address_v4(uint_type addr); /// Copy constructor. - address_v4(const address_v4& other) + address_v4(const address_v4& other) BOOST_ASIO_NOEXCEPT : addr_(other.addr_) { } #if defined(BOOST_ASIO_HAS_MOVE) /// Move constructor. - address_v4(address_v4&& other) + address_v4(address_v4&& other) BOOST_ASIO_NOEXCEPT : addr_(other.addr_) { } #endif // defined(BOOST_ASIO_HAS_MOVE) /// Assign from another address. - address_v4& operator=(const address_v4& other) + address_v4& operator=(const address_v4& other) BOOST_ASIO_NOEXCEPT { addr_ = other.addr_; return *this; @@ -95,7 +95,7 @@ public: #if defined(BOOST_ASIO_HAS_MOVE) /// Move-assign from another address. - address_v4& operator=(address_v4&& other) + address_v4& operator=(address_v4&& other) BOOST_ASIO_NOEXCEPT { addr_ = other.addr_; return *this; @@ -103,10 +103,10 @@ public: #endif // defined(BOOST_ASIO_HAS_MOVE) /// Get the address in bytes, in network byte order. - BOOST_ASIO_DECL bytes_type to_bytes() const; + BOOST_ASIO_DECL bytes_type to_bytes() const BOOST_ASIO_NOEXCEPT; /// Get the address as an unsigned integer in host byte order - BOOST_ASIO_DECL uint_type to_uint() const; + BOOST_ASIO_DECL uint_type to_uint() const BOOST_ASIO_NOEXCEPT; #if !defined(BOOST_ASIO_NO_DEPRECATED) /// Get the address as an unsigned long in host byte order @@ -141,10 +141,10 @@ public: #endif // !defined(BOOST_ASIO_NO_DEPRECATED) /// Determine whether the address is a loopback address. - BOOST_ASIO_DECL bool is_loopback() const; + BOOST_ASIO_DECL bool is_loopback() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is unspecified. - BOOST_ASIO_DECL bool is_unspecified() const; + BOOST_ASIO_DECL bool is_unspecified() const BOOST_ASIO_NOEXCEPT; #if !defined(BOOST_ASIO_NO_DEPRECATED) /// (Deprecated: Use network_v4 class.) Determine whether the address is a @@ -161,58 +161,64 @@ public: #endif // !defined(BOOST_ASIO_NO_DEPRECATED) /// Determine whether the address is a multicast address. - BOOST_ASIO_DECL bool is_multicast() const; + BOOST_ASIO_DECL bool is_multicast() const BOOST_ASIO_NOEXCEPT; /// Compare two addresses for equality. - friend bool operator==(const address_v4& a1, const address_v4& a2) + friend bool operator==(const address_v4& a1, + const address_v4& a2) BOOST_ASIO_NOEXCEPT { return a1.addr_.s_addr == a2.addr_.s_addr; } /// Compare two addresses for inequality. - friend bool operator!=(const address_v4& a1, const address_v4& a2) + friend bool operator!=(const address_v4& a1, + const address_v4& a2) BOOST_ASIO_NOEXCEPT { return a1.addr_.s_addr != a2.addr_.s_addr; } /// Compare addresses for ordering. - friend bool operator<(const address_v4& a1, const address_v4& a2) + friend bool operator<(const address_v4& a1, + const address_v4& a2) BOOST_ASIO_NOEXCEPT { return a1.to_uint() < a2.to_uint(); } /// Compare addresses for ordering. - friend bool operator>(const address_v4& a1, const address_v4& a2) + friend bool operator>(const address_v4& a1, + const address_v4& a2) BOOST_ASIO_NOEXCEPT { return a1.to_uint() > a2.to_uint(); } /// Compare addresses for ordering. - friend bool operator<=(const address_v4& a1, const address_v4& a2) + friend bool operator<=(const address_v4& a1, + const address_v4& a2) BOOST_ASIO_NOEXCEPT { return a1.to_uint() <= a2.to_uint(); } /// Compare addresses for ordering. - friend bool operator>=(const address_v4& a1, const address_v4& a2) + friend bool operator>=(const address_v4& a1, + const address_v4& a2) BOOST_ASIO_NOEXCEPT { return a1.to_uint() >= a2.to_uint(); } /// Obtain an address object that represents any address. - static address_v4 any() + static address_v4 any() BOOST_ASIO_NOEXCEPT { return address_v4(); } /// Obtain an address object that represents the loopback address. - static address_v4 loopback() + static address_v4 loopback() BOOST_ASIO_NOEXCEPT { return address_v4(0x7F000001); } /// Obtain an address object that represents the broadcast address. - static address_v4 broadcast() + static address_v4 broadcast() BOOST_ASIO_NOEXCEPT { return address_v4(0xFFFFFFFF); } @@ -262,8 +268,8 @@ BOOST_ASIO_DECL address_v4 make_address_v4(const char* str); /** * @relates address_v4 */ -BOOST_ASIO_DECL address_v4 make_address_v4( - const char* str, boost::system::error_code& ec); +BOOST_ASIO_DECL address_v4 make_address_v4(const char* str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; /// Create an IPv4 address from an IP address string in dotted decimal form. /** @@ -275,8 +281,8 @@ BOOST_ASIO_DECL address_v4 make_address_v4(const std::string& str); /** * @relates address_v4 */ -BOOST_ASIO_DECL address_v4 make_address_v4( - const std::string& str, boost::system::error_code& ec); +BOOST_ASIO_DECL address_v4 make_address_v4(const std::string& str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; #if defined(BOOST_ASIO_HAS_STRING_VIEW) \ || defined(GENERATING_DOCUMENTATION) @@ -291,8 +297,8 @@ BOOST_ASIO_DECL address_v4 make_address_v4(string_view str); /** * @relates address_v4 */ -BOOST_ASIO_DECL address_v4 make_address_v4( - string_view str, boost::system::error_code& ec); +BOOST_ASIO_DECL address_v4 make_address_v4(string_view str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; #endif // defined(BOOST_ASIO_HAS_STRING_VIEW) // || defined(GENERATING_DOCUMENTATION) diff --git a/boost/asio/ip/address_v4_iterator.hpp b/boost/asio/ip/address_v4_iterator.hpp index 3574cda1e9..5a52fe0e1a 100644 --- a/boost/asio/ip/address_v4_iterator.hpp +++ b/boost/asio/ip/address_v4_iterator.hpp @@ -2,7 +2,7 @@ // ip/address_v4_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/address_v4_range.hpp b/boost/asio/ip/address_v4_range.hpp index 261ead22ac..5e9c548bea 100644 --- a/boost/asio/ip/address_v4_range.hpp +++ b/boost/asio/ip/address_v4_range.hpp @@ -2,7 +2,7 @@ // ip/address_v4_range.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/address_v6.hpp b/boost/asio/ip/address_v6.hpp index 8c4ac0a732..62dff45c54 100644 --- a/boost/asio/ip/address_v6.hpp +++ b/boost/asio/ip/address_v6.hpp @@ -2,7 +2,7 @@ // ip/address_v6.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -60,33 +60,34 @@ public: #endif /// Default constructor. - BOOST_ASIO_DECL address_v6(); + BOOST_ASIO_DECL address_v6() BOOST_ASIO_NOEXCEPT; /// Construct an address from raw bytes and scope ID. BOOST_ASIO_DECL explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0); /// Copy constructor. - BOOST_ASIO_DECL address_v6(const address_v6& other); + BOOST_ASIO_DECL address_v6(const address_v6& other) BOOST_ASIO_NOEXCEPT; #if defined(BOOST_ASIO_HAS_MOVE) /// Move constructor. - BOOST_ASIO_DECL address_v6(address_v6&& other); + BOOST_ASIO_DECL address_v6(address_v6&& other) BOOST_ASIO_NOEXCEPT; #endif // defined(BOOST_ASIO_HAS_MOVE) /// Assign from another address. - BOOST_ASIO_DECL address_v6& operator=(const address_v6& other); + BOOST_ASIO_DECL address_v6& operator=( + const address_v6& other) BOOST_ASIO_NOEXCEPT; #if defined(BOOST_ASIO_HAS_MOVE) /// Move-assign from another address. - BOOST_ASIO_DECL address_v6& operator=(address_v6&& other); + BOOST_ASIO_DECL address_v6& operator=(address_v6&& other) BOOST_ASIO_NOEXCEPT; #endif // defined(BOOST_ASIO_HAS_MOVE) /// The scope ID of the address. /** * Returns the scope ID associated with the IPv6 address. */ - unsigned long scope_id() const + unsigned long scope_id() const BOOST_ASIO_NOEXCEPT { return scope_id_; } @@ -95,13 +96,13 @@ public: /** * Modifies the scope ID associated with the IPv6 address. */ - void scope_id(unsigned long id) + void scope_id(unsigned long id) BOOST_ASIO_NOEXCEPT { scope_id_ = id; } /// Get the address in bytes, in network byte order. - BOOST_ASIO_DECL bytes_type to_bytes() const; + BOOST_ASIO_DECL bytes_type to_bytes() const BOOST_ASIO_NOEXCEPT; /// Get the address as a string. BOOST_ASIO_DECL std::string to_string() const; @@ -134,19 +135,19 @@ public: #endif // !defined(BOOST_ASIO_NO_DEPRECATED) /// Determine whether the address is a loopback address. - BOOST_ASIO_DECL bool is_loopback() const; + BOOST_ASIO_DECL bool is_loopback() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is unspecified. - BOOST_ASIO_DECL bool is_unspecified() const; + BOOST_ASIO_DECL bool is_unspecified() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is link local. - BOOST_ASIO_DECL bool is_link_local() const; + BOOST_ASIO_DECL bool is_link_local() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is site local. - BOOST_ASIO_DECL bool is_site_local() const; + BOOST_ASIO_DECL bool is_site_local() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is a mapped IPv4 address. - BOOST_ASIO_DECL bool is_v4_mapped() const; + BOOST_ASIO_DECL bool is_v4_mapped() const BOOST_ASIO_NOEXCEPT; #if !defined(BOOST_ASIO_NO_DEPRECATED) /// (Deprecated: No replacement.) Determine whether the address is an @@ -155,63 +156,67 @@ public: #endif // !defined(BOOST_ASIO_NO_DEPRECATED) /// Determine whether the address is a multicast address. - BOOST_ASIO_DECL bool is_multicast() const; + BOOST_ASIO_DECL bool is_multicast() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is a global multicast address. - BOOST_ASIO_DECL bool is_multicast_global() const; + BOOST_ASIO_DECL bool is_multicast_global() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is a link-local multicast address. - BOOST_ASIO_DECL bool is_multicast_link_local() const; + BOOST_ASIO_DECL bool is_multicast_link_local() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is a node-local multicast address. - BOOST_ASIO_DECL bool is_multicast_node_local() const; + BOOST_ASIO_DECL bool is_multicast_node_local() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is a org-local multicast address. - BOOST_ASIO_DECL bool is_multicast_org_local() const; + BOOST_ASIO_DECL bool is_multicast_org_local() const BOOST_ASIO_NOEXCEPT; /// Determine whether the address is a site-local multicast address. - BOOST_ASIO_DECL bool is_multicast_site_local() const; + BOOST_ASIO_DECL bool is_multicast_site_local() const BOOST_ASIO_NOEXCEPT; /// Compare two addresses for equality. - BOOST_ASIO_DECL friend bool operator==( - const address_v6& a1, const address_v6& a2); + BOOST_ASIO_DECL friend bool operator==(const address_v6& a1, + const address_v6& a2) BOOST_ASIO_NOEXCEPT; /// Compare two addresses for inequality. - friend bool operator!=(const address_v6& a1, const address_v6& a2) + friend bool operator!=(const address_v6& a1, + const address_v6& a2) BOOST_ASIO_NOEXCEPT { return !(a1 == a2); } /// Compare addresses for ordering. - BOOST_ASIO_DECL friend bool operator<( - const address_v6& a1, const address_v6& a2); + BOOST_ASIO_DECL friend bool operator<(const address_v6& a1, + const address_v6& a2) BOOST_ASIO_NOEXCEPT; /// Compare addresses for ordering. - friend bool operator>(const address_v6& a1, const address_v6& a2) + friend bool operator>(const address_v6& a1, + const address_v6& a2) BOOST_ASIO_NOEXCEPT { return a2 < a1; } /// Compare addresses for ordering. - friend bool operator<=(const address_v6& a1, const address_v6& a2) + friend bool operator<=(const address_v6& a1, + const address_v6& a2) BOOST_ASIO_NOEXCEPT { return !(a2 < a1); } /// Compare addresses for ordering. - friend bool operator>=(const address_v6& a1, const address_v6& a2) + friend bool operator>=(const address_v6& a1, + const address_v6& a2) BOOST_ASIO_NOEXCEPT { return !(a1 < a2); } /// Obtain an address object that represents any address. - static address_v6 any() + static address_v6 any() BOOST_ASIO_NOEXCEPT { return address_v6(); } /// Obtain an address object that represents the loopback address. - BOOST_ASIO_DECL static address_v6 loopback(); + BOOST_ASIO_DECL static address_v6 loopback() BOOST_ASIO_NOEXCEPT; #if !defined(BOOST_ASIO_NO_DEPRECATED) /// (Deprecated: Use make_address_v6().) Create an IPv4-mapped IPv6 address. @@ -251,8 +256,8 @@ BOOST_ASIO_DECL address_v6 make_address_v6(const char* str); /** * @relates address_v6 */ -BOOST_ASIO_DECL address_v6 make_address_v6( - const char* str, boost::system::error_code& ec); +BOOST_ASIO_DECL address_v6 make_address_v6(const char* str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; /// Createan IPv6 address from an IP address string. /** @@ -264,8 +269,8 @@ BOOST_ASIO_DECL address_v6 make_address_v6(const std::string& str); /** * @relates address_v6 */ -BOOST_ASIO_DECL address_v6 make_address_v6( - const std::string& str, boost::system::error_code& ec); +BOOST_ASIO_DECL address_v6 make_address_v6(const std::string& str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; #if defined(BOOST_ASIO_HAS_STRING_VIEW) \ || defined(GENERATING_DOCUMENTATION) @@ -280,8 +285,8 @@ BOOST_ASIO_DECL address_v6 make_address_v6(string_view str); /** * @relates address_v6 */ -BOOST_ASIO_DECL address_v6 make_address_v6( - string_view str, boost::system::error_code& ec); +BOOST_ASIO_DECL address_v6 make_address_v6(string_view str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT; #endif // defined(BOOST_ASIO_HAS_STRING_VIEW) // || defined(GENERATING_DOCUMENTATION) diff --git a/boost/asio/ip/address_v6_iterator.hpp b/boost/asio/ip/address_v6_iterator.hpp index 887b09f79a..4598a872b2 100644 --- a/boost/asio/ip/address_v6_iterator.hpp +++ b/boost/asio/ip/address_v6_iterator.hpp @@ -2,7 +2,7 @@ // ip/address_v6_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/ip/address_v6_range.hpp b/boost/asio/ip/address_v6_range.hpp index 0a095cd80b..9189fde3c9 100644 --- a/boost/asio/ip/address_v6_range.hpp +++ b/boost/asio/ip/address_v6_range.hpp @@ -2,7 +2,7 @@ // ip/address_v6_range.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/ip/bad_address_cast.hpp b/boost/asio/ip/bad_address_cast.hpp index fce9f053b1..da06983301 100644 --- a/boost/asio/ip/bad_address_cast.hpp +++ b/boost/asio/ip/bad_address_cast.hpp @@ -2,7 +2,7 @@ // ip/bad_address_cast.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/basic_endpoint.hpp b/boost/asio/ip/basic_endpoint.hpp index bad4114f0b..0951fd70d3 100644 --- a/boost/asio/ip/basic_endpoint.hpp +++ b/boost/asio/ip/basic_endpoint.hpp @@ -2,7 +2,7 @@ // ip/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -57,7 +57,7 @@ public: #endif /// Default constructor. - basic_endpoint() + basic_endpoint() BOOST_ASIO_NOEXCEPT : impl_() { } @@ -79,7 +79,7 @@ public: * @endcode */ basic_endpoint(const InternetProtocol& internet_protocol, - unsigned short port_num) + unsigned short port_num) BOOST_ASIO_NOEXCEPT : impl_(internet_protocol.family(), port_num) { } @@ -87,27 +87,28 @@ public: /// Construct an endpoint using a port number and an IP address. This /// constructor may be used for accepting connections on a specific interface /// or for making a connection to a remote endpoint. - basic_endpoint(const boost::asio::ip::address& addr, unsigned short port_num) + basic_endpoint(const boost::asio::ip::address& addr, + unsigned short port_num) BOOST_ASIO_NOEXCEPT : impl_(addr, port_num) { } /// Copy constructor. - basic_endpoint(const basic_endpoint& other) + basic_endpoint(const basic_endpoint& other) BOOST_ASIO_NOEXCEPT : impl_(other.impl_) { } #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. - basic_endpoint(basic_endpoint&& other) + basic_endpoint(basic_endpoint&& other) BOOST_ASIO_NOEXCEPT : impl_(other.impl_) { } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Assign from another endpoint. - basic_endpoint& operator=(const basic_endpoint& other) + basic_endpoint& operator=(const basic_endpoint& other) BOOST_ASIO_NOEXCEPT { impl_ = other.impl_; return *this; @@ -115,7 +116,7 @@ public: #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-assign from another endpoint. - basic_endpoint& operator=(basic_endpoint&& other) + basic_endpoint& operator=(basic_endpoint&& other) BOOST_ASIO_NOEXCEPT { impl_ = other.impl_; return *this; @@ -123,7 +124,7 @@ public: #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// The protocol associated with the endpoint. - protocol_type protocol() const + protocol_type protocol() const BOOST_ASIO_NOEXCEPT { if (impl_.is_v4()) return InternetProtocol::v4(); @@ -131,19 +132,19 @@ public: } /// Get the underlying endpoint in the native type. - data_type* data() + data_type* data() BOOST_ASIO_NOEXCEPT { return impl_.data(); } /// Get the underlying endpoint in the native type. - const data_type* data() const + const data_type* data() const BOOST_ASIO_NOEXCEPT { return impl_.data(); } /// Get the underlying size of the endpoint in the native type. - std::size_t size() const + std::size_t size() const BOOST_ASIO_NOEXCEPT { return impl_.size(); } @@ -155,75 +156,75 @@ public: } /// Get the capacity of the endpoint in the native type. - std::size_t capacity() const + std::size_t capacity() const BOOST_ASIO_NOEXCEPT { return impl_.capacity(); } /// Get the port associated with the endpoint. The port number is always in /// the host's byte order. - unsigned short port() const + unsigned short port() const BOOST_ASIO_NOEXCEPT { return impl_.port(); } /// Set the port associated with the endpoint. The port number is always in /// the host's byte order. - void port(unsigned short port_num) + void port(unsigned short port_num) BOOST_ASIO_NOEXCEPT { impl_.port(port_num); } /// Get the IP address associated with the endpoint. - boost::asio::ip::address address() const + boost::asio::ip::address address() const BOOST_ASIO_NOEXCEPT { return impl_.address(); } /// Set the IP address associated with the endpoint. - void address(const boost::asio::ip::address& addr) + void address(const boost::asio::ip::address& addr) BOOST_ASIO_NOEXCEPT { impl_.address(addr); } /// Compare two endpoints for equality. friend bool operator==(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) + const basic_endpoint<InternetProtocol>& e2) BOOST_ASIO_NOEXCEPT { return e1.impl_ == e2.impl_; } /// Compare two endpoints for inequality. friend bool operator!=(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) + const basic_endpoint<InternetProtocol>& e2) BOOST_ASIO_NOEXCEPT { return !(e1 == e2); } /// Compare endpoints for ordering. friend bool operator<(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) + const basic_endpoint<InternetProtocol>& e2) BOOST_ASIO_NOEXCEPT { return e1.impl_ < e2.impl_; } /// Compare endpoints for ordering. friend bool operator>(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) + const basic_endpoint<InternetProtocol>& e2) BOOST_ASIO_NOEXCEPT { return e2.impl_ < e1.impl_; } /// Compare endpoints for ordering. friend bool operator<=(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) + const basic_endpoint<InternetProtocol>& e2) BOOST_ASIO_NOEXCEPT { return !(e2 < e1); } /// Compare endpoints for ordering. friend bool operator>=(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) + const basic_endpoint<InternetProtocol>& e2) BOOST_ASIO_NOEXCEPT { return !(e1 < e2); } diff --git a/boost/asio/ip/basic_resolver.hpp b/boost/asio/ip/basic_resolver.hpp index 4979d104cf..b937ce5c10 100644 --- a/boost/asio/ip/basic_resolver.hpp +++ b/boost/asio/ip/basic_resolver.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -18,41 +18,43 @@ #include <boost/asio/detail/config.hpp> #include <string> #include <boost/asio/async_result.hpp> -#include <boost/asio/basic_io_object.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/string_view.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> #include <boost/asio/ip/basic_resolver_iterator.hpp> #include <boost/asio/ip/basic_resolver_query.hpp> #include <boost/asio/ip/basic_resolver_results.hpp> #include <boost/asio/ip/resolver_base.hpp> +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include <boost/asio/detail/winrt_resolver_service.hpp> +#else +# include <boost/asio/detail/resolver_service.hpp> +#endif #if defined(BOOST_ASIO_HAS_MOVE) # include <utility> #endif // defined(BOOST_ASIO_HAS_MOVE) -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/ip/resolver_service.hpp> -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/winrt_resolver_service.hpp> -# define BOOST_ASIO_SVC_T \ - boost::asio::detail::winrt_resolver_service<InternetProtocol> -# else -# include <boost/asio/detail/resolver_service.hpp> -# define BOOST_ASIO_SVC_T \ - boost::asio::detail::resolver_service<InternetProtocol> -# endif -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { namespace ip { +#if !defined(BOOST_ASIO_IP_BASIC_RESOLVER_FWD_DECL) +#define BOOST_ASIO_IP_BASIC_RESOLVER_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename InternetProtocol, typename Executor = executor> +class basic_resolver; + +#endif // !defined(BOOST_ASIO_IP_BASIC_RESOLVER_FWD_DECL) + /// Provides endpoint resolution functionality. /** * The basic_resolver class template provides the ability to resolve a query @@ -62,15 +64,13 @@ namespace ip { * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename InternetProtocol - BOOST_ASIO_SVC_TPARAM_DEF1(= resolver_service<InternetProtocol>)> +template <typename InternetProtocol, typename Executor> class basic_resolver - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>, - public resolver_base + : public resolver_base { public: /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; + typedef Executor executor_type; /// The protocol type. typedef InternetProtocol protocol_type; @@ -89,16 +89,33 @@ public: /// The results type. typedef basic_resolver_results<InternetProtocol> results_type; - /// Constructor. + /// Construct with executor. /** * This constructor creates a basic_resolver. * - * @param io_context The io_context object that the resolver will use to + * @param ex The I/O executor that the resolver will use, by default, to * dispatch handlers for any asynchronous operations performed on the * resolver. */ - explicit basic_resolver(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) + explicit basic_resolver(const executor_type& ex) + : impl_(ex) + { + } + + /// Construct with execution context. + /** + * This constructor creates a basic_resolver. + * + * @param context An execution context which provides the I/O executor that + * the resolver will use, by default, to dispatch handlers for any + * asynchronous operations performed on the resolver. + */ + template <typename ExecutionContext> + explicit basic_resolver(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { } @@ -111,10 +128,10 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_resolver(io_context&) constructor. + * constructed using the @c basic_resolver(const executor_type&) constructor. */ basic_resolver(basic_resolver&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) + : impl_(std::move(other.impl_)) { } @@ -128,11 +145,11 @@ public: * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_resolver(io_context&) constructor. + * constructed using the @c basic_resolver(const executor_type&) constructor. */ basic_resolver& operator=(basic_resolver&& other) { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); + impl_ = std::move(other.impl_); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -147,45 +164,11 @@ public: { } -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - // These functions are provided by basic_io_object<>. -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Get the executor associated with the object. executor_type get_executor() BOOST_ASIO_NOEXCEPT { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); + return impl_.get_executor(); } -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) /// Cancel any asynchronous operations that are waiting on the resolver. /** @@ -195,7 +178,7 @@ public: */ void cancel() { - return this->get_service().cancel(this->get_implementation()); + return impl_.get_service().cancel(impl_.get_implementation()); } #if !defined(BOOST_ASIO_NO_DEPRECATED) @@ -215,8 +198,8 @@ public: results_type resolve(const query& q) { boost::system::error_code ec; - results_type r = this->get_service().resolve( - this->get_implementation(), q, ec); + results_type r = impl_.get_service().resolve( + impl_.get_implementation(), q, ec); boost::asio::detail::throw_error(ec, "resolve"); return r; } @@ -236,7 +219,7 @@ public: */ results_type resolve(const query& q, boost::system::error_code& ec) { - return this->get_service().resolve(this->get_implementation(), q, ec); + return impl_.get_service().resolve(impl_.get_implementation(), q, ec); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -336,7 +319,8 @@ public: * * @param resolve_flags A set of flags that determine how name resolution * should be performed. The default flags are suitable for communication with - * remote hosts. + * remote hosts. See the @ref resolver_base documentation for the set of + * available flags. * * @returns A range object representing the list of endpoint entries. A * successful call to this function is guaranteed to return a non-empty @@ -361,8 +345,8 @@ public: boost::system::error_code ec; basic_resolver_query<protocol_type> q(static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); - results_type r = this->get_service().resolve( - this->get_implementation(), q, ec); + results_type r = impl_.get_service().resolve( + impl_.get_implementation(), q, ec); boost::asio::detail::throw_error(ec, "resolve"); return r; } @@ -385,7 +369,8 @@ public: * * @param resolve_flags A set of flags that determine how name resolution * should be performed. The default flags are suitable for communication with - * remote hosts. + * remote hosts. See the @ref resolver_base documentation for the set of + * available flags. * * @param ec Set to indicate what error occurred, if any. * @@ -410,7 +395,7 @@ public: { basic_resolver_query<protocol_type> q(static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); - return this->get_service().resolve(this->get_implementation(), q, ec); + return impl_.get_service().resolve(impl_.get_implementation(), q, ec); } /// Perform forward resolution of a query to a list of entries. @@ -519,7 +504,8 @@ public: * * @param resolve_flags A set of flags that determine how name resolution * should be performed. The default flags are suitable for communication with - * remote hosts. + * remote hosts. See the @ref resolver_base documentation for the set of + * available flags. * * @returns A range object representing the list of endpoint entries. A * successful call to this function is guaranteed to return a non-empty @@ -546,8 +532,8 @@ public: basic_resolver_query<protocol_type> q( protocol, static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); - results_type r = this->get_service().resolve( - this->get_implementation(), q, ec); + results_type r = impl_.get_service().resolve( + impl_.get_implementation(), q, ec); boost::asio::detail::throw_error(ec, "resolve"); return r; } @@ -573,7 +559,8 @@ public: * * @param resolve_flags A set of flags that determine how name resolution * should be performed. The default flags are suitable for communication with - * remote hosts. + * remote hosts. See the @ref resolver_base documentation for the set of + * available flags. * * @param ec Set to indicate what error occurred, if any. * @@ -599,7 +586,7 @@ public: basic_resolver_query<protocol_type> q( protocol, static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); - return this->get_service().resolve(this->get_implementation(), q, ec); + return impl_.get_service().resolve(impl_.get_implementation(), q, ec); } #if !defined(BOOST_ASIO_NO_DEPRECATED) @@ -619,9 +606,9 @@ public: * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. @@ -632,23 +619,9 @@ public: async_resolve(const query& q, BOOST_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. - BOOST_ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, results_type) type_check; - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_resolve(this->get_implementation(), q, - BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - boost::asio::async_completion<ResolveHandler, - void (boost::system::error_code, results_type)> init(handler); - - this->get_service().async_resolve( - this->get_implementation(), q, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return boost::asio::async_initiate<ResolveHandler, + void (boost::system::error_code, results_type)>( + initiate_async_resolve(), handler, this, q); } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) @@ -676,9 +649,9 @@ public: * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. @@ -723,7 +696,8 @@ public: * * @param resolve_flags A set of flags that determine how name resolution * should be performed. The default flags are suitable for communication with - * remote hosts. + * remote hosts. See the @ref resolver_base documentation for the set of + * available flags. * * @param handler The handler to be called when the resolve operation * completes. Copies will be made of the handler as required. The function @@ -733,9 +707,9 @@ public: * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. @@ -759,26 +733,12 @@ public: resolver_base::flags resolve_flags, BOOST_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. - BOOST_ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, results_type) type_check; - basic_resolver_query<protocol_type> q(static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_resolve(this->get_implementation(), q, - BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - boost::asio::async_completion<ResolveHandler, - void (boost::system::error_code, results_type)> init(handler); - - this->get_service().async_resolve( - this->get_implementation(), q, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return boost::asio::async_initiate<ResolveHandler, + void (boost::system::error_code, results_type)>( + initiate_async_resolve(), handler, this, q); } /// Asynchronously perform forward resolution of a query to a list of entries. @@ -808,9 +768,9 @@ public: * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. @@ -858,7 +818,8 @@ public: * * @param resolve_flags A set of flags that determine how name resolution * should be performed. The default flags are suitable for communication with - * remote hosts. + * remote hosts. See the @ref resolver_base documentation for the set of + * available flags. * * @param handler The handler to be called when the resolve operation * completes. Copies will be made of the handler as required. The function @@ -868,9 +829,9 @@ public: * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. @@ -894,27 +855,13 @@ public: resolver_base::flags resolve_flags, BOOST_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. - BOOST_ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, results_type) type_check; - basic_resolver_query<protocol_type> q( protocol, static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_resolve(this->get_implementation(), q, - BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - boost::asio::async_completion<ResolveHandler, - void (boost::system::error_code, results_type)> init(handler); - - this->get_service().async_resolve( - this->get_implementation(), q, init.completion_handler); - - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + return boost::asio::async_initiate<ResolveHandler, + void (boost::system::error_code, results_type)>( + initiate_async_resolve(), handler, this, q); } /// Perform reverse resolution of an endpoint to a list of entries. @@ -934,8 +881,8 @@ public: results_type resolve(const endpoint_type& e) { boost::system::error_code ec; - results_type i = this->get_service().resolve( - this->get_implementation(), e, ec); + results_type i = impl_.get_service().resolve( + impl_.get_implementation(), e, ec); boost::asio::detail::throw_error(ec, "resolve"); return i; } @@ -956,7 +903,7 @@ public: */ results_type resolve(const endpoint_type& e, boost::system::error_code& ec) { - return this->get_service().resolve(this->get_implementation(), e, ec); + return impl_.get_service().resolve(impl_.get_implementation(), e, ec); } /// Asynchronously perform reverse resolution of an endpoint to a list of @@ -976,9 +923,9 @@ public: * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. @@ -989,24 +936,43 @@ public: async_resolve(const endpoint_type& e, BOOST_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. - BOOST_ASIO_RESOLVE_HANDLER_CHECK( - ResolveHandler, handler, results_type) type_check; + return boost::asio::async_initiate<ResolveHandler, + void (boost::system::error_code, results_type)>( + initiate_async_resolve(), handler, this, e); + } -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_resolve(this->get_implementation(), e, - BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler)); -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - boost::asio::async_completion<ResolveHandler, - void (boost::system::error_code, results_type)> init(handler); +private: + // Disallow copying and assignment. + basic_resolver(const basic_resolver&) BOOST_ASIO_DELETED; + basic_resolver& operator=(const basic_resolver&) BOOST_ASIO_DELETED; - this->get_service().async_resolve( - this->get_implementation(), e, init.completion_handler); + struct initiate_async_resolve + { + template <typename ResolveHandler, typename Query> + void operator()(BOOST_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. + BOOST_ASIO_RESOLVE_HANDLER_CHECK( + ResolveHandler, handler, results_type) type_check; + + boost::asio::detail::non_const_lvalue<ResolveHandler> handler2(handler); + self->impl_.get_service().async_resolve( + self->impl_.get_implementation(), q, handler2.value, + self->impl_.get_implementation_executor()); + } + }; - return init.result.get(); -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - } +# if defined(BOOST_ASIO_WINDOWS_RUNTIME) + boost::asio::detail::io_object_impl< + boost::asio::detail::winrt_resolver_service<InternetProtocol>, + Executor> impl_; +# else + boost::asio::detail::io_object_impl< + boost::asio::detail::resolver_service<InternetProtocol>, + Executor> impl_; +# endif }; } // namespace ip @@ -1015,8 +981,4 @@ public: #include <boost/asio/detail/pop_options.hpp> -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# undef BOOST_ASIO_SVC_T -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_IP_BASIC_RESOLVER_HPP diff --git a/boost/asio/ip/basic_resolver_entry.hpp b/boost/asio/ip/basic_resolver_entry.hpp index efaf976577..c00f17a2aa 100644 --- a/boost/asio/ip/basic_resolver_entry.hpp +++ b/boost/asio/ip/basic_resolver_entry.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver_entry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/basic_resolver_iterator.hpp b/boost/asio/ip/basic_resolver_iterator.hpp index dd93b84149..5564a78d6f 100644 --- a/boost/asio/ip/basic_resolver_iterator.hpp +++ b/boost/asio/ip/basic_resolver_iterator.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/basic_resolver_query.hpp b/boost/asio/ip/basic_resolver_query.hpp index cbbae25ae7..e01597ebee 100644 --- a/boost/asio/ip/basic_resolver_query.hpp +++ b/boost/asio/ip/basic_resolver_query.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver_query.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/basic_resolver_results.hpp b/boost/asio/ip/basic_resolver_results.hpp index f553930cfc..64d1937c17 100644 --- a/boost/asio/ip/basic_resolver_results.hpp +++ b/boost/asio/ip/basic_resolver_results.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver_results.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/detail/endpoint.hpp b/boost/asio/ip/detail/endpoint.hpp index a6f04abed9..690e6b1703 100644 --- a/boost/asio/ip/detail/endpoint.hpp +++ b/boost/asio/ip/detail/endpoint.hpp @@ -2,7 +2,7 @@ // ip/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -34,42 +34,43 @@ class endpoint { public: // Default constructor. - BOOST_ASIO_DECL endpoint(); + BOOST_ASIO_DECL endpoint() BOOST_ASIO_NOEXCEPT; // Construct an endpoint using a family and port number. - BOOST_ASIO_DECL endpoint(int family, unsigned short port_num); + BOOST_ASIO_DECL endpoint(int family, + unsigned short port_num) BOOST_ASIO_NOEXCEPT; // Construct an endpoint using an address and port number. BOOST_ASIO_DECL endpoint(const boost::asio::ip::address& addr, - unsigned short port_num); + unsigned short port_num) BOOST_ASIO_NOEXCEPT; // Copy constructor. - endpoint(const endpoint& other) + endpoint(const endpoint& other) BOOST_ASIO_NOEXCEPT : data_(other.data_) { } // Assign from another endpoint. - endpoint& operator=(const endpoint& other) + endpoint& operator=(const endpoint& other) BOOST_ASIO_NOEXCEPT { data_ = other.data_; return *this; } // Get the underlying endpoint in the native type. - boost::asio::detail::socket_addr_type* data() + boost::asio::detail::socket_addr_type* data() BOOST_ASIO_NOEXCEPT { return &data_.base; } // Get the underlying endpoint in the native type. - const boost::asio::detail::socket_addr_type* data() const + const boost::asio::detail::socket_addr_type* data() const BOOST_ASIO_NOEXCEPT { return &data_.base; } // Get the underlying size of the endpoint in the native type. - std::size_t size() const + std::size_t size() const BOOST_ASIO_NOEXCEPT { if (is_v4()) return sizeof(boost::asio::detail::sockaddr_in4_type); @@ -81,33 +82,34 @@ public: BOOST_ASIO_DECL void resize(std::size_t new_size); // Get the capacity of the endpoint in the native type. - std::size_t capacity() const + std::size_t capacity() const BOOST_ASIO_NOEXCEPT { return sizeof(data_); } // Get the port associated with the endpoint. - BOOST_ASIO_DECL unsigned short port() const; + BOOST_ASIO_DECL unsigned short port() const BOOST_ASIO_NOEXCEPT; // Set the port associated with the endpoint. - BOOST_ASIO_DECL void port(unsigned short port_num); + BOOST_ASIO_DECL void port(unsigned short port_num) BOOST_ASIO_NOEXCEPT; // Get the IP address associated with the endpoint. - BOOST_ASIO_DECL boost::asio::ip::address address() const; + BOOST_ASIO_DECL boost::asio::ip::address address() const BOOST_ASIO_NOEXCEPT; // Set the IP address associated with the endpoint. - BOOST_ASIO_DECL void address(const boost::asio::ip::address& addr); + BOOST_ASIO_DECL void address( + const boost::asio::ip::address& addr) BOOST_ASIO_NOEXCEPT; // Compare two endpoints for equality. - BOOST_ASIO_DECL friend bool operator==( - const endpoint& e1, const endpoint& e2); + BOOST_ASIO_DECL friend bool operator==(const endpoint& e1, + const endpoint& e2) BOOST_ASIO_NOEXCEPT; // Compare endpoints for ordering. - BOOST_ASIO_DECL friend bool operator<( - const endpoint& e1, const endpoint& e2); + BOOST_ASIO_DECL friend bool operator<(const endpoint& e1, + const endpoint& e2) BOOST_ASIO_NOEXCEPT; // Determine whether the endpoint is IPv4. - bool is_v4() const + bool is_v4() const BOOST_ASIO_NOEXCEPT { return data_.base.sa_family == BOOST_ASIO_OS_DEF(AF_INET); } diff --git a/boost/asio/ip/detail/impl/endpoint.ipp b/boost/asio/ip/detail/impl/endpoint.ipp index 49f5af116f..9297429999 100644 --- a/boost/asio/ip/detail/impl/endpoint.ipp +++ b/boost/asio/ip/detail/impl/endpoint.ipp @@ -2,7 +2,7 @@ // ip/detail/impl/endpoint.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -32,7 +32,7 @@ namespace asio { namespace ip { namespace detail { -endpoint::endpoint() +endpoint::endpoint() BOOST_ASIO_NOEXCEPT : data_() { data_.v4.sin_family = BOOST_ASIO_OS_DEF(AF_INET); @@ -40,7 +40,7 @@ endpoint::endpoint() data_.v4.sin_addr.s_addr = BOOST_ASIO_OS_DEF(INADDR_ANY); } -endpoint::endpoint(int family, unsigned short port_num) +endpoint::endpoint(int family, unsigned short port_num) BOOST_ASIO_NOEXCEPT : data_() { using namespace std; // For memcpy. @@ -70,7 +70,7 @@ endpoint::endpoint(int family, unsigned short port_num) } endpoint::endpoint(const boost::asio::ip::address& addr, - unsigned short port_num) + unsigned short port_num) BOOST_ASIO_NOEXCEPT : data_() { using namespace std; // For memcpy. @@ -107,7 +107,7 @@ void endpoint::resize(std::size_t new_size) } } -unsigned short endpoint::port() const +unsigned short endpoint::port() const BOOST_ASIO_NOEXCEPT { if (is_v4()) { @@ -121,7 +121,7 @@ unsigned short endpoint::port() const } } -void endpoint::port(unsigned short port_num) +void endpoint::port(unsigned short port_num) BOOST_ASIO_NOEXCEPT { if (is_v4()) { @@ -135,7 +135,7 @@ void endpoint::port(unsigned short port_num) } } -boost::asio::ip::address endpoint::address() const +boost::asio::ip::address endpoint::address() const BOOST_ASIO_NOEXCEPT { using namespace std; // For memcpy. if (is_v4()) @@ -156,18 +156,18 @@ boost::asio::ip::address endpoint::address() const } } -void endpoint::address(const boost::asio::ip::address& addr) +void endpoint::address(const boost::asio::ip::address& addr) BOOST_ASIO_NOEXCEPT { endpoint tmp_endpoint(addr, port()); data_ = tmp_endpoint.data_; } -bool operator==(const endpoint& e1, const endpoint& e2) +bool operator==(const endpoint& e1, const endpoint& e2) BOOST_ASIO_NOEXCEPT { return e1.address() == e2.address() && e1.port() == e2.port(); } -bool operator<(const endpoint& e1, const endpoint& e2) +bool operator<(const endpoint& e1, const endpoint& e2) BOOST_ASIO_NOEXCEPT { if (e1.address() < e2.address()) return true; diff --git a/boost/asio/ip/detail/socket_option.hpp b/boost/asio/ip/detail/socket_option.hpp index ec3ca7e970..7f8b3f586f 100644 --- a/boost/asio/ip/detail/socket_option.hpp +++ b/boost/asio/ip/detail/socket_option.hpp @@ -2,7 +2,7 @@ // detail/socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/host_name.hpp b/boost/asio/ip/host_name.hpp index c1e4e0cf8b..bb893ef24b 100644 --- a/boost/asio/ip/host_name.hpp +++ b/boost/asio/ip/host_name.hpp @@ -2,7 +2,7 @@ // ip/host_name.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/icmp.hpp b/boost/asio/ip/icmp.hpp index 4b9d642048..229529f770 100644 --- a/boost/asio/ip/icmp.hpp +++ b/boost/asio/ip/icmp.hpp @@ -2,7 +2,7 @@ // ip/icmp.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/impl/address.hpp b/boost/asio/ip/impl/address.hpp index cf5afb4fcf..63f6b2e0ac 100644 --- a/boost/asio/ip/impl/address.hpp +++ b/boost/asio/ip/impl/address.hpp @@ -2,7 +2,7 @@ // ip/impl/address.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/impl/address.ipp b/boost/asio/ip/impl/address.ipp index 9afa566a35..2dc55290b0 100644 --- a/boost/asio/ip/impl/address.ipp +++ b/boost/asio/ip/impl/address.ipp @@ -2,7 +2,7 @@ // ip/impl/address.ipp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -30,28 +30,30 @@ namespace boost { namespace asio { namespace ip { -address::address() +address::address() BOOST_ASIO_NOEXCEPT : type_(ipv4), ipv4_address_(), ipv6_address_() { } -address::address(const boost::asio::ip::address_v4& ipv4_address) +address::address( + const boost::asio::ip::address_v4& ipv4_address) BOOST_ASIO_NOEXCEPT : type_(ipv4), ipv4_address_(ipv4_address), ipv6_address_() { } -address::address(const boost::asio::ip::address_v6& ipv6_address) +address::address( + const boost::asio::ip::address_v6& ipv6_address) BOOST_ASIO_NOEXCEPT : type_(ipv6), ipv4_address_(), ipv6_address_(ipv6_address) { } -address::address(const address& other) +address::address(const address& other) BOOST_ASIO_NOEXCEPT : type_(other.type_), ipv4_address_(other.ipv4_address_), ipv6_address_(other.ipv6_address_) @@ -59,7 +61,7 @@ address::address(const address& other) } #if defined(BOOST_ASIO_HAS_MOVE) -address::address(address&& other) +address::address(address&& other) BOOST_ASIO_NOEXCEPT : type_(other.type_), ipv4_address_(other.ipv4_address_), ipv6_address_(other.ipv6_address_) @@ -67,7 +69,7 @@ address::address(address&& other) } #endif // defined(BOOST_ASIO_HAS_MOVE) -address& address::operator=(const address& other) +address& address::operator=(const address& other) BOOST_ASIO_NOEXCEPT { type_ = other.type_; ipv4_address_ = other.ipv4_address_; @@ -76,7 +78,7 @@ address& address::operator=(const address& other) } #if defined(BOOST_ASIO_HAS_MOVE) -address& address::operator=(address&& other) +address& address::operator=(address&& other) BOOST_ASIO_NOEXCEPT { type_ = other.type_; ipv4_address_ = other.ipv4_address_; @@ -85,7 +87,8 @@ address& address::operator=(address&& other) } #endif // defined(BOOST_ASIO_HAS_MOVE) -address& address::operator=(const boost::asio::ip::address_v4& ipv4_address) +address& address::operator=( + const boost::asio::ip::address_v4& ipv4_address) BOOST_ASIO_NOEXCEPT { type_ = ipv4; ipv4_address_ = ipv4_address; @@ -93,7 +96,8 @@ address& address::operator=(const boost::asio::ip::address_v4& ipv4_address) return *this; } -address& address::operator=(const boost::asio::ip::address_v6& ipv6_address) +address& address::operator=( + const boost::asio::ip::address_v6& ipv6_address) BOOST_ASIO_NOEXCEPT { type_ = ipv6; ipv4_address_ = boost::asio::ip::address_v4(); @@ -109,7 +113,8 @@ address make_address(const char* str) return addr; } -address make_address(const char* str, boost::system::error_code& ec) +address make_address(const char* str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { boost::asio::ip::address_v6 ipv6_address = boost::asio::ip::make_address_v6(str, ec); @@ -130,7 +135,7 @@ address make_address(const std::string& str) } address make_address(const std::string& str, - boost::system::error_code& ec) + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { return make_address(str.c_str(), ec); } @@ -143,7 +148,7 @@ address make_address(string_view str) } address make_address(string_view str, - boost::system::error_code& ec) + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { return make_address(static_cast<std::string>(str), ec); } @@ -186,28 +191,28 @@ std::string address::to_string(boost::system::error_code& ec) const } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -bool address::is_loopback() const +bool address::is_loopback() const BOOST_ASIO_NOEXCEPT { return (type_ == ipv4) ? ipv4_address_.is_loopback() : ipv6_address_.is_loopback(); } -bool address::is_unspecified() const +bool address::is_unspecified() const BOOST_ASIO_NOEXCEPT { return (type_ == ipv4) ? ipv4_address_.is_unspecified() : ipv6_address_.is_unspecified(); } -bool address::is_multicast() const +bool address::is_multicast() const BOOST_ASIO_NOEXCEPT { return (type_ == ipv4) ? ipv4_address_.is_multicast() : ipv6_address_.is_multicast(); } -bool operator==(const address& a1, const address& a2) +bool operator==(const address& a1, const address& a2) BOOST_ASIO_NOEXCEPT { if (a1.type_ != a2.type_) return false; @@ -216,7 +221,7 @@ bool operator==(const address& a1, const address& a2) return a1.ipv4_address_ == a2.ipv4_address_; } -bool operator<(const address& a1, const address& a2) +bool operator<(const address& a1, const address& a2) BOOST_ASIO_NOEXCEPT { if (a1.type_ < a2.type_) return true; diff --git a/boost/asio/ip/impl/address_v4.hpp b/boost/asio/ip/impl/address_v4.hpp index 838dc613e2..98bd89d89f 100644 --- a/boost/asio/ip/impl/address_v4.hpp +++ b/boost/asio/ip/impl/address_v4.hpp @@ -2,7 +2,7 @@ // ip/impl/address_v4.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/impl/address_v4.ipp b/boost/asio/ip/impl/address_v4.ipp index 7693deaf40..c572100a8b 100644 --- a/boost/asio/ip/impl/address_v4.ipp +++ b/boost/asio/ip/impl/address_v4.ipp @@ -2,7 +2,7 @@ // ip/impl/address_v4.ipp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -58,7 +58,7 @@ address_v4::address_v4(address_v4::uint_type addr) static_cast<boost::asio::detail::u_long_type>(addr)); } -address_v4::bytes_type address_v4::to_bytes() const +address_v4::bytes_type address_v4::to_bytes() const BOOST_ASIO_NOEXCEPT { using namespace std; // For memcpy. bytes_type bytes; @@ -70,7 +70,7 @@ address_v4::bytes_type address_v4::to_bytes() const return bytes; } -address_v4::uint_type address_v4::to_uint() const +address_v4::uint_type address_v4::to_uint() const BOOST_ASIO_NOEXCEPT { return boost::asio::detail::socket_ops::network_to_host_long(addr_.s_addr); } @@ -109,12 +109,12 @@ std::string address_v4::to_string(boost::system::error_code& ec) const } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -bool address_v4::is_loopback() const +bool address_v4::is_loopback() const BOOST_ASIO_NOEXCEPT { return (to_uint() & 0xFF000000) == 0x7F000000; } -bool address_v4::is_unspecified() const +bool address_v4::is_unspecified() const BOOST_ASIO_NOEXCEPT { return to_uint() == 0; } @@ -136,7 +136,7 @@ bool address_v4::is_class_c() const } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -bool address_v4::is_multicast() const +bool address_v4::is_multicast() const BOOST_ASIO_NOEXCEPT { return (to_uint() & 0xF0000000) == 0xE0000000; } @@ -167,8 +167,8 @@ address_v4 make_address_v4(const char* str) return addr; } -address_v4 make_address_v4( - const char* str, boost::system::error_code& ec) +address_v4 make_address_v4(const char* str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { address_v4::bytes_type bytes; if (boost::asio::detail::socket_ops::inet_pton( @@ -182,8 +182,8 @@ address_v4 make_address_v4(const std::string& str) return make_address_v4(str.c_str()); } -address_v4 make_address_v4( - const std::string& str, boost::system::error_code& ec) +address_v4 make_address_v4(const std::string& str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { return make_address_v4(str.c_str(), ec); } @@ -196,7 +196,7 @@ address_v4 make_address_v4(string_view str) } address_v4 make_address_v4(string_view str, - boost::system::error_code& ec) + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { return make_address_v4(static_cast<std::string>(str), ec); } diff --git a/boost/asio/ip/impl/address_v6.hpp b/boost/asio/ip/impl/address_v6.hpp index f989b6a702..ebfd467e0f 100644 --- a/boost/asio/ip/impl/address_v6.hpp +++ b/boost/asio/ip/impl/address_v6.hpp @@ -2,7 +2,7 @@ // ip/impl/address_v6.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/impl/address_v6.ipp b/boost/asio/ip/impl/address_v6.ipp index 4eea4bc5a0..7ea2f24e1f 100644 --- a/boost/asio/ip/impl/address_v6.ipp +++ b/boost/asio/ip/impl/address_v6.ipp @@ -2,7 +2,7 @@ // ip/impl/address_v6.ipp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -32,7 +32,7 @@ namespace boost { namespace asio { namespace ip { -address_v6::address_v6() +address_v6::address_v6() BOOST_ASIO_NOEXCEPT : addr_(), scope_id_(0) { @@ -57,21 +57,21 @@ address_v6::address_v6(const address_v6::bytes_type& bytes, memcpy(addr_.s6_addr, bytes.data(), 16); } -address_v6::address_v6(const address_v6& other) +address_v6::address_v6(const address_v6& other) BOOST_ASIO_NOEXCEPT : addr_(other.addr_), scope_id_(other.scope_id_) { } #if defined(BOOST_ASIO_HAS_MOVE) -address_v6::address_v6(address_v6&& other) +address_v6::address_v6(address_v6&& other) BOOST_ASIO_NOEXCEPT : addr_(other.addr_), scope_id_(other.scope_id_) { } #endif // defined(BOOST_ASIO_HAS_MOVE) -address_v6& address_v6::operator=(const address_v6& other) +address_v6& address_v6::operator=(const address_v6& other) BOOST_ASIO_NOEXCEPT { addr_ = other.addr_; scope_id_ = other.scope_id_; @@ -79,7 +79,7 @@ address_v6& address_v6::operator=(const address_v6& other) } #if defined(BOOST_ASIO_HAS_MOVE) -address_v6& address_v6::operator=(address_v6&& other) +address_v6& address_v6::operator=(address_v6&& other) BOOST_ASIO_NOEXCEPT { addr_ = other.addr_; scope_id_ = other.scope_id_; @@ -87,7 +87,7 @@ address_v6& address_v6::operator=(address_v6&& other) } #endif // defined(BOOST_ASIO_HAS_MOVE) -address_v6::bytes_type address_v6::to_bytes() const +address_v6::bytes_type address_v6::to_bytes() const BOOST_ASIO_NOEXCEPT { using namespace std; // For memcpy. bytes_type bytes; @@ -139,7 +139,7 @@ address_v4 address_v6::to_v4() const } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -bool address_v6::is_loopback() const +bool address_v6::is_loopback() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) @@ -151,7 +151,7 @@ bool address_v6::is_loopback() const && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1)); } -bool address_v6::is_unspecified() const +bool address_v6::is_unspecified() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) @@ -163,17 +163,17 @@ bool address_v6::is_unspecified() const && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0)); } -bool address_v6::is_link_local() const +bool address_v6::is_link_local() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0x80)); } -bool address_v6::is_site_local() const +bool address_v6::is_site_local() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0xc0)); } -bool address_v6::is_v4_mapped() const +bool address_v6::is_v4_mapped() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) @@ -199,37 +199,37 @@ bool address_v6::is_v4_compatible() const } #endif // !defined(BOOST_ASIO_NO_DEPRECATED) -bool address_v6::is_multicast() const +bool address_v6::is_multicast() const BOOST_ASIO_NOEXCEPT { return (addr_.s6_addr[0] == 0xff); } -bool address_v6::is_multicast_global() const +bool address_v6::is_multicast_global() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x0e)); } -bool address_v6::is_multicast_link_local() const +bool address_v6::is_multicast_link_local() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x02)); } -bool address_v6::is_multicast_node_local() const +bool address_v6::is_multicast_node_local() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x01)); } -bool address_v6::is_multicast_org_local() const +bool address_v6::is_multicast_org_local() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x08)); } -bool address_v6::is_multicast_site_local() const +bool address_v6::is_multicast_site_local() const BOOST_ASIO_NOEXCEPT { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x05)); } -bool operator==(const address_v6& a1, const address_v6& a2) +bool operator==(const address_v6& a1, const address_v6& a2) BOOST_ASIO_NOEXCEPT { using namespace std; // For memcmp. return memcmp(&a1.addr_, &a2.addr_, @@ -237,7 +237,7 @@ bool operator==(const address_v6& a1, const address_v6& a2) && a1.scope_id_ == a2.scope_id_; } -bool operator<(const address_v6& a1, const address_v6& a2) +bool operator<(const address_v6& a1, const address_v6& a2) BOOST_ASIO_NOEXCEPT { using namespace std; // For memcmp. int memcmp_result = memcmp(&a1.addr_, &a2.addr_, @@ -249,7 +249,7 @@ bool operator<(const address_v6& a1, const address_v6& a2) return a1.scope_id_ < a2.scope_id_; } -address_v6 address_v6::loopback() +address_v6 address_v6::loopback() BOOST_ASIO_NOEXCEPT { address_v6 tmp; tmp.addr_.s6_addr[15] = 1; @@ -282,8 +282,8 @@ address_v6 make_address_v6(const char* str) return addr; } -address_v6 make_address_v6( - const char* str, boost::system::error_code& ec) +address_v6 make_address_v6(const char* str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { address_v6::bytes_type bytes; unsigned long scope_id = 0; @@ -298,8 +298,8 @@ address_v6 make_address_v6(const std::string& str) return make_address_v6(str.c_str()); } -address_v6 make_address_v6( - const std::string& str, boost::system::error_code& ec) +address_v6 make_address_v6(const std::string& str, + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { return make_address_v6(str.c_str(), ec); } @@ -312,7 +312,7 @@ address_v6 make_address_v6(string_view str) } address_v6 make_address_v6(string_view str, - boost::system::error_code& ec) + boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT { return make_address_v6(static_cast<std::string>(str), ec); } diff --git a/boost/asio/ip/impl/basic_endpoint.hpp b/boost/asio/ip/impl/basic_endpoint.hpp index 23655bf940..5eba925242 100644 --- a/boost/asio/ip/impl/basic_endpoint.hpp +++ b/boost/asio/ip/impl/basic_endpoint.hpp @@ -2,7 +2,7 @@ // ip/impl/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/impl/host_name.ipp b/boost/asio/ip/impl/host_name.ipp index 17b8395a76..565e5459a3 100644 --- a/boost/asio/ip/impl/host_name.ipp +++ b/boost/asio/ip/impl/host_name.ipp @@ -2,7 +2,7 @@ // ip/impl/host_name.ipp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/impl/network_v4.hpp b/boost/asio/ip/impl/network_v4.hpp index 3ca4e746bd..e20a6fefc9 100644 --- a/boost/asio/ip/impl/network_v4.hpp +++ b/boost/asio/ip/impl/network_v4.hpp @@ -2,7 +2,7 @@ // ip/impl/network_v4.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/ip/impl/network_v4.ipp b/boost/asio/ip/impl/network_v4.ipp index 62f742c669..d443475183 100644 --- a/boost/asio/ip/impl/network_v4.ipp +++ b/boost/asio/ip/impl/network_v4.ipp @@ -2,7 +2,7 @@ // ip/impl/network_v4.ipp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/ip/impl/network_v6.hpp b/boost/asio/ip/impl/network_v6.hpp index 1b13879ea3..6be5ab533f 100644 --- a/boost/asio/ip/impl/network_v6.hpp +++ b/boost/asio/ip/impl/network_v6.hpp @@ -2,7 +2,7 @@ // ip/impl/network_v6.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/impl/network_v6.ipp b/boost/asio/ip/impl/network_v6.ipp index 426bc33b39..cbdb974489 100644 --- a/boost/asio/ip/impl/network_v6.ipp +++ b/boost/asio/ip/impl/network_v6.ipp @@ -2,7 +2,7 @@ // ip/impl/network_v6.ipp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/ip/multicast.hpp b/boost/asio/ip/multicast.hpp index d46692c268..d863284192 100644 --- a/boost/asio/ip/multicast.hpp +++ b/boost/asio/ip/multicast.hpp @@ -2,7 +2,7 @@ // ip/multicast.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -33,7 +33,7 @@ namespace multicast { * @par Examples * Setting the option to join a multicast group: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::address multicast_address = * boost::asio::ip::address::from_string("225.0.0.1"); @@ -61,7 +61,7 @@ typedef boost::asio::ip::detail::socket_option::multicast_request< * @par Examples * Setting the option to leave a multicast group: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::address multicast_address = * boost::asio::ip::address::from_string("225.0.0.1"); @@ -89,7 +89,7 @@ typedef boost::asio::ip::detail::socket_option::multicast_request< * @par Examples * Setting the option: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::address_v4 local_interface = * boost::asio::ip::address_v4::from_string("1.2.3.4"); @@ -117,7 +117,7 @@ typedef boost::asio::ip::detail::socket_option::network_interface< * @par Examples * Setting the option: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::multicast::hops option(4); * socket.set_option(option); @@ -126,7 +126,7 @@ typedef boost::asio::ip::detail::socket_option::network_interface< * @par * Getting the current option value: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::multicast::hops option; * socket.get_option(option); @@ -154,7 +154,7 @@ typedef boost::asio::ip::detail::socket_option::multicast_hops< * @par Examples * Setting the option: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::multicast::enable_loopback option(true); * socket.set_option(option); @@ -163,7 +163,7 @@ typedef boost::asio::ip::detail::socket_option::multicast_hops< * @par * Getting the current option value: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::multicast::enable_loopback option; * socket.get_option(option); diff --git a/boost/asio/ip/network_v4.hpp b/boost/asio/ip/network_v4.hpp index 24e67b8371..25cbbce69f 100644 --- a/boost/asio/ip/network_v4.hpp +++ b/boost/asio/ip/network_v4.hpp @@ -2,7 +2,7 @@ // ip/network_v4.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/ip/network_v6.hpp b/boost/asio/ip/network_v6.hpp index 5fe96743df..dce950870b 100644 --- a/boost/asio/ip/network_v6.hpp +++ b/boost/asio/ip/network_v6.hpp @@ -2,7 +2,7 @@ // ip/network_v6.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/ip/resolver_base.hpp b/boost/asio/ip/resolver_base.hpp index 06cbcd0220..a61565fdc1 100644 --- a/boost/asio/ip/resolver_base.hpp +++ b/boost/asio/ip/resolver_base.hpp @@ -2,7 +2,7 @@ // ip/resolver_base.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/resolver_query_base.hpp b/boost/asio/ip/resolver_query_base.hpp index 1e287c6225..9e0a0321a5 100644 --- a/boost/asio/ip/resolver_query_base.hpp +++ b/boost/asio/ip/resolver_query_base.hpp @@ -2,7 +2,7 @@ // ip/resolver_query_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/resolver_service.hpp b/boost/asio/ip/resolver_service.hpp deleted file mode 100644 index 3e1fd38a70..0000000000 --- a/boost/asio/ip/resolver_service.hpp +++ /dev/null @@ -1,202 +0,0 @@ -// -// ip/resolver_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_IP_RESOLVER_SERVICE_HPP -#define BOOST_ASIO_IP_RESOLVER_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <boost/asio/async_result.hpp> -#include <boost/system/error_code.hpp> -#include <boost/asio/io_context.hpp> -#include <boost/asio/ip/basic_resolver_iterator.hpp> -#include <boost/asio/ip/basic_resolver_query.hpp> -#include <boost/asio/ip/basic_resolver_results.hpp> - -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/winrt_resolver_service.hpp> -#else -# include <boost/asio/detail/resolver_service.hpp> -#endif - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace ip { - -/// Default service implementation for a resolver. -template <typename InternetProtocol> -class resolver_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base< - resolver_service<InternetProtocol> > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - - /// The protocol type. - typedef InternetProtocol protocol_type; - - /// The endpoint type. - typedef typename InternetProtocol::endpoint endpoint_type; - - /// The query type. - typedef basic_resolver_query<InternetProtocol> query_type; - - /// The iterator type. - typedef basic_resolver_iterator<InternetProtocol> iterator_type; - - /// The results type. - typedef basic_resolver_results<InternetProtocol> results_type; - -private: - // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) - typedef boost::asio::detail::winrt_resolver_service<InternetProtocol> - service_impl_type; -#else - typedef boost::asio::detail::resolver_service<InternetProtocol> - service_impl_type; -#endif - -public: - /// The type of a resolver implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new resolver service for the specified io_context. - explicit resolver_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - resolver_service<InternetProtocol> >(io_context), - service_impl_(io_context) - { - } - - /// Construct a new resolver implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new resolver implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another resolver implementation. - void move_assign(implementation_type& impl, - resolver_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a resolver implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Cancel pending asynchronous operations. - void cancel(implementation_type& impl) - { - service_impl_.cancel(impl); - } - - /// Resolve a query to a list of entries. - results_type resolve(implementation_type& impl, const query_type& query, - boost::system::error_code& ec) - { - return service_impl_.resolve(impl, query, ec); - } - - /// Asynchronously resolve a query to a list of entries. - template <typename ResolveHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler, - void (boost::system::error_code, results_type)) - async_resolve(implementation_type& impl, const query_type& query, - BOOST_ASIO_MOVE_ARG(ResolveHandler) handler) - { - boost::asio::async_completion<ResolveHandler, - void (boost::system::error_code, results_type)> init(handler); - - service_impl_.async_resolve(impl, query, init.completion_handler); - - return init.result.get(); - } - - /// Resolve an endpoint to a list of entries. - results_type resolve(implementation_type& impl, - const endpoint_type& endpoint, boost::system::error_code& ec) - { - return service_impl_.resolve(impl, endpoint, ec); - } - - /// Asynchronously resolve an endpoint to a list of entries. - template <typename ResolveHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler, - void (boost::system::error_code, results_type)) - async_resolve(implementation_type& impl, const endpoint_type& endpoint, - BOOST_ASIO_MOVE_ARG(ResolveHandler) handler) - { - boost::asio::async_completion<ResolveHandler, - void (boost::system::error_code, results_type)> init(handler); - - service_impl_.async_resolve(impl, endpoint, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // Perform any fork-related housekeeping. - void notify_fork(boost::asio::io_context::fork_event event) - { - service_impl_.notify_fork(event); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace ip -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_IP_RESOLVER_SERVICE_HPP diff --git a/boost/asio/ip/tcp.hpp b/boost/asio/ip/tcp.hpp index dce1c8ee6a..d37b012b3c 100644 --- a/boost/asio/ip/tcp.hpp +++ b/boost/asio/ip/tcp.hpp @@ -2,7 +2,7 @@ // ip/tcp.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -100,7 +100,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::no_delay option(true); * socket.set_option(option); @@ -109,7 +109,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::tcp::no_delay option; * socket.get_option(option); diff --git a/boost/asio/ip/udp.hpp b/boost/asio/ip/udp.hpp index 9f07a55e7e..8ba20b4e62 100644 --- a/boost/asio/ip/udp.hpp +++ b/boost/asio/ip/udp.hpp @@ -2,7 +2,7 @@ // ip/udp.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ip/unicast.hpp b/boost/asio/ip/unicast.hpp index 793c5f7eb4..2cfcc59601 100644 --- a/boost/asio/ip/unicast.hpp +++ b/boost/asio/ip/unicast.hpp @@ -2,7 +2,7 @@ // ip/unicast.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -33,7 +33,7 @@ namespace unicast { * @par Examples * Setting the option: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::unicast::hops option(4); * socket.set_option(option); @@ -42,7 +42,7 @@ namespace unicast { * @par * Getting the current option value: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::ip::unicast::hops option; * socket.get_option(option); diff --git a/boost/asio/ip/v6_only.hpp b/boost/asio/ip/v6_only.hpp index c2f34acc11..54f4706430 100644 --- a/boost/asio/ip/v6_only.hpp +++ b/boost/asio/ip/v6_only.hpp @@ -2,7 +2,7 @@ // ip/v6_only.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -32,7 +32,7 @@ namespace ip { * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::v6_only option(true); * socket.set_option(option); @@ -41,7 +41,7 @@ namespace ip { * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::ip::v6_only option; * socket.get_option(option); diff --git a/boost/asio/is_executor.hpp b/boost/asio/is_executor.hpp index 8570475241..6cb8bb8380 100644 --- a/boost/asio/is_executor.hpp +++ b/boost/asio/is_executor.hpp @@ -2,7 +2,7 @@ // is_executor.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/is_read_buffered.hpp b/boost/asio/is_read_buffered.hpp index 4839bc53a7..bc97ba77f5 100644 --- a/boost/asio/is_read_buffered.hpp +++ b/boost/asio/is_read_buffered.hpp @@ -2,7 +2,7 @@ // is_read_buffered.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/is_write_buffered.hpp b/boost/asio/is_write_buffered.hpp index f18e981ba8..5ed8318e53 100644 --- a/boost/asio/is_write_buffered.hpp +++ b/boost/asio/is_write_buffered.hpp @@ -2,7 +2,7 @@ // is_write_buffered.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/local/basic_endpoint.hpp b/boost/asio/local/basic_endpoint.hpp index 248c4a809e..835eb20922 100644 --- a/boost/asio/local/basic_endpoint.hpp +++ b/boost/asio/local/basic_endpoint.hpp @@ -2,7 +2,7 @@ // local/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -77,6 +77,14 @@ public: { } + #if defined(BOOST_ASIO_HAS_STRING_VIEW) + /// Construct an endpoint using the specified path name. + basic_endpoint(string_view path_name) + : impl_(path_name) + { + } + #endif // defined(BOOST_ASIO_HAS_STRING_VIEW) + /// Copy constructor. basic_endpoint(const basic_endpoint& other) : impl_(other.impl_) diff --git a/boost/asio/local/connect_pair.hpp b/boost/asio/local/connect_pair.hpp index 10a3f6d2b1..6ee9a23ae3 100644 --- a/boost/asio/local/connect_pair.hpp +++ b/boost/asio/local/connect_pair.hpp @@ -2,7 +2,7 @@ // local/connect_pair.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -33,33 +33,28 @@ namespace asio { namespace local { /// Create a pair of connected sockets. -template <typename Protocol BOOST_ASIO_SVC_TPARAM BOOST_ASIO_SVC_TPARAM1> -void connect_pair( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket1, - basic_socket<Protocol BOOST_ASIO_SVC_TARG1>& socket2); +template <typename Protocol, typename Executor1, typename Executor2> +void connect_pair(basic_socket<Protocol, Executor1>& socket1, + basic_socket<Protocol, Executor2>& socket2); /// Create a pair of connected sockets. -template <typename Protocol BOOST_ASIO_SVC_TPARAM BOOST_ASIO_SVC_TPARAM1> -BOOST_ASIO_SYNC_OP_VOID connect_pair( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket1, - basic_socket<Protocol BOOST_ASIO_SVC_TARG1>& socket2, - boost::system::error_code& ec); - -template <typename Protocol BOOST_ASIO_SVC_TPARAM BOOST_ASIO_SVC_TPARAM1> -inline void connect_pair( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket1, - basic_socket<Protocol BOOST_ASIO_SVC_TARG1>& socket2) +template <typename Protocol, typename Executor1, typename Executor2> +BOOST_ASIO_SYNC_OP_VOID connect_pair(basic_socket<Protocol, Executor1>& socket1, + basic_socket<Protocol, Executor2>& socket2, boost::system::error_code& ec); + +template <typename Protocol, typename Executor1, typename Executor2> +inline void connect_pair(basic_socket<Protocol, Executor1>& socket1, + basic_socket<Protocol, Executor2>& socket2) { boost::system::error_code ec; connect_pair(socket1, socket2, ec); boost::asio::detail::throw_error(ec, "connect_pair"); } -template <typename Protocol BOOST_ASIO_SVC_TPARAM BOOST_ASIO_SVC_TPARAM1> +template <typename Protocol, typename Executor1, typename Executor2> inline BOOST_ASIO_SYNC_OP_VOID connect_pair( - basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket1, - basic_socket<Protocol BOOST_ASIO_SVC_TARG1>& socket2, - boost::system::error_code& ec) + basic_socket<Protocol, Executor1>& socket1, + basic_socket<Protocol, Executor2>& socket2, boost::system::error_code& ec) { // Check that this function is only being used with a UNIX domain socket. boost::asio::local::basic_endpoint<Protocol>* tmp diff --git a/boost/asio/local/datagram_protocol.hpp b/boost/asio/local/datagram_protocol.hpp index c664323013..b29add6fc5 100644 --- a/boost/asio/local/datagram_protocol.hpp +++ b/boost/asio/local/datagram_protocol.hpp @@ -2,7 +2,7 @@ // local/datagram_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/local/detail/endpoint.hpp b/boost/asio/local/detail/endpoint.hpp index 52d6246ae9..294fb95ef9 100644 --- a/boost/asio/local/detail/endpoint.hpp +++ b/boost/asio/local/detail/endpoint.hpp @@ -2,7 +2,7 @@ // local/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -23,6 +23,7 @@ #include <cstddef> #include <string> #include <boost/asio/detail/socket_types.hpp> +#include <boost/asio/detail/string_view.hpp> #include <boost/asio/detail/push_options.hpp> @@ -44,6 +45,11 @@ public: // Construct an endpoint using the specified path name. BOOST_ASIO_DECL endpoint(const std::string& path_name); + #if defined(BOOST_ASIO_HAS_STRING_VIEW) + // Construct an endpoint using the specified path name. + BOOST_ASIO_DECL endpoint(string_view path_name); + #endif // defined(BOOST_ASIO_HAS_STRING_VIEW) + // Copy constructor. endpoint(const endpoint& other) : data_(other.data_), diff --git a/boost/asio/local/detail/impl/endpoint.ipp b/boost/asio/local/detail/impl/endpoint.ipp index 3d6a800414..51ce2cf36d 100644 --- a/boost/asio/local/detail/impl/endpoint.ipp +++ b/boost/asio/local/detail/impl/endpoint.ipp @@ -2,7 +2,7 @@ // local/detail/impl/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -49,6 +49,13 @@ endpoint::endpoint(const std::string& path_name) init(path_name.data(), path_name.length()); } +#if defined(BOOST_ASIO_HAS_STRING_VIEW) +endpoint::endpoint(string_view path_name) +{ + init(path_name.data(), path_name.length()); +} +#endif // defined(BOOST_ASIO_HAS_STRING_VIEW) + void endpoint::resize(std::size_t new_size) { if (new_size > sizeof(boost::asio::detail::sockaddr_un_type)) diff --git a/boost/asio/local/stream_protocol.hpp b/boost/asio/local/stream_protocol.hpp index 65fdbf1a90..4fe0de5352 100644 --- a/boost/asio/local/stream_protocol.hpp +++ b/boost/asio/local/stream_protocol.hpp @@ -2,7 +2,7 @@ // local/stream_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/packaged_task.hpp b/boost/asio/packaged_task.hpp index 4928a1cc7a..0985e6d49b 100644 --- a/boost/asio/packaged_task.hpp +++ b/boost/asio/packaged_task.hpp @@ -2,7 +2,7 @@ // packaged_task.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/placeholders.hpp b/boost/asio/placeholders.hpp index 50e399ed28..3640bd62b5 100644 --- a/boost/asio/placeholders.hpp +++ b/boost/asio/placeholders.hpp @@ -2,7 +2,7 @@ // placeholders.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/posix/basic_descriptor.hpp b/boost/asio/posix/basic_descriptor.hpp index faf5b6def2..301c618e4d 100644 --- a/boost/asio/posix/basic_descriptor.hpp +++ b/boost/asio/posix/basic_descriptor.hpp @@ -2,7 +2,7 @@ // posix/basic_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,16 +17,24 @@ #include <boost/asio/detail/config.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ || defined(GENERATING_DOCUMENTATION) -#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/async_result.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> +#include <boost/asio/detail/reactive_descriptor_service.hpp> #include <boost/asio/detail/throw_error.hpp> #include <boost/asio/error.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> #include <boost/asio/posix/descriptor_base.hpp> +#if defined(BOOST_ASIO_HAS_MOVE) +# include <utility> +#endif // defined(BOOST_ASIO_HAS_MOVE) + #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -42,37 +50,61 @@ namespace posix { * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename DescriptorService> +template <typename Executor = executor> class basic_descriptor - : public basic_io_object<DescriptorService>, - public descriptor_base + : public descriptor_base { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + /// The native representation of a descriptor. - typedef typename DescriptorService::native_handle_type native_handle_type; +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef detail::reactive_descriptor_service::native_handle_type + native_handle_type; +#endif - /// A basic_descriptor is always the lowest layer. - typedef basic_descriptor<DescriptorService> lowest_layer_type; + /// A descriptor is always the lowest layer. + typedef basic_descriptor lowest_layer_type; - /// Construct a basic_descriptor without opening it. + /// Construct a descriptor without opening it. /** * This constructor creates a descriptor without opening it. * - * @param io_context The io_context object that the descriptor will use to + * @param ex The I/O executor that the descriptor will use, by default, to * dispatch handlers for any asynchronous operations performed on the * descriptor. */ - explicit basic_descriptor(boost::asio::io_context& io_context) - : basic_io_object<DescriptorService>(io_context) + explicit basic_descriptor(const executor_type& ex) + : impl_(ex) + { + } + + /// Construct a descriptor without opening it. + /** + * This constructor creates a descriptor without opening it. + * + * @param context An execution context which provides the I/O executor that + * the descriptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the descriptor. + */ + template <typename ExecutionContext> + explicit basic_descriptor(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { } - /// Construct a basic_descriptor on an existing native descriptor. + /// Construct a descriptor on an existing native descriptor. /** * This constructor creates a descriptor object to hold an existing native * descriptor. * - * @param io_context The io_context object that the descriptor will use to + * @param ex The I/O executor that the descriptor will use, by default, to * dispatch handlers for any asynchronous operations performed on the * descriptor. * @@ -80,55 +112,88 @@ public: * * @throws boost::system::system_error Thrown on failure. */ - basic_descriptor(boost::asio::io_context& io_context, + basic_descriptor(const executor_type& ex, const native_handle_type& native_descriptor) - : basic_io_object<DescriptorService>(io_context) + : impl_(ex) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + native_descriptor, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct a descriptor on an existing native descriptor. + /** + * This constructor creates a descriptor object to hold an existing native + * descriptor. + * + * @param context An execution context which provides the I/O executor that + * the descriptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the descriptor. + * + * @param native_descriptor A native descriptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_descriptor(ExecutionContext& context, + const native_handle_type& native_descriptor, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) { boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), native_descriptor, ec); boost::asio::detail::throw_error(ec, "assign"); } #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a basic_descriptor from another. + /// Move-construct a descriptor from another. /** * This constructor moves a descriptor from one object to another. * - * @param other The other basic_descriptor object from which the move will + * @param other The other descriptor object from which the move will * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_descriptor(io_context&) constructor. + * constructed using the @c basic_descriptor(const executor_type&) + * constructor. */ basic_descriptor(basic_descriptor&& other) - : basic_io_object<DescriptorService>( - BOOST_ASIO_MOVE_CAST(basic_descriptor)(other)) + : impl_(std::move(other.impl_)) { } - /// Move-assign a basic_descriptor from another. + /// Move-assign a descriptor from another. /** * This assignment operator moves a descriptor from one object to another. * - * @param other The other basic_descriptor object from which the move will + * @param other The other descriptor object from which the move will * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_descriptor(io_context&) constructor. + * constructed using the @c basic_descriptor(const executor_type&) + * constructor. */ basic_descriptor& operator=(basic_descriptor&& other) { - basic_io_object<DescriptorService>::operator=( - BOOST_ASIO_MOVE_CAST(basic_descriptor)(other)); + impl_ = std::move(other.impl_); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return impl_.get_executor(); + } + /// Get a reference to the lowest layer. /** * This function returns a reference to the lowest layer in a stack of - * layers. Since a basic_descriptor cannot contain any further layers, it + * layers. Since a descriptor cannot contain any further layers, it * simply returns a reference to itself. * * @return A reference to the lowest layer in the stack of layers. Ownership @@ -142,7 +207,7 @@ public: /// Get a const reference to the lowest layer. /** * This function returns a const reference to the lowest layer in a stack of - * layers. Since a basic_descriptor cannot contain any further layers, it + * layers. Since a descriptor cannot contain any further layers, it * simply returns a reference to itself. * * @return A const reference to the lowest layer in the stack of layers. @@ -164,7 +229,7 @@ public: void assign(const native_handle_type& native_descriptor) { boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), native_descriptor, ec); boost::asio::detail::throw_error(ec, "assign"); } @@ -180,15 +245,15 @@ public: BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor, boost::system::error_code& ec) { - this->get_service().assign( - this->get_implementation(), native_descriptor, ec); + impl_.get_service().assign( + impl_.get_implementation(), native_descriptor, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } /// Determine whether the descriptor is open. bool is_open() const { - return this->get_service().is_open(this->get_implementation()); + return impl_.get_service().is_open(impl_.get_implementation()); } /// Close the descriptor. @@ -203,7 +268,7 @@ public: void close() { boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "close"); } @@ -218,7 +283,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) { - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -230,7 +295,7 @@ public: */ native_handle_type native_handle() { - return this->get_service().native_handle(this->get_implementation()); + return impl_.get_service().native_handle(impl_.get_implementation()); } /// Release ownership of the native descriptor implementation. @@ -245,7 +310,7 @@ public: */ native_handle_type release() { - return this->get_service().release(this->get_implementation()); + return impl_.get_service().release(impl_.get_implementation()); } /// Cancel all asynchronous operations associated with the descriptor. @@ -259,7 +324,7 @@ public: void cancel() { boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "cancel"); } @@ -273,7 +338,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) { - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -292,7 +357,7 @@ public: * @par Example * Getting the number of bytes ready to read: * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); + * boost::asio::posix::stream_descriptor descriptor(my_context); * ... * boost::asio::posix::stream_descriptor::bytes_readable command; * descriptor.io_control(command); @@ -303,7 +368,7 @@ public: void io_control(IoControlCommand& command) { boost::system::error_code ec; - this->get_service().io_control(this->get_implementation(), command, ec); + impl_.get_service().io_control(impl_.get_implementation(), command, ec); boost::asio::detail::throw_error(ec, "io_control"); } @@ -322,7 +387,7 @@ public: * @par Example * Getting the number of bytes ready to read: * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); + * boost::asio::posix::stream_descriptor descriptor(my_context); * ... * boost::asio::posix::stream_descriptor::bytes_readable command; * boost::system::error_code ec; @@ -338,7 +403,7 @@ public: BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, boost::system::error_code& ec) { - this->get_service().io_control(this->get_implementation(), command, ec); + impl_.get_service().io_control(impl_.get_implementation(), command, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -355,7 +420,7 @@ public: */ bool non_blocking() const { - return this->get_service().non_blocking(this->get_implementation()); + return impl_.get_service().non_blocking(impl_.get_implementation()); } /// Sets the non-blocking mode of the descriptor. @@ -374,7 +439,7 @@ public: void non_blocking(bool mode) { boost::system::error_code ec; - this->get_service().non_blocking(this->get_implementation(), mode, ec); + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); boost::asio::detail::throw_error(ec, "non_blocking"); } @@ -394,7 +459,7 @@ public: BOOST_ASIO_SYNC_OP_VOID non_blocking( bool mode, boost::system::error_code& ec) { - this->get_service().non_blocking(this->get_implementation(), mode, ec); + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -414,8 +479,8 @@ public: */ bool native_non_blocking() const { - return this->get_service().native_non_blocking( - this->get_implementation()); + return impl_.get_service().native_non_blocking( + impl_.get_implementation()); } /// Sets the non-blocking mode of the native descriptor implementation. @@ -436,8 +501,8 @@ public: void native_non_blocking(bool mode) { boost::system::error_code ec; - this->get_service().native_non_blocking( - this->get_implementation(), mode, ec); + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); boost::asio::detail::throw_error(ec, "native_non_blocking"); } @@ -459,8 +524,8 @@ public: BOOST_ASIO_SYNC_OP_VOID native_non_blocking( bool mode, boost::system::error_code& ec) { - this->get_service().native_non_blocking( - this->get_implementation(), mode, ec); + impl_.get_service().native_non_blocking( + impl_.get_implementation(), mode, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -475,7 +540,7 @@ public: * @par Example * Waiting for a descriptor to become readable. * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); + * boost::asio::posix::stream_descriptor descriptor(my_context); * ... * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read); * @endcode @@ -483,7 +548,7 @@ public: void wait(wait_type w) { boost::system::error_code ec; - this->get_service().wait(this->get_implementation(), w, ec); + impl_.get_service().wait(impl_.get_implementation(), w, ec); boost::asio::detail::throw_error(ec, "wait"); } @@ -500,7 +565,7 @@ public: * @par Example * Waiting for a descriptor to become readable. * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); + * boost::asio::posix::stream_descriptor descriptor(my_context); * ... * boost::system::error_code ec; * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec); @@ -508,7 +573,7 @@ public: */ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) { - this->get_service().wait(this->get_implementation(), w, ec); + impl_.get_service().wait(impl_.get_implementation(), w, ec); BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -527,9 +592,9 @@ public: * const boost::system::error_code& error // Result of operation * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * @code @@ -543,7 +608,7 @@ public: * * ... * - * boost::asio::posix::stream_descriptor descriptor(io_context); + * boost::asio::posix::stream_descriptor descriptor(my_context); * ... * descriptor.async_wait( * boost::asio::posix::stream_descriptor::wait_read, @@ -555,19 +620,44 @@ public: void (boost::system::error_code)) async_wait(wait_type w, BOOST_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. - BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - - return this->get_service().async_wait(this->get_implementation(), - w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); + return async_initiate<WaitHandler, void (boost::system::error_code)>( + initiate_async_wait(), handler, this, w); } protected: /// Protected destructor to prevent deletion through this type. + /** + * This function destroys the descriptor, cancelling any outstanding + * asynchronous wait operations associated with the descriptor as if by + * calling @c cancel. + */ ~basic_descriptor() { } + + detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_; + +private: + // Disallow copying and assignment. + basic_descriptor(const basic_descriptor&) BOOST_ASIO_DELETED; + basic_descriptor& operator=(const basic_descriptor&) BOOST_ASIO_DELETED; + + struct initiate_async_wait + { + template <typename WaitHandler> + void operator()(BOOST_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. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue<WaitHandler> handler2(handler); + self->impl_.get_service().async_wait( + self->impl_.get_implementation(), w, handler2.value, + self->impl_.get_implementation_executor()); + } + }; }; } // namespace posix @@ -579,6 +669,4 @@ protected: #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) // || defined(GENERATING_DOCUMENTATION) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP diff --git a/boost/asio/posix/basic_stream_descriptor.hpp b/boost/asio/posix/basic_stream_descriptor.hpp index d840703a95..0098802211 100644 --- a/boost/asio/posix/basic_stream_descriptor.hpp +++ b/boost/asio/posix/basic_stream_descriptor.hpp @@ -2,7 +2,7 @@ // posix/basic_stream_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -16,21 +16,11 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +#include <boost/asio/posix/descriptor.hpp> #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ || defined(GENERATING_DOCUMENTATION) -#include <cstddef> -#include <boost/asio/detail/handler_type_requirements.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/posix/basic_descriptor.hpp> -#include <boost/asio/posix/stream_descriptor_service.hpp> - -#include <boost/asio/detail/push_options.hpp> - namespace boost { namespace asio { namespace posix { @@ -47,81 +37,126 @@ namespace posix { * @par Concepts: * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. */ -template <typename StreamDescriptorService = stream_descriptor_service> +template <typename Executor = executor> class basic_stream_descriptor - : public basic_descriptor<StreamDescriptorService> + : public basic_descriptor<Executor> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + /// The native representation of a descriptor. - typedef typename StreamDescriptorService::native_handle_type + typedef typename basic_descriptor<Executor>::native_handle_type native_handle_type; - /// Construct a basic_stream_descriptor without opening it. + /// Construct a stream descriptor without opening it. /** * This constructor creates a stream descriptor without opening it. The * descriptor needs to be opened and then connected or accepted before data * can be sent or received on it. * - * @param io_context The io_context object that the stream descriptor will - * use to dispatch handlers for any asynchronous operations performed on the + * @param ex The I/O executor that the descriptor will use, by default, to + * dispatch handlers for any asynchronous operations performed on the * descriptor. */ - explicit basic_stream_descriptor(boost::asio::io_context& io_context) - : basic_descriptor<StreamDescriptorService>(io_context) + explicit basic_stream_descriptor(const executor_type& ex) + : basic_descriptor<Executor>(ex) + { + } + + /// Construct a stream descriptor without opening it. + /** + * This constructor creates a stream descriptor without opening it. The + * descriptor needs to be opened and then connected or accepted before data + * can be sent or received on it. + * + * @param context An execution context which provides the I/O executor that + * the descriptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the descriptor. + */ + template <typename ExecutionContext> + explicit basic_stream_descriptor(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_descriptor<Executor>(context) { } - /// Construct a basic_stream_descriptor on an existing native descriptor. + /// Construct a stream descriptor on an existing native descriptor. /** * This constructor creates a stream descriptor object to hold an existing * native descriptor. * - * @param io_context The io_context object that the stream descriptor will - * use to dispatch handlers for any asynchronous operations performed on the + * @param ex The I/O executor that the descriptor will use, by default, to + * dispatch handlers for any asynchronous operations performed on the * descriptor. * * @param native_descriptor The new underlying descriptor implementation. * * @throws boost::system::system_error Thrown on failure. */ - basic_stream_descriptor(boost::asio::io_context& io_context, + basic_stream_descriptor(const executor_type& ex, const native_handle_type& native_descriptor) - : basic_descriptor<StreamDescriptorService>(io_context, native_descriptor) + : basic_descriptor<Executor>(ex, native_descriptor) + { + } + + /// Construct a stream descriptor on an existing native descriptor. + /** + * This constructor creates a stream descriptor object to hold an existing + * native descriptor. + * + * @param context An execution context which provides the I/O executor that + * the descriptor will use, by default, to dispatch handlers for any + * asynchronous operations performed on the descriptor. + * + * @param native_descriptor The new underlying descriptor implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_stream_descriptor(ExecutionContext& context, + const native_handle_type& native_descriptor, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_descriptor<Executor>(context, native_descriptor) { } #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a basic_stream_descriptor from another. + /// Move-construct a stream descriptor from another. /** * This constructor moves a stream descriptor from one object to another. * - * @param other The other basic_stream_descriptor object from which the move + * @param other The other stream descriptor object from which the move * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_stream_descriptor(io_context&) constructor. + * constructed using the @c basic_stream_descriptor(const executor_type&) + * constructor. */ basic_stream_descriptor(basic_stream_descriptor&& other) - : basic_descriptor<StreamDescriptorService>( - BOOST_ASIO_MOVE_CAST(basic_stream_descriptor)(other)) + : descriptor(std::move(other)) { } - /// Move-assign a basic_stream_descriptor from another. + /// Move-assign a stream descriptor from another. /** * This assignment operator moves a stream descriptor from one object to * another. * - * @param other The other basic_stream_descriptor object from which the move + * @param other The other stream descriptor object from which the move * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_stream_descriptor(io_context&) constructor. + * constructed using the @c basic_stream_descriptor(const executor_type&) + * constructor. */ basic_stream_descriptor& operator=(basic_stream_descriptor&& other) { - basic_descriptor<StreamDescriptorService>::operator=( - BOOST_ASIO_MOVE_CAST(basic_stream_descriptor)(other)); + descriptor::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -157,8 +192,8 @@ public: std::size_t write_some(const ConstBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().write_some( - this->get_implementation(), buffers, ec); + std::size_t s = this->impl_.get_service().write_some( + this->impl_.get_implementation(), buffers, ec); boost::asio::detail::throw_error(ec, "write_some"); return s; } @@ -183,8 +218,8 @@ public: std::size_t write_some(const ConstBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().write_some( - this->get_implementation(), buffers, ec); + return this->impl_.get_service().write_some( + this->impl_.get_implementation(), buffers, ec); } /// Start an asynchronous write. @@ -205,9 +240,9 @@ public: * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all @@ -228,12 +263,9 @@ public: async_write_some(const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - return this->get_service().async_write_some(this->get_implementation(), - buffers, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_write_some(), handler, this, buffers); } /// Read some data from the descriptor. @@ -268,8 +300,8 @@ public: std::size_t read_some(const MutableBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().read_some( - this->get_implementation(), buffers, ec); + std::size_t s = this->impl_.get_service().read_some( + this->impl_.get_implementation(), buffers, ec); boost::asio::detail::throw_error(ec, "read_some"); return s; } @@ -295,8 +327,8 @@ public: std::size_t read_some(const MutableBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().read_some( - this->get_implementation(), buffers, ec); + return this->impl_.get_service().read_some( + this->impl_.get_implementation(), buffers, ec); } /// Start an asynchronous read. @@ -317,9 +349,9 @@ public: * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the @@ -341,24 +373,54 @@ public: async_read_some(const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - return this->get_service().async_read_some(this->get_implementation(), - buffers, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_read_some(), handler, this, buffers); } + +private: + struct initiate_async_write_some + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue<WriteHandler> 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 <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> handler2(handler); + self->impl_.get_service().async_read_some( + self->impl_.get_implementation(), buffers, handler2.value, + self->impl_.get_implementation_executor()); + } + }; }; } // namespace posix } // namespace asio } // namespace boost -#include <boost/asio/detail/pop_options.hpp> - #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) // || defined(GENERATING_DOCUMENTATION) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP diff --git a/boost/asio/posix/descriptor.hpp b/boost/asio/posix/descriptor.hpp index be672ff11c..d7aa928725 100644 --- a/boost/asio/posix/descriptor.hpp +++ b/boost/asio/posix/descriptor.hpp @@ -2,7 +2,7 @@ // posix/descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,630 +17,23 @@ #include <boost/asio/detail/config.hpp> -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ || defined(GENERATING_DOCUMENTATION) -#include <boost/asio/async_result.hpp> -#include <boost/asio/basic_io_object.hpp> -#include <boost/asio/detail/handler_type_requirements.hpp> -#include <boost/asio/detail/reactive_descriptor_service.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> -#include <boost/asio/posix/descriptor_base.hpp> - -#if defined(BOOST_ASIO_HAS_MOVE) -# include <utility> -#endif // defined(BOOST_ASIO_HAS_MOVE) - -#define BOOST_ASIO_SVC_T boost::asio::detail::reactive_descriptor_service - -#include <boost/asio/detail/push_options.hpp> +#include <boost/asio/posix/basic_descriptor.hpp> namespace boost { namespace asio { namespace posix { -/// Provides POSIX descriptor functionality. -/** - * The posix::descriptor class template provides the ability to wrap a - * POSIX descriptor. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class descriptor - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>, - public descriptor_base -{ -public: - /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; - - /// The native representation of a descriptor. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type; -#endif - - /// A descriptor is always the lowest layer. - typedef descriptor lowest_layer_type; - - /// Construct a descriptor without opening it. - /** - * This constructor creates a descriptor without opening it. - * - * @param io_context The io_context object that the descriptor will use to - * dispatch handlers for any asynchronous operations performed on the - * descriptor. - */ - explicit descriptor(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - } - - /// Construct a descriptor on an existing native descriptor. - /** - * This constructor creates a descriptor object to hold an existing native - * descriptor. - * - * @param io_context The io_context object that the descriptor will use to - * dispatch handlers for any asynchronous operations performed on the - * descriptor. - * - * @param native_descriptor A native descriptor. - * - * @throws boost::system::system_error Thrown on failure. - */ - descriptor(boost::asio::io_context& io_context, - const native_handle_type& native_descriptor) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), - native_descriptor, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a descriptor from another. - /** - * This constructor moves a descriptor from one object to another. - * - * @param other The other descriptor object from which the move will - * occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c descriptor(io_context&) constructor. - */ - descriptor(descriptor&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) - { - } - - /// Move-assign a descriptor from another. - /** - * This assignment operator moves a descriptor from one object to another. - * - * @param other The other descriptor object from which the move will - * occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c descriptor(io_context&) constructor. - */ - descriptor& operator=(descriptor&& other) - { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); - return *this; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - - /// Get the executor associated with the object. - executor_type get_executor() BOOST_ASIO_NOEXCEPT - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since a descriptor cannot contain any further layers, it - * simply returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Get a const reference to the lowest layer. - /** - * This function returns a const reference to the lowest layer in a stack of - * layers. Since a descriptor cannot contain any further layers, it - * simply returns a reference to itself. - * - * @return A const reference to the lowest layer in the stack of layers. - * Ownership is not transferred to the caller. - */ - const lowest_layer_type& lowest_layer() const - { - return *this; - } - - /// Assign an existing native descriptor to the descriptor. - /* - * This function opens the descriptor to hold an existing native descriptor. - * - * @param native_descriptor A native descriptor. - * - * @throws boost::system::system_error Thrown on failure. - */ - void assign(const native_handle_type& native_descriptor) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), - native_descriptor, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - - /// Assign an existing native descriptor to the descriptor. - /* - * This function opens the descriptor to hold an existing native descriptor. - * - * @param native_descriptor A native descriptor. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor, - boost::system::error_code& ec) - { - this->get_service().assign( - this->get_implementation(), native_descriptor, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the descriptor is open. - bool is_open() const - { - return this->get_service().is_open(this->get_implementation()); - } - - /// Close the descriptor. - /** - * This function is used to close the descriptor. Any asynchronous read or - * write operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. Note that, even if - * the function indicates an error, the underlying descriptor is closed. - */ - void close() - { - boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "close"); - } - - /// Close the descriptor. - /** - * This function is used to close the descriptor. Any asynchronous read or - * write operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. Note that, even if - * the function indicates an error, the underlying descriptor is closed. - */ - BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) - { - this->get_service().close(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native descriptor representation. - /** - * This function may be used to obtain the underlying representation of the - * descriptor. This is intended to allow access to native descriptor - * functionality that is not otherwise provided. - */ - native_handle_type native_handle() - { - return this->get_service().native_handle(this->get_implementation()); - } - - /// Release ownership of the native descriptor implementation. - /** - * This function may be used to obtain the underlying representation of the - * descriptor. After calling this function, @c is_open() returns false. The - * caller is responsible for closing the descriptor. - * - * All outstanding asynchronous read or write operations will finish - * immediately, and the handlers for cancelled operations will be passed the - * boost::asio::error::operation_aborted error. - */ - native_handle_type release() - { - return this->get_service().release(this->get_implementation()); - } - - /// Cancel all asynchronous operations associated with the descriptor. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void cancel() - { - boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "cancel"); - } - - /// Cancel all asynchronous operations associated with the descriptor. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) - { - this->get_service().cancel(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Perform an IO control command on the descriptor. - /** - * This function is used to execute an IO control command on the descriptor. - * - * @param command The IO control command to be performed on the descriptor. - * - * @throws boost::system::system_error Thrown on failure. - * - * @sa IoControlCommand @n - * boost::asio::posix::descriptor_base::bytes_readable @n - * boost::asio::posix::descriptor_base::non_blocking_io - * - * @par Example - * Getting the number of bytes ready to read: - * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); - * ... - * boost::asio::posix::stream_descriptor::bytes_readable command; - * descriptor.io_control(command); - * std::size_t bytes_readable = command.get(); - * @endcode - */ - template <typename IoControlCommand> - void io_control(IoControlCommand& command) - { - boost::system::error_code ec; - this->get_service().io_control(this->get_implementation(), command, ec); - boost::asio::detail::throw_error(ec, "io_control"); - } - - /// Perform an IO control command on the descriptor. - /** - * This function is used to execute an IO control command on the descriptor. - * - * @param command The IO control command to be performed on the descriptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa IoControlCommand @n - * boost::asio::posix::descriptor_base::bytes_readable @n - * boost::asio::posix::descriptor_base::non_blocking_io - * - * @par Example - * Getting the number of bytes ready to read: - * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); - * ... - * boost::asio::posix::stream_descriptor::bytes_readable command; - * boost::system::error_code ec; - * descriptor.io_control(command, ec); - * if (ec) - * { - * // An error occurred. - * } - * std::size_t bytes_readable = command.get(); - * @endcode - */ - template <typename IoControlCommand> - BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, - boost::system::error_code& ec) - { - this->get_service().io_control(this->get_implementation(), command, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the descriptor. - /** - * @returns @c true if the descriptor's synchronous operations will fail with - * boost::asio::error::would_block if they are unable to perform the requested - * operation immediately. If @c false, synchronous operations will block - * until complete. - * - * @note The non-blocking mode has no effect on the behaviour of asynchronous - * operations. Asynchronous operations will never fail with the error - * boost::asio::error::would_block. - */ - bool non_blocking() const - { - return this->get_service().non_blocking(this->get_implementation()); - } - - /// Sets the non-blocking mode of the descriptor. - /** - * @param mode If @c true, the descriptor's synchronous operations will fail - * with boost::asio::error::would_block if they are unable to perform the - * requested operation immediately. If @c false, synchronous operations will - * block until complete. - * - * @throws boost::system::system_error Thrown on failure. - * - * @note The non-blocking mode has no effect on the behaviour of asynchronous - * operations. Asynchronous operations will never fail with the error - * boost::asio::error::would_block. - */ - void non_blocking(bool mode) - { - boost::system::error_code ec; - this->get_service().non_blocking(this->get_implementation(), mode, ec); - boost::asio::detail::throw_error(ec, "non_blocking"); - } - - /// Sets the non-blocking mode of the descriptor. - /** - * @param mode If @c true, the descriptor's synchronous operations will fail - * with boost::asio::error::would_block if they are unable to perform the - * requested operation immediately. If @c false, synchronous operations will - * block until complete. - * - * @param ec Set to indicate what error occurred, if any. - * - * @note The non-blocking mode has no effect on the behaviour of asynchronous - * operations. Asynchronous operations will never fail with the error - * boost::asio::error::would_block. - */ - BOOST_ASIO_SYNC_OP_VOID non_blocking( - bool mode, boost::system::error_code& ec) - { - this->get_service().non_blocking(this->get_implementation(), mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the native descriptor implementation. - /** - * This function is used to retrieve the non-blocking mode of the underlying - * native descriptor. This mode has no effect on the behaviour of the - * descriptor object's synchronous operations. - * - * @returns @c true if the underlying descriptor is in non-blocking mode and - * direct system calls may fail with boost::asio::error::would_block (or the - * equivalent system error). - * - * @note The current non-blocking mode is cached by the descriptor object. - * Consequently, the return value may be incorrect if the non-blocking mode - * was set directly on the native descriptor. - */ - bool native_non_blocking() const - { - return this->get_service().native_non_blocking( - this->get_implementation()); - } - - /// Sets the non-blocking mode of the native descriptor implementation. - /** - * This function is used to modify the non-blocking mode of the underlying - * native descriptor. It has no effect on the behaviour of the descriptor - * object's synchronous operations. - * - * @param mode If @c true, the underlying descriptor is put into non-blocking - * mode and direct system calls may fail with boost::asio::error::would_block - * (or the equivalent system error). - * - * @throws boost::system::system_error Thrown on failure. If the @c mode is - * @c false, but the current value of @c non_blocking() is @c true, this - * function fails with boost::asio::error::invalid_argument, as the - * combination does not make sense. - */ - void native_non_blocking(bool mode) - { - boost::system::error_code ec; - this->get_service().native_non_blocking( - this->get_implementation(), mode, ec); - boost::asio::detail::throw_error(ec, "native_non_blocking"); - } - - /// Sets the non-blocking mode of the native descriptor implementation. - /** - * This function is used to modify the non-blocking mode of the underlying - * native descriptor. It has no effect on the behaviour of the descriptor - * object's synchronous operations. - * - * @param mode If @c true, the underlying descriptor is put into non-blocking - * mode and direct system calls may fail with boost::asio::error::would_block - * (or the equivalent system error). - * - * @param ec Set to indicate what error occurred, if any. If the @c mode is - * @c false, but the current value of @c non_blocking() is @c true, this - * function fails with boost::asio::error::invalid_argument, as the - * combination does not make sense. - */ - BOOST_ASIO_SYNC_OP_VOID native_non_blocking( - bool mode, boost::system::error_code& ec) - { - this->get_service().native_non_blocking( - this->get_implementation(), mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Wait for the descriptor to become ready to read, ready to write, or to - /// have pending error conditions. - /** - * This function is used to perform a blocking wait for a descriptor to enter - * a ready to read, write or error condition state. - * - * @param w Specifies the desired descriptor state. - * - * @par Example - * Waiting for a descriptor to become readable. - * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); - * ... - * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read); - * @endcode - */ - void wait(wait_type w) - { - boost::system::error_code ec; - this->get_service().wait(this->get_implementation(), w, ec); - boost::asio::detail::throw_error(ec, "wait"); - } - - /// Wait for the descriptor to become ready to read, ready to write, or to - /// have pending error conditions. - /** - * This function is used to perform a blocking wait for a descriptor to enter - * a ready to read, write or error condition state. - * - * @param w Specifies the desired descriptor state. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * Waiting for a descriptor to become readable. - * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); - * ... - * boost::system::error_code ec; - * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec); - * @endcode - */ - BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) - { - this->get_service().wait(this->get_implementation(), w, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Asynchronously wait for the descriptor to become ready to read, ready to - /// write, or to have pending error conditions. - /** - * This function is used to perform an asynchronous wait for a descriptor to - * enter a ready to read, write or error condition state. - * - * @param w Specifies the desired descriptor state. - * - * @param handler The handler to be called when the wait operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error // Result of operation - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @par Example - * @code - * void wait_handler(const boost::system::error_code& error) - * { - * if (!error) - * { - * // Wait succeeded. - * } - * } - * - * ... - * - * boost::asio::posix::stream_descriptor descriptor(io_context); - * ... - * descriptor.async_wait( - * boost::asio::posix::stream_descriptor::wait_read, - * wait_handler); - * @endcode - */ - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(wait_type w, BOOST_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. - BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_wait( - this->get_implementation(), w, init.completion_handler); - - return init.result.get(); - } - -protected: - /// Protected destructor to prevent deletion through this type. - /** - * This function destroys the descriptor, cancelling any outstanding - * asynchronous wait operations associated with the descriptor as if by - * calling @c cancel. - */ - ~descriptor() - { - } -}; +/// Typedef for the typical usage of basic_descriptor. +typedef basic_descriptor<> descriptor; } // namespace posix } // namespace asio } // namespace boost -#include <boost/asio/detail/pop_options.hpp> - -#undef BOOST_ASIO_SVC_T - #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) - // || defined(GENERATING_DOCUMENTATION) - -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + // || defined(GENERATING_DOCUMENTATION) #endif // BOOST_ASIO_POSIX_DESCRIPTOR_HPP diff --git a/boost/asio/posix/descriptor_base.hpp b/boost/asio/posix/descriptor_base.hpp index 6722f04ef7..ff7d4c9845 100644 --- a/boost/asio/posix/descriptor_base.hpp +++ b/boost/asio/posix/descriptor_base.hpp @@ -2,7 +2,7 @@ // posix/descriptor_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -57,7 +57,7 @@ public: * * @par Example * @code - * boost::asio::posix::stream_descriptor descriptor(io_context); + * boost::asio::posix::stream_descriptor descriptor(my_context); * ... * boost::asio::descriptor_base::bytes_readable command(true); * descriptor.io_control(command); diff --git a/boost/asio/posix/stream_descriptor.hpp b/boost/asio/posix/stream_descriptor.hpp index af8cbe92c0..035cf3c5b1 100644 --- a/boost/asio/posix/stream_descriptor.hpp +++ b/boost/asio/posix/stream_descriptor.hpp @@ -2,7 +2,7 @@ // posix/stream_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -16,341 +16,18 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> -#include <boost/asio/posix/descriptor.hpp> #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ || defined(GENERATING_DOCUMENTATION) -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/posix/basic_stream_descriptor.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +#include <boost/asio/posix/basic_stream_descriptor.hpp> namespace boost { namespace asio { namespace posix { -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -// Typedef for the typical usage of a stream-oriented descriptor. +/// Typedef for the typical usage of a stream-oriented descriptor. typedef basic_stream_descriptor<> stream_descriptor; -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -/// Provides stream-oriented descriptor functionality. -/** - * The posix::stream_descriptor class template provides asynchronous and - * blocking stream-oriented descriptor functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -class stream_descriptor - : public descriptor -{ -public: - /// Construct a stream_descriptor without opening it. - /** - * This constructor creates a stream descriptor without opening it. The - * descriptor needs to be opened and then connected or accepted before data - * can be sent or received on it. - * - * @param io_context The io_context object that the stream descriptor will - * use to dispatch handlers for any asynchronous operations performed on the - * descriptor. - */ - explicit stream_descriptor(boost::asio::io_context& io_context) - : descriptor(io_context) - { - } - - /// Construct a stream_descriptor on an existing native descriptor. - /** - * This constructor creates a stream descriptor object to hold an existing - * native descriptor. - * - * @param io_context The io_context object that the stream descriptor will - * use to dispatch handlers for any asynchronous operations performed on the - * descriptor. - * - * @param native_descriptor The new underlying descriptor implementation. - * - * @throws boost::system::system_error Thrown on failure. - */ - stream_descriptor(boost::asio::io_context& io_context, - const native_handle_type& native_descriptor) - : descriptor(io_context, native_descriptor) - { - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a stream_descriptor from another. - /** - * This constructor moves a stream descriptor from one object to another. - * - * @param other The other stream_descriptor object from which the move - * will occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c stream_descriptor(io_context&) constructor. - */ - stream_descriptor(stream_descriptor&& other) - : descriptor(std::move(other)) - { - } - - /// Move-assign a stream_descriptor from another. - /** - * This assignment operator moves a stream descriptor from one object to - * another. - * - * @param other The other stream_descriptor object from which the move - * will occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c stream_descriptor(io_context&) constructor. - */ - stream_descriptor& operator=(stream_descriptor&& other) - { - descriptor::operator=(std::move(other)); - return *this; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Write some data to the descriptor. - /** - * This function is used to write data to the stream descriptor. The function - * call will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the descriptor. - * - * @returns The number of bytes written. - * - * @throws boost::system::system_error Thrown on failure. An error code of - * boost::asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * descriptor.write_some(boost::asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename ConstBufferSequence> - std::size_t write_some(const ConstBufferSequence& buffers) - { - boost::system::error_code ec; - std::size_t s = this->get_service().write_some( - this->get_implementation(), buffers, ec); - boost::asio::detail::throw_error(ec, "write_some"); - return s; - } - - /// Write some data to the descriptor. - /** - * This function is used to write data to the stream descriptor. The function - * call will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the descriptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template <typename ConstBufferSequence> - std::size_t write_some(const ConstBufferSequence& buffers, - boost::system::error_code& ec) - { - return this->get_service().write_some( - this->get_implementation(), buffers, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write data to the stream - * descriptor. The function call always returns immediately. - * - * @param buffers One or more data buffers to be written to the descriptor. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * descriptor.async_write_some(boost::asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - boost::asio::async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_write_some( - this->get_implementation(), buffers, init.completion_handler); - - return init.result.get(); - } - - /// Read some data from the descriptor. - /** - * This function is used to read data from the stream descriptor. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws boost::system::system_error Thrown on failure. An error code of - * boost::asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * descriptor.read_some(boost::asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename MutableBufferSequence> - std::size_t read_some(const MutableBufferSequence& buffers) - { - boost::system::error_code ec; - std::size_t s = this->get_service().read_some( - this->get_implementation(), buffers, ec); - boost::asio::detail::throw_error(ec, "read_some"); - return s; - } - - /// Read some data from the descriptor. - /** - * This function is used to read data from the stream descriptor. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template <typename MutableBufferSequence> - std::size_t read_some(const MutableBufferSequence& buffers, - boost::system::error_code& ec) - { - return this->get_service().read_some( - this->get_implementation(), buffers, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read data from the stream - * descriptor. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read function if you need to ensure that the - * requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * descriptor.async_read_some(boost::asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - boost::asio::async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_read_some( - this->get_implementation(), buffers, init.completion_handler); - - return init.result.get(); - } -}; -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } // namespace posix } // namespace asio diff --git a/boost/asio/posix/stream_descriptor_service.hpp b/boost/asio/posix/stream_descriptor_service.hpp deleted file mode 100644 index b91000ba29..0000000000 --- a/boost/asio/posix/stream_descriptor_service.hpp +++ /dev/null @@ -1,281 +0,0 @@ -// -// posix/stream_descriptor_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP -#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ - || defined(GENERATING_DOCUMENTATION) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> -#include <boost/asio/detail/reactive_descriptor_service.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace posix { - -/// Default service implementation for a stream descriptor. -class stream_descriptor_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<stream_descriptor_service> -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - -private: - // The type of the platform-specific implementation. - typedef detail::reactive_descriptor_service service_impl_type; - -public: - /// The type of a stream descriptor implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native descriptor type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new stream descriptor service for the specified io_context. - explicit stream_descriptor_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base<stream_descriptor_service>(io_context), - service_impl_(io_context) - { - } - - /// Construct a new stream descriptor implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new stream descriptor implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another stream descriptor implementation. - void move_assign(implementation_type& impl, - stream_descriptor_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a stream descriptor implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Assign an existing native descriptor to a stream descriptor. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const native_handle_type& native_descriptor, - boost::system::error_code& ec) - { - service_impl_.assign(impl, native_descriptor, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the descriptor is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a stream descriptor implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native descriptor implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Release ownership of the native descriptor implementation. - native_handle_type release(implementation_type& impl) - { - return service_impl_.release(impl); - } - - /// Cancel all asynchronous operations associated with the descriptor. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Perform an IO control command on the descriptor. - template <typename IoControlCommand> - BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl, - IoControlCommand& command, boost::system::error_code& ec) - { - service_impl_.io_control(impl, command, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the descriptor. - bool non_blocking(const implementation_type& impl) const - { - return service_impl_.non_blocking(impl); - } - - /// Sets the non-blocking mode of the descriptor. - BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the native descriptor implementation. - bool native_non_blocking(const implementation_type& impl) const - { - return service_impl_.native_non_blocking(impl); - } - - /// Sets the non-blocking mode of the native descriptor implementation. - BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.native_non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Wait for the descriptor to become ready to read, ready to write, or to - /// have pending error conditions. - BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl, - descriptor_base::wait_type w, boost::system::error_code& ec) - { - service_impl_.wait(impl, w, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Asynchronously wait for the descriptor to become ready to read, ready to - /// write, or to have pending error conditions. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, descriptor_base::wait_type w, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, w, init.completion_handler); - - return init.result.get(); - } - - /// Write the given data to the stream. - template <typename ConstBufferSequence> - std::size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, boost::system::error_code& ec) - { - return service_impl_.write_some(impl, buffers, ec); - } - - /// Start an asynchronous write. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - boost::asio::async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_write_some(impl, buffers, init.completion_handler); - - return init.result.get(); - } - - /// Read some data from the stream. - template <typename MutableBufferSequence> - std::size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, boost::system::error_code& ec) - { - return service_impl_.read_some(impl, buffers, ec); - } - - /// Start an asynchronous read. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - boost::asio::async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_read_some(impl, buffers, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace posix -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) - // || defined(GENERATING_DOCUMENTATION) - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP diff --git a/boost/asio/post.hpp b/boost/asio/post.hpp index 667613ec54..0fbdbf0b98 100644 --- a/boost/asio/post.hpp +++ b/boost/asio/post.hpp @@ -2,7 +2,7 @@ // post.hpp // ~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -32,6 +32,9 @@ namespace asio { * executor. The function object is queued for execution, and is never called * from the current thread prior to returning from <tt>post()</tt>. * + * The use of @c post(), rather than @ref defer(), indicates the caller's + * preference that the function object be eagerly queued for execution. + * * This function has the following effects: * * @li Constructs a function object handler of type @c Handler, initialized @@ -60,6 +63,9 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post( * The function object is queued for execution, and is never called from the * current thread prior to returning from <tt>post()</tt>. * + * The use of @c post(), rather than @ref defer(), indicates the caller's + * preference that the function object be eagerly queued for execution. + * * This function has the following effects: * * @li Constructs a function object handler of type @c Handler, initialized diff --git a/boost/asio/raw_socket_service.hpp b/boost/asio/raw_socket_service.hpp deleted file mode 100644 index 63ebf5cb30..0000000000 --- a/boost/asio/raw_socket_service.hpp +++ /dev/null @@ -1,468 +0,0 @@ -// -// raw_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_RAW_SOCKET_SERVICE_HPP -#define BOOST_ASIO_RAW_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/type_traits.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/null_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_socket_service.hpp> -#else -# include <boost/asio/detail/reactive_socket_service.hpp> -#endif - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a raw socket. -template <typename Protocol> -class raw_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<raw_socket_service<Protocol> > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) - typedef detail::null_socket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#else - typedef detail::reactive_socket_service<Protocol> service_impl_type; -#endif - -public: - /// The type of a raw socket. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef typename service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new raw socket service for the specified io_context. - explicit raw_socket_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - raw_socket_service<Protocol> >(io_context), - service_impl_(io_context) - { - } - - /// Construct a new raw socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new raw socket implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another raw socket implementation. - void move_assign(implementation_type& impl, - raw_socket_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } - - // All socket services have access to each other's implementations. - template <typename Protocol1> friend class raw_socket_service; - - /// Move-construct a new raw socket implementation from another protocol - /// type. - template <typename Protocol1> - void converting_move_construct(implementation_type& impl, - raw_socket_service<Protocol1>& other_service, - typename raw_socket_service< - Protocol1>::implementation_type& other_impl, - typename enable_if<is_convertible< - Protocol1, Protocol>::value>::type* = 0) - { - service_impl_.template converting_move_construct<Protocol1>( - impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a raw socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - // Open a new raw socket implementation. - BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl, - const protocol_type& protocol, boost::system::error_code& ec) - { - if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_RAW)) - service_impl_.open(impl, protocol, ec); - else - ec = boost::asio::error::invalid_argument; - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Assign an existing native socket to a raw socket. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const protocol_type& protocol, const native_handle_type& native_socket, - boost::system::error_code& ec) - { - service_impl_.assign(impl, protocol, native_socket, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a raw socket implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Release ownership of the underlying socket. - native_handle_type release(implementation_type& impl, - boost::system::error_code& ec) - { - return service_impl_.release(impl, ec); - } - - /// Get the native socket implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - // Bind the raw socket to the specified local endpoint. - BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl, - const endpoint_type& endpoint, boost::system::error_code& ec) - { - service_impl_.bind(impl, endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Connect the raw socket to the specified endpoint. - BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl, - const endpoint_type& peer_endpoint, boost::system::error_code& ec) - { - service_impl_.connect(impl, peer_endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Start an asynchronous connect. - template <typename ConnectHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, - void (boost::system::error_code)) - async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, - BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) - { - async_completion<ConnectHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_connect(impl, peer_endpoint, init.completion_handler); - - return init.result.get(); - } - - /// Set a socket option. - template <typename SettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl, - const SettableSocketOption& option, boost::system::error_code& ec) - { - service_impl_.set_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get a socket option. - template <typename GettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl, - GettableSocketOption& option, boost::system::error_code& ec) const - { - service_impl_.get_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Perform an IO control command on the socket. - template <typename IoControlCommand> - BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl, - IoControlCommand& command, boost::system::error_code& ec) - { - service_impl_.io_control(impl, command, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the socket. - bool non_blocking(const implementation_type& impl) const - { - return service_impl_.non_blocking(impl); - } - - /// Sets the non-blocking mode of the socket. - BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the native socket implementation. - bool native_non_blocking(const implementation_type& impl) const - { - return service_impl_.native_non_blocking(impl); - } - - /// Sets the non-blocking mode of the native socket implementation. - BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.native_non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl, - socket_base::shutdown_type what, boost::system::error_code& ec) - { - service_impl_.shutdown(impl, what, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Wait for the socket to become ready to read, ready to write, or to have - /// pending error conditions. - BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl, - socket_base::wait_type w, boost::system::error_code& ec) - { - service_impl_.wait(impl, w, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Asynchronously wait for the socket to become ready to read, ready to - /// write, or to have pending error conditions. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, socket_base::wait_type w, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, w, init.completion_handler); - - return init.result.get(); - } - - /// Send the given data to the peer. - template <typename ConstBufferSequence> - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_send(impl, buffers, flags, init.completion_handler); - - return init.result.get(); - } - - /// Send raw data to the specified endpoint. - template <typename ConstBufferSequence> - std::size_t send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.send_to(impl, buffers, destination, flags, ec); - } - - /// Start an asynchronous send. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_send_to(impl, buffers, - destination, flags, init.completion_handler); - - return init.result.get(); - } - - /// Receive some data from the peer. - template <typename MutableBufferSequence> - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Start an asynchronous receive. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_receive(impl, buffers, flags, init.completion_handler); - - return init.result.get(); - } - - /// Receive raw data with the endpoint of the sender. - template <typename MutableBufferSequence> - std::size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, - ec); - } - - /// Start an asynchronous receive that will get the endpoint of the sender. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_receive_from(impl, buffers, - sender_endpoint, flags, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_RAW_SOCKET_SERVICE_HPP diff --git a/boost/asio/read.hpp b/boost/asio/read.hpp index efa373c3cf..3c4868605b 100644 --- a/boost/asio/read.hpp +++ b/boost/asio/read.hpp @@ -2,7 +2,7 @@ // read.hpp // ~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -224,6 +224,8 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, is_mutable_buffer_sequence<MutableBufferSequence>::value >::type* = 0); +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// Attempt to read a certain amount of data from a stream before returning. /** * This function is used to read a certain number of bytes of data from a @@ -251,11 +253,12 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, * s, buffers, * boost::asio::transfer_all()); @endcode */ -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); /// Attempt to read a certain amount of data from a stream before returning. @@ -284,12 +287,13 @@ std::size_t read(SyncReadStream& s, * s, buffers, * boost::asio::transfer_all(), ec); @endcode */ -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, boost::system::error_code& ec, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); /// Attempt to read a certain amount of data from a stream before returning. @@ -328,13 +332,14 @@ std::size_t read(SyncReadStream& s, * * @throws boost::system::system_error Thrown on failure. */ -template <typename SyncReadStream, typename DynamicBuffer, +template <typename SyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t read(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); /// Attempt to read a certain amount of data from a stream before returning. @@ -374,13 +379,14 @@ std::size_t read(SyncReadStream& s, * @returns The number of bytes read. If an error occurs, returns the total * number of bytes successfully transferred prior to the error. */ -template <typename SyncReadStream, typename DynamicBuffer, +template <typename SyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t read(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, boost::system::error_code& ec, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -528,6 +534,162 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b, #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The specified dynamic buffer sequence is full (that is, it has reached + * maximum size). + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code boost::asio::read( + * s, buffers, + * boost::asio::transfer_all()); @endcode + */ +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The supplied buffer is full (that is, it has reached maximum size). + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes transferred. + * + * @note This overload is equivalent to calling: + * @code boost::asio::read( + * s, buffers, + * boost::asio::transfer_all(), ec); @endcode + */ +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, + boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The specified dynamic buffer sequence is full (that is, it has reached + * maximum size). + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest read_some operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the read operation is complete. A non-zero + * return value indicates the maximum number of bytes to be read on the next + * call to the stream's read_some function. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + */ +template <typename SyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition> +std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The specified dynamic buffer sequence is full (that is, it has reached + * maximum size). + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest read_some operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the read operation is complete. A non-zero + * return value indicates the maximum number of bytes to be read on the next + * call to the stream's read_some function. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template <typename SyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition> +std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); /*@}*/ /** @@ -579,9 +741,9 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b, * // prior to the error. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To read into a single data buffer use the @ref buffer function as follows: @@ -657,9 +819,9 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, * // prior to the error. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To read into a single data buffer use the @ref buffer function as follows: @@ -682,6 +844,8 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, is_mutable_buffer_sequence<MutableBufferSequence>::value >::type* = 0); +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** @@ -722,9 +886,9 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, * // prior to the error. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note This overload is equivalent to calling: * @code boost::asio::async_read( @@ -733,14 +897,15 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, * handler); @endcode */ template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); /// Start an asynchronous operation to read a certain amount of data from a @@ -797,20 +962,21 @@ async_read(AsyncReadStream& s, * // prior to the error. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -854,9 +1020,9 @@ async_read(AsyncReadStream& s, * // prior to the error. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note This overload is equivalent to calling: * @code boost::asio::async_read( @@ -922,9 +1088,9 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, * // prior to the error. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename AsyncReadStream, typename Allocator, typename CompletionCondition, typename ReadHandler> @@ -936,6 +1102,136 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +/// Start an asynchronous operation to read a certain amount of data from a +/// stream. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions is + * true: + * + * @li The specified dynamic buffer sequence is full (that is, it has reached + * maximum size). + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other read operations (such + * as async_read, the stream's async_read_some function, or any other composed + * operations that perform reads) until this operation completes. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes copied into the + * // buffers. If an error occurred, + * // this will be the number of + * // bytes successfully transferred + * // prior to the error. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note This overload is equivalent to calling: + * @code boost::asio::async_read( + * s, buffers, + * boost::asio::transfer_all(), + * handler); @endcode + */ +template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Start an asynchronous operation to read a certain amount of data from a +/// stream. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions is + * true: + * + * @li The specified dynamic buffer sequence is full (that is, it has reached + * maximum size). + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other read operations (such + * as async_read, the stream's async_read_some function, or any other composed + * operations that perform reads) until this operation completes. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest async_read_some operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the read operation is complete. A non-zero + * return value indicates the maximum number of bytes to be read on the next + * call to the stream's async_read_some function. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes copied into the + * // buffers. If an error occurred, + * // this will be the number of + * // bytes successfully transferred + * // prior to the error. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + */ +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); /*@}*/ diff --git a/boost/asio/read_at.hpp b/boost/asio/read_at.hpp index ec6780382b..8319feb196 100644 --- a/boost/asio/read_at.hpp +++ b/boost/asio/read_at.hpp @@ -2,7 +2,7 @@ // read_at.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -440,9 +440,9 @@ std::size_t read_at(SyncRandomAccessReadDevice& d, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To read into a single data buffer use the @ref buffer function as follows: @@ -518,9 +518,9 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To read into a single data buffer use the @ref buffer function as follows: @@ -579,9 +579,9 @@ async_read_at(AsyncRandomAccessReadDevice& d, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note This overload is equivalent to calling: * @code boost::asio::async_read_at( @@ -645,9 +645,9 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename AsyncRandomAccessReadDevice, typename Allocator, typename CompletionCondition, typename ReadHandler> diff --git a/boost/asio/read_until.hpp b/boost/asio/read_until.hpp index f9c1f51323..96ed6a77de 100644 --- a/boost/asio/read_until.hpp +++ b/boost/asio/read_until.hpp @@ -2,7 +2,7 @@ // read_until.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -19,6 +19,7 @@ #include <cstddef> #include <string> #include <boost/asio/async_result.hpp> +#include <boost/asio/buffer.hpp> #include <boost/asio/detail/regex_fwd.hpp> #include <boost/asio/detail/string_view.hpp> #include <boost/asio/detail/type_traits.hpp> @@ -75,6 +76,8 @@ struct is_match_condition */ /*@{*/ +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. /** @@ -128,9 +131,13 @@ struct is_match_condition * This data may be the start of a new line, to be extracted by a subsequent * @c read_until operation. */ -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, char delim); + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -166,10 +173,14 @@ std::size_t read_until(SyncReadStream& s, * typically leave that data in the dynamic buffer sequence for a subsequent * read_until operation to examine. */ -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - char delim, boost::system::error_code& ec); + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + char delim, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -222,10 +233,14 @@ std::size_t read_until(SyncReadStream& s, * This data may be the start of a new line, to be extracted by a subsequent * @c read_until operation. */ -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - BOOST_ASIO_STRING_VIEW_PARAM delim); + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + BOOST_ASIO_STRING_VIEW_PARAM delim, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -261,11 +276,15 @@ std::size_t read_until(SyncReadStream& s, * typically leave that data in the dynamic buffer sequence for a subsequent * read_until operation to examine. */ -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, BOOST_ASIO_STRING_VIEW_PARAM delim, - boost::system::error_code& ec); + boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); #if !defined(BOOST_ASIO_NO_EXTENSIONS) #if defined(BOOST_ASIO_HAS_BOOST_REGEX) \ @@ -325,10 +344,14 @@ std::size_t read_until(SyncReadStream& s, * This data may be the start of a new line, to be extracted by a subsequent * @c read_until operation. */ -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - const boost::regex& expr); + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + const boost::regex& expr, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); /// Read data into a dynamic buffer sequence until some part of the data it /// contains matches a regular expression. @@ -366,10 +389,14 @@ std::size_t read_until(SyncReadStream& s, * expression. An application will typically leave that data in the dynamic * buffer sequence for a subsequent read_until operation to examine. */ -template <typename SyncReadStream, typename DynamicBuffer> +template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - const boost::regex& expr, boost::system::error_code& ec); + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + const boost::regex& expr, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION) @@ -402,7 +429,7 @@ std::size_t read_until(SyncReadStream& s, * @code pair<iterator, bool> match_condition(iterator begin, iterator end); * @endcode * where @c iterator represents the type: - * @code buffers_iterator<typename DynamicBuffer::const_buffers_type> + * @code buffers_iterator<typename DynamicBuffer_v1::const_buffers_type> * @endcode * The iterator parameters @c begin and @c end define the range of bytes to be * scanned to determine whether there is a match. The @c first member of the @@ -477,11 +504,15 @@ std::size_t read_until(SyncReadStream& s, * @endcode */ template <typename SyncReadStream, - typename DynamicBuffer, typename MatchCondition> + typename DynamicBuffer_v1, typename MatchCondition> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition, - typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0); + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); /// Read data into a dynamic buffer sequence until a function object indicates a /// match. @@ -510,7 +541,7 @@ std::size_t read_until(SyncReadStream& s, * @code pair<iterator, bool> match_condition(iterator begin, iterator end); * @endcode * where @c iterator represents the type: - * @code buffers_iterator<DynamicBuffer::const_buffers_type> + * @code buffers_iterator<DynamicBuffer_v1::const_buffers_type> * @endcode * The iterator parameters @c begin and @c end define the range of bytes to be * scanned to determine whether there is a match. The @c first member of the @@ -537,11 +568,15 @@ std::size_t read_until(SyncReadStream& s, * function objects. */ template <typename SyncReadStream, - typename DynamicBuffer, typename MatchCondition> + typename DynamicBuffer_v1, typename MatchCondition> std::size_t read_until(SyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition, boost::system::error_code& ec, - typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0); + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); #if !defined(BOOST_ASIO_NO_IOSTREAM) @@ -982,6 +1017,492 @@ std::size_t read_until(SyncReadStream& s, #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +/// Read data into a dynamic buffer sequence until it contains a specified +/// delimiter. +/** + * This function is used to read data into the specified dynamic buffer + * sequence until the dynamic buffer sequence's get area contains the specified + * delimiter. The call will block until one of the following conditions is + * true: + * + * @li The get area of the dynamic buffer sequence contains the specified + * delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the dynamic buffer sequence's get area already + * contains the delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * + * @param delim The delimiter character. + * + * @returns The number of bytes in the dynamic buffer sequence's get area up to + * and including the delimiter. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note After a successful read_until operation, the dynamic buffer sequence + * may contain additional data beyond the delimiter. An application will + * typically leave that data in the dynamic buffer sequence for a subsequent + * read_until operation to examine. + * + * @par Example + * To read data into a @c std::string until a newline is encountered: + * @code std::string data; + * std::string n = boost::asio::read_until(s, + * boost::asio::dynamic_buffer(data), '\n'); + * std::string line = data.substr(0, n); + * data.erase(0, n); @endcode + * After the @c read_until operation completes successfully, the string @c data + * contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode + * The call to @c substr then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\n' } @endcode + * After the call to @c erase, the remaining data is left in the buffer @c b as + * follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c read_until operation. + */ +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Read data into a dynamic buffer sequence until it contains a specified +/// delimiter. +/** + * This function is used to read data into the specified dynamic buffer + * sequence until the dynamic buffer sequence's get area contains the specified + * delimiter. The call will block until one of the following conditions is + * true: + * + * @li The get area of the dynamic buffer sequence contains the specified + * delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the dynamic buffer sequence's get area already + * contains the delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * + * @param delim The delimiter character. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the dynamic buffer sequence's get area up to + * and including the delimiter. Returns 0 if an error occurred. + * + * @note After a successful read_until operation, the dynamic buffer sequence + * may contain additional data beyond the delimiter. An application will + * typically leave that data in the dynamic buffer sequence for a subsequent + * read_until operation to examine. + */ +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + char delim, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Read data into a dynamic buffer sequence until it contains a specified +/// delimiter. +/** + * This function is used to read data into the specified dynamic buffer + * sequence until the dynamic buffer sequence's get area contains the specified + * delimiter. The call will block until one of the following conditions is + * true: + * + * @li The get area of the dynamic buffer sequence contains the specified + * delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the dynamic buffer sequence's get area already + * contains the delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * + * @param delim The delimiter string. + * + * @returns The number of bytes in the dynamic buffer sequence's get area up to + * and including the delimiter. + * + * @note After a successful read_until operation, the dynamic buffer sequence + * may contain additional data beyond the delimiter. An application will + * typically leave that data in the dynamic buffer sequence for a subsequent + * read_until operation to examine. + * + * @par Example + * To read data into a @c std::string until a CR-LF sequence is encountered: + * @code std::string data; + * std::string n = boost::asio::read_until(s, + * boost::asio::dynamic_buffer(data), "\r\n"); + * std::string line = data.substr(0, n); + * data.erase(0, n); @endcode + * After the @c read_until operation completes successfully, the string @c data + * contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode + * The call to @c substr then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode + * After the call to @c erase, the remaining data is left in the buffer @c b as + * follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c read_until operation. + */ +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + BOOST_ASIO_STRING_VIEW_PARAM delim, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Read data into a dynamic buffer sequence until it contains a specified +/// delimiter. +/** + * This function is used to read data into the specified dynamic buffer + * sequence until the dynamic buffer sequence's get area contains the specified + * delimiter. The call will block until one of the following conditions is + * true: + * + * @li The get area of the dynamic buffer sequence contains the specified + * delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the dynamic buffer sequence's get area already + * contains the delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * + * @param delim The delimiter string. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the dynamic buffer sequence's get area up to + * and including the delimiter. Returns 0 if an error occurred. + * + * @note After a successful read_until operation, the dynamic buffer sequence + * may contain additional data beyond the delimiter. An application will + * typically leave that data in the dynamic buffer sequence for a subsequent + * read_until operation to examine. + */ +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) +#if defined(BOOST_ASIO_HAS_BOOST_REGEX) \ + || defined(GENERATING_DOCUMENTATION) + +/// Read data into a dynamic buffer sequence until some part of the data it +/// contains matches a regular expression. +/** + * This function is used to read data into the specified dynamic buffer + * sequence until the dynamic buffer sequence's get area contains some data + * that matches a regular expression. The call will block until one of the + * following conditions is true: + * + * @li A substring of the dynamic buffer sequence's get area matches the + * regular expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the dynamic buffer sequence's get area already + * contains data that matches the regular expression, the function returns + * immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers A dynamic buffer sequence into which the data will be read. + * + * @param expr The regular expression. + * + * @returns The number of bytes in the dynamic buffer sequence's get area up to + * and including the substring that matches the regular expression. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note After a successful read_until operation, the dynamic buffer sequence + * may contain additional data beyond that which matched the regular + * expression. An application will typically leave that data in the dynamic + * buffer sequence for a subsequent read_until operation to examine. + * + * @par Example + * To read data into a @c std::string until a CR-LF sequence is encountered: + * @code std::string data; + * std::string n = boost::asio::read_until(s, + * boost::asio::dynamic_buffer(data), boost::regex("\r\n")); + * std::string line = data.substr(0, n); + * data.erase(0, n); @endcode + * After the @c read_until operation completes successfully, the string @c data + * contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode + * The call to @c substr then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode + * After the call to @c erase, the remaining data is left in the buffer @c b as + * follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c read_until operation. + */ +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + const boost::regex& expr, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Read data into a dynamic buffer sequence until some part of the data it +/// contains matches a regular expression. +/** + * This function is used to read data into the specified dynamic buffer + * sequence until the dynamic buffer sequence's get area contains some data + * that matches a regular expression. The call will block until one of the + * following conditions is true: + * + * @li A substring of the dynamic buffer sequence's get area matches the + * regular expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the dynamic buffer sequence's get area already + * contains data that matches the regular expression, the function returns + * immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers A dynamic buffer sequence into which the data will be read. + * + * @param expr The regular expression. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the dynamic buffer sequence's get area up to + * and including the substring that matches the regular expression. Returns 0 + * if an error occurred. + * + * @note After a successful read_until operation, the dynamic buffer sequence + * may contain additional data beyond that which matched the regular + * expression. An application will typically leave that data in the dynamic + * buffer sequence for a subsequent read_until operation to examine. + */ +template <typename SyncReadStream, typename DynamicBuffer_v2> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + const boost::regex& expr, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX) + // || defined(GENERATING_DOCUMENTATION) + +/// Read data into a dynamic buffer sequence until a function object indicates a +/// match. + +/** + * This function is used to read data into the specified dynamic buffer + * sequence until a user-defined match condition function object, when applied + * to the data contained in the dynamic buffer sequence, indicates a successful + * match. The call will block until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the match condition function object already indicates + * a match, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers A dynamic buffer sequence into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair<iterator, bool> match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator<typename DynamicBuffer_v2::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @returns The number of bytes in the dynamic_buffer's get area that + * have been fully consumed by the match function. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note After a successful read_until operation, the dynamic buffer sequence + * may contain additional data beyond that which matched the function object. + * An application will typically leave that data in the dynamic buffer sequence + * for a subsequent read_until operation to examine. + + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + * + * @par Examples + * To read data into a dynamic buffer sequence until whitespace is encountered: + * @code typedef boost::asio::buffers_iterator< + * boost::asio::const_buffers_1> iterator; + * + * std::pair<iterator, bool> + * match_whitespace(iterator begin, iterator end) + * { + * iterator i = begin; + * while (i != end) + * if (std::isspace(*i++)) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * ... + * std::string data; + * boost::asio::read_until(s, data, match_whitespace); + * @endcode + * + * To read data into a @c std::string until a matching character is found: + * @code class match_char + * { + * public: + * explicit match_char(char c) : c_(c) {} + * + * template <typename Iterator> + * std::pair<Iterator, bool> operator()( + * Iterator begin, Iterator end) const + * { + * Iterator i = begin; + * while (i != end) + * if (c_ == *i++) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * + * private: + * char c_; + * }; + * + * namespace asio { + * template <> struct is_match_condition<match_char> + * : public boost::true_type {}; + * } // namespace asio + * ... + * std::string data; + * boost::asio::read_until(s, data, match_char('a')); + * @endcode + */ +template <typename SyncReadStream, + typename DynamicBuffer_v2, typename MatchCondition> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + MatchCondition match_condition, + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Read data into a dynamic buffer sequence until a function object indicates a +/// match. +/** + * This function is used to read data into the specified dynamic buffer + * sequence until a user-defined match condition function object, when applied + * to the data contained in the dynamic buffer sequence, indicates a successful + * match. The call will block until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the match condition function object already indicates + * a match, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers A dynamic buffer sequence into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair<iterator, bool> match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator<DynamicBuffer_v2::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the dynamic buffer sequence's get area that + * have been fully consumed by the match function. Returns 0 if an error + * occurred. + * + * @note After a successful read_until operation, the dynamic buffer sequence + * may contain additional data beyond that which matched the function object. + * An application will typically leave that data in the dynamic buffer sequence + * for a subsequent read_until operation to examine. + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + */ +template <typename SyncReadStream, + typename DynamicBuffer_v2, typename MatchCondition> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + MatchCondition match_condition, boost::system::error_code& ec, + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) /*@}*/ /** @@ -994,6 +1515,8 @@ std::size_t read_until(SyncReadStream& s, */ /*@{*/ +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// Start an asynchronous operation to read data into a dynamic buffer sequence /// until it contains a specified delimiter. /** @@ -1039,9 +1562,9 @@ std::size_t read_until(SyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application @@ -1077,12 +1600,16 @@ std::size_t read_until(SyncReadStream& s, * @c async_read_until operation. */ template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read_until(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, - char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler); + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); /// Start an asynchronous operation to read data into a dynamic buffer sequence /// until it contains a specified delimiter. @@ -1129,9 +1656,9 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application @@ -1167,13 +1694,17 @@ async_read_until(AsyncReadStream& s, * @c async_read_until operation. */ template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read_until(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, BOOST_ASIO_STRING_VIEW_PARAM delim, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler); + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); #if !defined(BOOST_ASIO_NO_EXTENSIONS) #if defined(BOOST_ASIO_HAS_BOOST_REGEX) \ @@ -1226,9 +1757,9 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond that which matched the regular @@ -1265,13 +1796,17 @@ async_read_until(AsyncReadStream& s, * @c async_read_until operation. */ template <typename AsyncReadStream, - typename DynamicBuffer, typename ReadHandler> + typename DynamicBuffer_v1, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read_until(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const boost::regex& expr, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler); + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION) @@ -1312,7 +1847,7 @@ async_read_until(AsyncReadStream& s, * @code pair<iterator, bool> match_condition(iterator begin, iterator end); * @endcode * where @c iterator represents the type: - * @code buffers_iterator<typename DynamicBuffer::const_buffers_type> + * @code buffers_iterator<typename DynamicBuffer_v1::const_buffers_type> * @endcode * The iterator parameters @c begin and @c end define the range of bytes to be * scanned to determine whether there is a match. The @c first member of the @@ -1335,9 +1870,9 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond that which matched the function @@ -1404,14 +1939,18 @@ async_read_until(AsyncReadStream& s, * boost::asio::async_read_until(s, data, match_char('a'), handler); * @endcode */ -template <typename AsyncReadStream, typename DynamicBuffer, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (boost::system::error_code, std::size_t)) async_read_until(AsyncReadStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, - typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0); + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value + >::type* = 0); #if !defined(BOOST_ASIO_NO_IOSTREAM) @@ -1457,9 +1996,9 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond the delimiter. An application will typically @@ -1542,9 +2081,9 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond the delimiter. An application will typically @@ -1634,9 +2173,9 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond that which matched the regular expression. An @@ -1736,9 +2275,9 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond that which matched the function object. An @@ -1815,6 +2354,436 @@ async_read_until(AsyncReadStream& s, #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +/// Start an asynchronous operation to read data into a dynamic buffer sequence +/// until it contains a specified delimiter. +/** + * This function is used to asynchronously read data into the specified dynamic + * buffer sequence until the dynamic buffer sequence's get area contains the + * specified delimiter. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li The get area of the dynamic buffer sequence contains the specified + * delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function, and is known as a <em>composed operation</em>. If + * the dynamic buffer sequence's get area already contains the delimiter, this + * asynchronous operation completes immediately. The program must ensure that + * the stream performs no other read operations (such as async_read, + * async_read_until, the stream's async_read_some function, or any other + * composed operations that perform reads) until this operation completes. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param delim The delimiter character. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the dynamic buffer sequence's + * // get area up to and including the delimiter. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note After a successful async_read_until operation, the dynamic buffer + * sequence may contain additional data beyond the delimiter. An application + * will typically leave that data in the dynamic buffer sequence for a + * subsequent async_read_until operation to examine. + * + * @par Example + * To asynchronously read data into a @c std::string until a newline is + * encountered: + * @code std::string data; + * ... + * void handler(const boost::system::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::string line = data.substr(0, n); + * data.erase(0, n); + * ... + * } + * } + * ... + * boost::asio::async_read_until(s, data, '\n', handler); @endcode + * After the @c async_read_until operation completes successfully, the buffer + * @c data contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode + * The call to @c substr then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\n' } @endcode + * After the call to @c erase, the remaining data is left in the buffer @c data + * as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c async_read_until operation. + */ +template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Start an asynchronous operation to read data into a dynamic buffer sequence +/// until it contains a specified delimiter. +/** + * This function is used to asynchronously read data into the specified dynamic + * buffer sequence until the dynamic buffer sequence's get area contains the + * specified delimiter. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li The get area of the dynamic buffer sequence contains the specified + * delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function, and is known as a <em>composed operation</em>. If + * the dynamic buffer sequence's get area already contains the delimiter, this + * asynchronous operation completes immediately. The program must ensure that + * the stream performs no other read operations (such as async_read, + * async_read_until, the stream's async_read_some function, or any other + * composed operations that perform reads) until this operation completes. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param delim The delimiter string. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the dynamic buffer sequence's + * // get area up to and including the delimiter. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note After a successful async_read_until operation, the dynamic buffer + * sequence may contain additional data beyond the delimiter. An application + * will typically leave that data in the dynamic buffer sequence for a + * subsequent async_read_until operation to examine. + * + * @par Example + * To asynchronously read data into a @c std::string until a CR-LF sequence is + * encountered: + * @code std::string data; + * ... + * void handler(const boost::system::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::string line = data.substr(0, n); + * data.erase(0, n); + * ... + * } + * } + * ... + * boost::asio::async_read_until(s, data, "\r\n", handler); @endcode + * After the @c async_read_until operation completes successfully, the string + * @c data contains the delimiter: + * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode + * The call to @c substr then extracts the data up to and including the + * delimiter, so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode + * After the call to @c erase, the remaining data is left in the string @c data + * as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c async_read_until operation. + */ +template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + BOOST_ASIO_STRING_VIEW_PARAM delim, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +#if !defined(BOOST_ASIO_NO_EXTENSIONS) +#if defined(BOOST_ASIO_HAS_BOOST_REGEX) \ + || defined(GENERATING_DOCUMENTATION) + +/// Start an asynchronous operation to read data into a dynamic buffer sequence +/// until some part of its data matches a regular expression. +/** + * This function is used to asynchronously read data into the specified dynamic + * buffer sequence until the dynamic buffer sequence's get area contains some + * data that matches a regular expression. The function call always returns + * immediately. The asynchronous operation will continue until one of the + * following conditions is true: + * + * @li A substring of the dynamic buffer sequence's get area matches the regular + * expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function, and is known as a <em>composed operation</em>. If + * the dynamic buffer sequence's get area already contains data that matches + * the regular expression, this asynchronous operation completes immediately. + * The program must ensure that the stream performs no other read operations + * (such as async_read, async_read_until, the stream's async_read_some + * function, or any other composed operations that perform reads) until this + * operation completes. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param expr The regular expression. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the dynamic buffer + * // sequence's get area up to and including the + * // substring that matches the regular expression. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note After a successful async_read_until operation, the dynamic buffer + * sequence may contain additional data beyond that which matched the regular + * expression. An application will typically leave that data in the dynamic + * buffer sequence for a subsequent async_read_until operation to examine. + * + * @par Example + * To asynchronously read data into a @c std::string until a CR-LF sequence is + * encountered: + * @code std::string data; + * ... + * void handler(const boost::system::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::string line = data.substr(0, n); + * data.erase(0, n); + * ... + * } + * } + * ... + * boost::asio::async_read_until(s, data, + * boost::regex("\r\n"), handler); @endcode + * After the @c async_read_until operation completes successfully, the string + * @c data contains the data which matched the regular expression: + * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode + * The call to @c substr then extracts the data up to and including the match, + * so that the string @c line contains: + * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode + * After the call to @c erase, the remaining data is left in the string @c data + * as follows: + * @code { 'd', 'e', ... } @endcode + * This data may be the start of a new line, to be extracted by a subsequent + * @c async_read_until operation. + */ +template <typename AsyncReadStream, + typename DynamicBuffer_v2, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + const boost::regex& expr, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX) + // || defined(GENERATING_DOCUMENTATION) + +/// Start an asynchronous operation to read data into a dynamic buffer sequence +/// until a function object indicates a match. +/** + * This function is used to asynchronously read data into the specified dynamic + * buffer sequence until a user-defined match condition function object, when + * applied to the data contained in the dynamic buffer sequence, indicates a + * successful match. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function, and is known as a <em>composed operation</em>. If + * the match condition function object already indicates a match, this + * asynchronous operation completes immediately. The program must ensure that + * the stream performs no other read operations (such as async_read, + * async_read_until, the stream's async_read_some function, or any other + * composed operations that perform reads) until this operation completes. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers The dynamic buffer sequence into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair<iterator, bool> match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator<typename DynamicBuffer_v2::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the dynamic buffer sequence's + * // get area that have been fully consumed by the match + * // function. O if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + * + * @note After a successful async_read_until operation, the dynamic buffer + * sequence may contain additional data beyond that which matched the function + * object. An application will typically leave that data in the dynamic buffer + * sequence for a subsequent async_read_until operation to examine. + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + * + * @par Examples + * To asynchronously read data into a @c std::string until whitespace is + * encountered: + * @code typedef boost::asio::buffers_iterator< + * boost::asio::const_buffers_1> iterator; + * + * std::pair<iterator, bool> + * match_whitespace(iterator begin, iterator end) + * { + * iterator i = begin; + * while (i != end) + * if (std::isspace(*i++)) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * ... + * void handler(const boost::system::error_code& e, std::size_t size); + * ... + * std::string data; + * boost::asio::async_read_until(s, data, match_whitespace, handler); + * @endcode + * + * To asynchronously read data into a @c std::string until a matching character + * is found: + * @code class match_char + * { + * public: + * explicit match_char(char c) : c_(c) {} + * + * template <typename Iterator> + * std::pair<Iterator, bool> operator()( + * Iterator begin, Iterator end) const + * { + * Iterator i = begin; + * while (i != end) + * if (c_ == *i++) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * + * private: + * char c_; + * }; + * + * namespace asio { + * template <> struct is_match_condition<match_char> + * : public boost::true_type {}; + * } // namespace asio + * ... + * void handler(const boost::system::error_code& e, std::size_t size); + * ... + * std::string data; + * boost::asio::async_read_until(s, data, match_char('a'), handler); + * @endcode + */ +template <typename AsyncReadStream, typename DynamicBuffer_v2, + typename MatchCondition, typename ReadHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) +async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler, + typename enable_if< + is_match_condition<MatchCondition>::value + && is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +#endif // !defined(BOOST_ASIO_NO_EXTENSIONS) /*@}*/ diff --git a/boost/asio/experimental/redirect_error.hpp b/boost/asio/redirect_error.hpp index a138854521..f4563a5931 100644 --- a/boost/asio/experimental/redirect_error.hpp +++ b/boost/asio/redirect_error.hpp @@ -1,15 +1,15 @@ // -// experimental/redirect_error.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// redirect_error.hpp +// ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef BOOST_ASIO_EXPERIMENTAL_REDIRECT_ERROR_HPP -#define BOOST_ASIO_EXPERIMENTAL_REDIRECT_ERROR_HPP +#ifndef BOOST_ASIO_REDIRECT_ERROR_HPP +#define BOOST_ASIO_REDIRECT_ERROR_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -23,7 +23,6 @@ namespace boost { namespace asio { -namespace experimental { /// Completion token type used to specify that an error produced by an /// asynchronous operation is captured to an error_code variable. @@ -52,18 +51,18 @@ public: /// Create a completion token to capture error_code values to a variable. template <typename CompletionToken> inline redirect_error_t<typename decay<CompletionToken>::type> redirect_error( - CompletionToken&& completion_token, boost::system::error_code& ec) + BOOST_ASIO_MOVE_ARG(CompletionToken) completion_token, + boost::system::error_code& ec) { return redirect_error_t<typename decay<CompletionToken>::type>( BOOST_ASIO_MOVE_CAST(CompletionToken)(completion_token), ec); } -} // namespace experimental } // namespace asio } // namespace boost #include <boost/asio/detail/pop_options.hpp> -#include <boost/asio/experimental/impl/redirect_error.hpp> +#include <boost/asio/impl/redirect_error.hpp> -#endif // BOOST_ASIO_EXPERIMENTAL_REDIRECT_ERROR_HPP +#endif // BOOST_ASIO_REDIRECT_ERROR_HPP diff --git a/boost/asio/seq_packet_socket_service.hpp b/boost/asio/seq_packet_socket_service.hpp deleted file mode 100644 index d6445782b3..0000000000 --- a/boost/asio/seq_packet_socket_service.hpp +++ /dev/null @@ -1,418 +0,0 @@ -// -// seq_packet_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP -#define BOOST_ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/type_traits.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/null_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_socket_service.hpp> -#else -# include <boost/asio/detail/reactive_socket_service.hpp> -#endif - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a sequenced packet socket. -template <typename Protocol> -class seq_packet_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base< - seq_packet_socket_service<Protocol> > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) - typedef detail::null_socket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#else - typedef detail::reactive_socket_service<Protocol> service_impl_type; -#endif - -public: - /// The type of a sequenced packet socket implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef typename service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new sequenced packet socket service for the specified - /// io_context. - explicit seq_packet_socket_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - seq_packet_socket_service<Protocol> >(io_context), - service_impl_(io_context) - { - } - - /// Construct a new sequenced packet socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new sequenced packet socket implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another sequenced packet socket implementation. - void move_assign(implementation_type& impl, - seq_packet_socket_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } - - // All socket services have access to each other's implementations. - template <typename Protocol1> friend class seq_packet_socket_service; - - /// Move-construct a new sequenced packet socket implementation from another - /// protocol type. - template <typename Protocol1> - void converting_move_construct(implementation_type& impl, - seq_packet_socket_service<Protocol1>& other_service, - typename seq_packet_socket_service< - Protocol1>::implementation_type& other_impl, - typename enable_if<is_convertible< - Protocol1, Protocol>::value>::type* = 0) - { - service_impl_.template converting_move_construct<Protocol1>( - impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a sequenced packet socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a sequenced packet socket. - BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl, - const protocol_type& protocol, boost::system::error_code& ec) - { - if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_SEQPACKET)) - service_impl_.open(impl, protocol, ec); - else - ec = boost::asio::error::invalid_argument; - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Assign an existing native socket to a sequenced packet socket. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const protocol_type& protocol, const native_handle_type& native_socket, - boost::system::error_code& ec) - { - service_impl_.assign(impl, protocol, native_socket, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a sequenced packet socket implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Release ownership of the underlying socket. - native_handle_type release(implementation_type& impl, - boost::system::error_code& ec) - { - return service_impl_.release(impl, ec); - } - - /// Get the native socket implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - /// Bind the sequenced packet socket to the specified local endpoint. - BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl, - const endpoint_type& endpoint, boost::system::error_code& ec) - { - service_impl_.bind(impl, endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Connect the sequenced packet socket to the specified endpoint. - BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl, - const endpoint_type& peer_endpoint, boost::system::error_code& ec) - { - service_impl_.connect(impl, peer_endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Start an asynchronous connect. - template <typename ConnectHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, - void (boost::system::error_code)) - async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, - BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) - { - async_completion<ConnectHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_connect(impl, peer_endpoint, init.completion_handler); - - return init.result.get(); - } - - /// Set a socket option. - template <typename SettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl, - const SettableSocketOption& option, boost::system::error_code& ec) - { - service_impl_.set_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get a socket option. - template <typename GettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl, - GettableSocketOption& option, boost::system::error_code& ec) const - { - service_impl_.get_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Perform an IO control command on the socket. - template <typename IoControlCommand> - BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl, - IoControlCommand& command, boost::system::error_code& ec) - { - service_impl_.io_control(impl, command, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the socket. - bool non_blocking(const implementation_type& impl) const - { - return service_impl_.non_blocking(impl); - } - - /// Sets the non-blocking mode of the socket. - BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the native socket implementation. - bool native_non_blocking(const implementation_type& impl) const - { - return service_impl_.native_non_blocking(impl); - } - - /// Sets the non-blocking mode of the native socket implementation. - BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.native_non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl, - socket_base::shutdown_type what, boost::system::error_code& ec) - { - service_impl_.shutdown(impl, what, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Wait for the socket to become ready to read, ready to write, or to have - /// pending error conditions. - BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl, - socket_base::wait_type w, boost::system::error_code& ec) - { - service_impl_.wait(impl, w, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Asynchronously wait for the socket to become ready to read, ready to - /// write, or to have pending error conditions. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, socket_base::wait_type w, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, w, init.completion_handler); - - return init.result.get(); - } - - /// Send the given data to the peer. - template <typename ConstBufferSequence> - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_send(impl, buffers, flags, init.completion_handler); - - return init.result.get(); - } - - /// Receive some data from the peer. - template <typename MutableBufferSequence> - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, boost::system::error_code& ec) - { - return service_impl_.receive_with_flags(impl, - buffers, in_flags, out_flags, ec); - } - - /// Start an asynchronous receive. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, socket_base::message_flags in_flags, - socket_base::message_flags& out_flags, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_receive_with_flags(impl, - buffers, in_flags, out_flags, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP diff --git a/boost/asio/serial_port.hpp b/boost/asio/serial_port.hpp index f2185b8037..b0960d8934 100644 --- a/boost/asio/serial_port.hpp +++ b/boost/asio/serial_port.hpp @@ -2,7 +2,7 @@ // serial_port.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -21,750 +21,17 @@ #if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ || defined(GENERATING_DOCUMENTATION) -#include <string> -#include <boost/asio/async_result.hpp> -#include <boost/asio/basic_io_object.hpp> -#include <boost/asio/detail/handler_type_requirements.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> -#include <boost/asio/serial_port_base.hpp> - -#if defined(BOOST_ASIO_HAS_MOVE) -# include <utility> -#endif // defined(BOOST_ASIO_HAS_MOVE) - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/basic_serial_port.hpp> -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# if defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_serial_port_service.hpp> -# define BOOST_ASIO_SVC_T detail::win_iocp_serial_port_service -# else -# include <boost/asio/detail/reactive_serial_port_service.hpp> -# define BOOST_ASIO_SVC_T detail::reactive_serial_port_service -# endif -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <boost/asio/detail/push_options.hpp> +#include <boost/asio/basic_serial_port.hpp> namespace boost { namespace asio { -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -// Typedef for the typical usage of a serial port. +/// Typedef for the typical usage of a serial port. typedef basic_serial_port<> serial_port; -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -/// Provides serial port functionality. -/** - * The serial_port class provides a wrapper over serial port functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class serial_port - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>, - public serial_port_base -{ -public: - /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; - - /// The native representation of a serial port. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type; -#endif - - /// A basic_serial_port is always the lowest layer. - typedef serial_port lowest_layer_type; - - /// Construct a serial_port without opening it. - /** - * This constructor creates a serial port without opening it. - * - * @param io_context The io_context object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. - */ - explicit serial_port(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - } - - /// Construct and open a serial_port. - /** - * This constructor creates and opens a serial port for the specified device - * name. - * - * @param io_context The io_context object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. - * - * @param device The platform-specific device name for this serial - * port. - */ - explicit serial_port(boost::asio::io_context& io_context, - const char* device) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - boost::system::error_code ec; - this->get_service().open(this->get_implementation(), device, ec); - boost::asio::detail::throw_error(ec, "open"); - } - - /// Construct and open a serial_port. - /** - * This constructor creates and opens a serial port for the specified device - * name. - * - * @param io_context The io_context object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. - * - * @param device The platform-specific device name for this serial - * port. - */ - explicit serial_port(boost::asio::io_context& io_context, - const std::string& device) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - boost::system::error_code ec; - this->get_service().open(this->get_implementation(), device, ec); - boost::asio::detail::throw_error(ec, "open"); - } - - /// Construct a serial_port on an existing native serial port. - /** - * This constructor creates a serial port object to hold an existing native - * serial port. - * - * @param io_context The io_context object that the serial port will use to - * dispatch handlers for any asynchronous operations performed on the port. - * - * @param native_serial_port A native serial port. - * - * @throws boost::system::system_error Thrown on failure. - */ - serial_port(boost::asio::io_context& io_context, - const native_handle_type& native_serial_port) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), - native_serial_port, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a serial_port from another. - /** - * This constructor moves a serial port from one object to another. - * - * @param other The other serial_port object from which the move will - * occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c serial_port(io_context&) constructor. - */ - serial_port(serial_port&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) - { - } - - /// Move-assign a serial_port from another. - /** - * This assignment operator moves a serial port from one object to another. - * - * @param other The other serial_port object from which the move will - * occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c serial_port(io_context&) constructor. - */ - serial_port& operator=(serial_port&& other) - { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); - return *this; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroys the serial port. - /** - * This function destroys the serial port, cancelling any outstanding - * asynchronous wait operations associated with the serial port as if by - * calling @c cancel. - */ - ~serial_port() - { - } - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - - /// Get the executor associated with the object. - executor_type get_executor() BOOST_ASIO_NOEXCEPT - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since a serial_port cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Get a const reference to the lowest layer. - /** - * This function returns a const reference to the lowest layer in a stack of - * layers. Since a serial_port cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A const reference to the lowest layer in the stack of layers. - * Ownership is not transferred to the caller. - */ - const lowest_layer_type& lowest_layer() const - { - return *this; - } - - /// Open the serial port using the specified device name. - /** - * This function opens the serial port for the specified device name. - * - * @param device The platform-specific device name. - * - * @throws boost::system::system_error Thrown on failure. - */ - void open(const std::string& device) - { - boost::system::error_code ec; - this->get_service().open(this->get_implementation(), device, ec); - boost::asio::detail::throw_error(ec, "open"); - } - - /// Open the serial port using the specified device name. - /** - * This function opens the serial port using the given platform-specific - * device name. - * - * @param device The platform-specific device name. - * - * @param ec Set the indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID open(const std::string& device, - boost::system::error_code& ec) - { - this->get_service().open(this->get_implementation(), device, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Assign an existing native serial port to the serial port. - /* - * This function opens the serial port to hold an existing native serial port. - * - * @param native_serial_port A native serial port. - * - * @throws boost::system::system_error Thrown on failure. - */ - void assign(const native_handle_type& native_serial_port) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), - native_serial_port, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - - /// Assign an existing native serial port to the serial port. - /* - * This function opens the serial port to hold an existing native serial port. - * - * @param native_serial_port A native serial port. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port, - boost::system::error_code& ec) - { - this->get_service().assign(this->get_implementation(), - native_serial_port, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the serial port is open. - bool is_open() const - { - return this->get_service().is_open(this->get_implementation()); - } - - /// Close the serial port. - /** - * This function is used to close the serial port. Any asynchronous read or - * write operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void close() - { - boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "close"); - } - - /// Close the serial port. - /** - * This function is used to close the serial port. Any asynchronous read or - * write operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) - { - this->get_service().close(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native serial port representation. - /** - * This function may be used to obtain the underlying representation of the - * serial port. This is intended to allow access to native serial port - * functionality that is not otherwise provided. - */ - native_handle_type native_handle() - { - return this->get_service().native_handle(this->get_implementation()); - } - - /// Cancel all asynchronous operations associated with the serial port. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void cancel() - { - boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "cancel"); - } - - /// Cancel all asynchronous operations associated with the serial port. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) - { - this->get_service().cancel(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Send a break sequence to the serial port. - /** - * This function causes a break sequence of platform-specific duration to be - * sent out the serial port. - * - * @throws boost::system::system_error Thrown on failure. - */ - void send_break() - { - boost::system::error_code ec; - this->get_service().send_break(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "send_break"); - } - - /// Send a break sequence to the serial port. - /** - * This function causes a break sequence of platform-specific duration to be - * sent out the serial port. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID send_break(boost::system::error_code& ec) - { - this->get_service().send_break(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Set an option on the serial port. - /** - * This function is used to set an option on the serial port. - * - * @param option The option value to be set on the serial port. - * - * @throws boost::system::system_error Thrown on failure. - * - * @sa SettableSerialPortOption @n - * boost::asio::serial_port_base::baud_rate @n - * boost::asio::serial_port_base::flow_control @n - * boost::asio::serial_port_base::parity @n - * boost::asio::serial_port_base::stop_bits @n - * boost::asio::serial_port_base::character_size - */ - template <typename SettableSerialPortOption> - void set_option(const SettableSerialPortOption& option) - { - boost::system::error_code ec; - this->get_service().set_option(this->get_implementation(), option, ec); - boost::asio::detail::throw_error(ec, "set_option"); - } - - /// Set an option on the serial port. - /** - * This function is used to set an option on the serial port. - * - * @param option The option value to be set on the serial port. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa SettableSerialPortOption @n - * boost::asio::serial_port_base::baud_rate @n - * boost::asio::serial_port_base::flow_control @n - * boost::asio::serial_port_base::parity @n - * boost::asio::serial_port_base::stop_bits @n - * boost::asio::serial_port_base::character_size - */ - template <typename SettableSerialPortOption> - BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option, - boost::system::error_code& ec) - { - this->get_service().set_option(this->get_implementation(), option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get an option from the serial port. - /** - * This function is used to get the current value of an option on the serial - * port. - * - * @param option The option value to be obtained from the serial port. - * - * @throws boost::system::system_error Thrown on failure. - * - * @sa GettableSerialPortOption @n - * boost::asio::serial_port_base::baud_rate @n - * boost::asio::serial_port_base::flow_control @n - * boost::asio::serial_port_base::parity @n - * boost::asio::serial_port_base::stop_bits @n - * boost::asio::serial_port_base::character_size - */ - template <typename GettableSerialPortOption> - void get_option(GettableSerialPortOption& option) - { - boost::system::error_code ec; - this->get_service().get_option(this->get_implementation(), option, ec); - boost::asio::detail::throw_error(ec, "get_option"); - } - - /// Get an option from the serial port. - /** - * This function is used to get the current value of an option on the serial - * port. - * - * @param option The option value to be obtained from the serial port. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa GettableSerialPortOption @n - * boost::asio::serial_port_base::baud_rate @n - * boost::asio::serial_port_base::flow_control @n - * boost::asio::serial_port_base::parity @n - * boost::asio::serial_port_base::stop_bits @n - * boost::asio::serial_port_base::character_size - */ - template <typename GettableSerialPortOption> - BOOST_ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option, - boost::system::error_code& ec) - { - this->get_service().get_option(this->get_implementation(), option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Write some data to the serial port. - /** - * This function is used to write data to the serial port. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the serial port. - * - * @returns The number of bytes written. - * - * @throws boost::system::system_error Thrown on failure. An error code of - * boost::asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * serial_port.write_some(boost::asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename ConstBufferSequence> - std::size_t write_some(const ConstBufferSequence& buffers) - { - boost::system::error_code ec; - std::size_t s = this->get_service().write_some( - this->get_implementation(), buffers, ec); - boost::asio::detail::throw_error(ec, "write_some"); - return s; - } - - /// Write some data to the serial port. - /** - * This function is used to write data to the serial port. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the serial port. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template <typename ConstBufferSequence> - std::size_t write_some(const ConstBufferSequence& buffers, - boost::system::error_code& ec) - { - return this->get_service().write_some( - this->get_implementation(), buffers, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write data to the serial port. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be written to the serial port. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * serial_port.async_write_some(boost::asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_write_some( - this->get_implementation(), buffers, init.completion_handler); - - return init.result.get(); - } - - /// Read some data from the serial port. - /** - * This function is used to read data from the serial port. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws boost::system::system_error Thrown on failure. An error code of - * boost::asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * serial_port.read_some(boost::asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename MutableBufferSequence> - std::size_t read_some(const MutableBufferSequence& buffers) - { - boost::system::error_code ec; - std::size_t s = this->get_service().read_some( - this->get_implementation(), buffers, ec); - boost::asio::detail::throw_error(ec, "read_some"); - return s; - } - - /// Read some data from the serial port. - /** - * This function is used to read data from the serial port. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template <typename MutableBufferSequence> - std::size_t read_some(const MutableBufferSequence& buffers, - boost::system::error_code& ec) - { - return this->get_service().read_some( - this->get_implementation(), buffers, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read data from the serial port. - * The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read function if you need to ensure that the - * requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * serial_port.async_read_some(boost::asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_read_some( - this->get_implementation(), buffers, init.completion_handler); - - return init.result.get(); - } -}; -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } // namespace asio } // namespace boost -#include <boost/asio/detail/pop_options.hpp> - -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# undef BOOST_ASIO_SVC_T -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) // || defined(GENERATING_DOCUMENTATION) diff --git a/boost/asio/serial_port_base.hpp b/boost/asio/serial_port_base.hpp index 3b8c4951f3..f902af1ebe 100644 --- a/boost/asio/serial_port_base.hpp +++ b/boost/asio/serial_port_base.hpp @@ -2,7 +2,7 @@ // serial_port_base.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/boost/asio/serial_port_service.hpp b/boost/asio/serial_port_service.hpp deleted file mode 100644 index 935f92fffa..0000000000 --- a/boost/asio/serial_port_service.hpp +++ /dev/null @@ -1,251 +0,0 @@ -// -// serial_port_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_SERIAL_PORT_SERVICE_HPP -#define BOOST_ASIO_SERIAL_PORT_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ - || defined(GENERATING_DOCUMENTATION) - -#include <cstddef> -#include <string> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/reactive_serial_port_service.hpp> -#include <boost/asio/detail/win_iocp_serial_port_service.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> -#include <boost/asio/serial_port_base.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a serial port. -class serial_port_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<serial_port_service> -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - -private: - // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_HAS_IOCP) - typedef detail::win_iocp_serial_port_service service_impl_type; -#else - typedef detail::reactive_serial_port_service service_impl_type; -#endif - -public: - /// The type of a serial port implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native handle type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new serial port service for the specified io_context. - explicit serial_port_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base<serial_port_service>(io_context), - service_impl_(io_context) - { - } - - /// Construct a new serial port implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new serial port implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another serial port implementation. - void move_assign(implementation_type& impl, - serial_port_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a serial port implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a serial port. - BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl, - const std::string& device, boost::system::error_code& ec) - { - service_impl_.open(impl, device, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Assign an existing native handle to a serial port. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const native_handle_type& handle, boost::system::error_code& ec) - { - service_impl_.assign(impl, handle, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a serial port implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native handle implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Cancel all asynchronous operations associated with the handle. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Set a serial port option. - template <typename SettableSerialPortOption> - BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl, - const SettableSerialPortOption& option, boost::system::error_code& ec) - { - service_impl_.set_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get a serial port option. - template <typename GettableSerialPortOption> - BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl, - GettableSerialPortOption& option, boost::system::error_code& ec) const - { - service_impl_.get_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Send a break sequence to the serial port. - BOOST_ASIO_SYNC_OP_VOID send_break(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.send_break(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Write the given data to the stream. - template <typename ConstBufferSequence> - std::size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, boost::system::error_code& ec) - { - return service_impl_.write_some(impl, buffers, ec); - } - - /// Start an asynchronous write. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_write_some(impl, buffers, init.completion_handler); - - return init.result.get(); - } - - /// Read some data from the stream. - template <typename MutableBufferSequence> - std::size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, boost::system::error_code& ec) - { - return service_impl_.read_some(impl, buffers, ec); - } - - /// Start an asynchronous read. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_read_some(impl, buffers, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) - // || defined(GENERATING_DOCUMENTATION) - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_SERIAL_PORT_SERVICE_HPP diff --git a/boost/asio/signal_set.hpp b/boost/asio/signal_set.hpp index 0ddb996a58..29cfd1b3e5 100644 --- a/boost/asio/signal_set.hpp +++ b/boost/asio/signal_set.hpp @@ -2,7 +2,7 @@ // signal_set.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -16,432 +16,13 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> - -#include <boost/asio/async_result.hpp> -#include <boost/asio/basic_io_object.hpp> -#include <boost/asio/detail/handler_type_requirements.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/basic_signal_set.hpp> -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/detail/signal_set_service.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +#include <boost/asio/basic_signal_set.hpp> namespace boost { namespace asio { -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -// Typedef for the typical usage of a signal set. +/// Typedef for the typical usage of a signal set. typedef basic_signal_set<> signal_set; -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -/// Provides signal functionality. -/** - * The signal_set class provides the ability to perform an asynchronous wait - * for one or more signals to occur. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Example - * Performing an asynchronous wait: - * @code - * void handler( - * const boost::system::error_code& error, - * int signal_number) - * { - * if (!error) - * { - * // A signal occurred. - * } - * } - * - * ... - * - * // Construct a signal set registered for process termination. - * boost::asio::signal_set signals(io_context, SIGINT, SIGTERM); - * - * // Start an asynchronous wait for one of the signals to occur. - * signals.async_wait(handler); - * @endcode - * - * @par Queueing of signal notifications - * - * If a signal is registered with a signal_set, and the signal occurs when - * there are no waiting handlers, then the signal notification is queued. The - * next async_wait operation on that signal_set will dequeue the notification. - * If multiple notifications are queued, subsequent async_wait operations - * dequeue them one at a time. Signal notifications are dequeued in order of - * ascending signal number. - * - * If a signal number is removed from a signal_set (using the @c remove or @c - * erase member functions) then any queued notifications for that signal are - * discarded. - * - * @par Multiple registration of signals - * - * The same signal number may be registered with different signal_set objects. - * When the signal occurs, one handler is called for each signal_set object. - * - * Note that multiple registration only works for signals that are registered - * using Asio. The application must not also register a signal handler using - * functions such as @c signal() or @c sigaction(). - * - * @par Signal masking on POSIX platforms - * - * POSIX allows signals to be blocked using functions such as @c sigprocmask() - * and @c pthread_sigmask(). For signals to be delivered, programs must ensure - * that any signals registered using signal_set objects are unblocked in at - * least one thread. - */ -class signal_set - : BOOST_ASIO_SVC_ACCESS basic_io_object<detail::signal_set_service> -{ -public: - /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; - - /// Construct a signal set without adding any signals. - /** - * This constructor creates a signal set without registering for any signals. - * - * @param io_context The io_context object that the signal set will use to - * dispatch handlers for any asynchronous operations performed on the set. - */ - explicit signal_set(boost::asio::io_context& io_context) - : basic_io_object<detail::signal_set_service>(io_context) - { - } - - /// Construct a signal set and add one signal. - /** - * This constructor creates a signal set and registers for one signal. - * - * @param io_context The io_context object that the signal set will use to - * dispatch handlers for any asynchronous operations performed on the set. - * - * @param signal_number_1 The signal number to be added. - * - * @note This constructor is equivalent to performing: - * @code boost::asio::signal_set signals(io_context); - * signals.add(signal_number_1); @endcode - */ - signal_set(boost::asio::io_context& io_context, int signal_number_1) - : basic_io_object<detail::signal_set_service>(io_context) - { - boost::system::error_code ec; - this->get_service().add(this->get_implementation(), signal_number_1, ec); - boost::asio::detail::throw_error(ec, "add"); - } - - /// Construct a signal set and add two signals. - /** - * This constructor creates a signal set and registers for two signals. - * - * @param io_context The io_context object that the signal set will use to - * dispatch handlers for any asynchronous operations performed on the set. - * - * @param signal_number_1 The first signal number to be added. - * - * @param signal_number_2 The second signal number to be added. - * - * @note This constructor is equivalent to performing: - * @code boost::asio::signal_set signals(io_context); - * signals.add(signal_number_1); - * signals.add(signal_number_2); @endcode - */ - signal_set(boost::asio::io_context& io_context, int signal_number_1, - int signal_number_2) - : basic_io_object<detail::signal_set_service>(io_context) - { - boost::system::error_code ec; - this->get_service().add(this->get_implementation(), signal_number_1, ec); - boost::asio::detail::throw_error(ec, "add"); - this->get_service().add(this->get_implementation(), signal_number_2, ec); - boost::asio::detail::throw_error(ec, "add"); - } - - /// Construct a signal set and add three signals. - /** - * This constructor creates a signal set and registers for three signals. - * - * @param io_context The io_context object that the signal set will use to - * dispatch handlers for any asynchronous operations performed on the set. - * - * @param signal_number_1 The first signal number to be added. - * - * @param signal_number_2 The second signal number to be added. - * - * @param signal_number_3 The third signal number to be added. - * - * @note This constructor is equivalent to performing: - * @code boost::asio::signal_set signals(io_context); - * signals.add(signal_number_1); - * signals.add(signal_number_2); - * signals.add(signal_number_3); @endcode - */ - signal_set(boost::asio::io_context& io_context, int signal_number_1, - int signal_number_2, int signal_number_3) - : basic_io_object<detail::signal_set_service>(io_context) - { - boost::system::error_code ec; - this->get_service().add(this->get_implementation(), signal_number_1, ec); - boost::asio::detail::throw_error(ec, "add"); - this->get_service().add(this->get_implementation(), signal_number_2, ec); - boost::asio::detail::throw_error(ec, "add"); - this->get_service().add(this->get_implementation(), signal_number_3, ec); - boost::asio::detail::throw_error(ec, "add"); - } - - /// Destroys the signal set. - /** - * This function destroys the signal set, cancelling any outstanding - * asynchronous wait operations associated with the signal set as if by - * calling @c cancel. - */ - ~signal_set() - { - } - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<detail::signal_set_service>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<detail::signal_set_service>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - - /// Get the executor associated with the object. - executor_type get_executor() BOOST_ASIO_NOEXCEPT - { - return basic_io_object<detail::signal_set_service>::get_executor(); - } - - /// Add a signal to a signal_set. - /** - * This function adds the specified signal to the set. It has no effect if the - * signal is already in the set. - * - * @param signal_number The signal to be added to the set. - * - * @throws boost::system::system_error Thrown on failure. - */ - void add(int signal_number) - { - boost::system::error_code ec; - this->get_service().add(this->get_implementation(), signal_number, ec); - boost::asio::detail::throw_error(ec, "add"); - } - - /// Add a signal to a signal_set. - /** - * This function adds the specified signal to the set. It has no effect if the - * signal is already in the set. - * - * @param signal_number The signal to be added to the set. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID add(int signal_number, - boost::system::error_code& ec) - { - this->get_service().add(this->get_implementation(), signal_number, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Remove a signal from a signal_set. - /** - * This function removes the specified signal from the set. It has no effect - * if the signal is not in the set. - * - * @param signal_number The signal to be removed from the set. - * - * @throws boost::system::system_error Thrown on failure. - * - * @note Removes any notifications that have been queued for the specified - * signal number. - */ - void remove(int signal_number) - { - boost::system::error_code ec; - this->get_service().remove(this->get_implementation(), signal_number, ec); - boost::asio::detail::throw_error(ec, "remove"); - } - - /// Remove a signal from a signal_set. - /** - * This function removes the specified signal from the set. It has no effect - * if the signal is not in the set. - * - * @param signal_number The signal to be removed from the set. - * - * @param ec Set to indicate what error occurred, if any. - * - * @note Removes any notifications that have been queued for the specified - * signal number. - */ - BOOST_ASIO_SYNC_OP_VOID remove(int signal_number, - boost::system::error_code& ec) - { - this->get_service().remove(this->get_implementation(), signal_number, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Remove all signals from a signal_set. - /** - * This function removes all signals from the set. It has no effect if the set - * is already empty. - * - * @throws boost::system::system_error Thrown on failure. - * - * @note Removes all queued notifications. - */ - void clear() - { - boost::system::error_code ec; - this->get_service().clear(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "clear"); - } - - /// Remove all signals from a signal_set. - /** - * This function removes all signals from the set. It has no effect if the set - * is already empty. - * - * @param ec Set to indicate what error occurred, if any. - * - * @note Removes all queued notifications. - */ - BOOST_ASIO_SYNC_OP_VOID clear(boost::system::error_code& ec) - { - this->get_service().clear(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Cancel all operations associated with the signal set. - /** - * This function forces the completion of any pending asynchronous wait - * operations against the signal set. The handler for each cancelled - * operation will be invoked with the boost::asio::error::operation_aborted - * error code. - * - * Cancellation does not alter the set of registered signals. - * - * @throws boost::system::system_error Thrown on failure. - * - * @note If a registered signal occurred before cancel() is called, then the - * handlers for asynchronous wait operations will: - * - * @li have already been invoked; or - * - * @li have been queued for invocation in the near future. - * - * These handlers can no longer be cancelled, and therefore are passed an - * error code that indicates the successful completion of the wait operation. - */ - void cancel() - { - boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "cancel"); - } - - /// Cancel all operations associated with the signal set. - /** - * This function forces the completion of any pending asynchronous wait - * operations against the signal set. The handler for each cancelled - * operation will be invoked with the boost::asio::error::operation_aborted - * error code. - * - * Cancellation does not alter the set of registered signals. - * - * @param ec Set to indicate what error occurred, if any. - * - * @note If a registered signal occurred before cancel() is called, then the - * handlers for asynchronous wait operations will: - * - * @li have already been invoked; or - * - * @li have been queued for invocation in the near future. - * - * These handlers can no longer be cancelled, and therefore are passed an - * error code that indicates the successful completion of the wait operation. - */ - BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) - { - this->get_service().cancel(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Start an asynchronous operation to wait for a signal to be delivered. - /** - * This function may be used to initiate an asynchronous wait against the - * signal set. It always returns immediately. - * - * For each call to async_wait(), the supplied handler will be called exactly - * once. The handler will be called when: - * - * @li One of the registered signals in the signal set occurs; or - * - * @li The signal set was cancelled, in which case the handler is passed the - * error code boost::asio::error::operation_aborted. - * - * @param handler The handler to be called when the signal occurs. Copies - * will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * int signal_number // Indicates which signal occurred. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - */ - template <typename SignalHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler, - void (boost::system::error_code, int)) - async_wait(BOOST_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. - BOOST_ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check; - - async_completion<SignalHandler, - void (boost::system::error_code, int)> init(handler); - - this->get_service().async_wait(this->get_implementation(), - init.completion_handler); - - return init.result.get(); - } -}; -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } // namespace asio } // namespace boost diff --git a/boost/asio/signal_set_service.hpp b/boost/asio/signal_set_service.hpp deleted file mode 100644 index 743611620d..0000000000 --- a/boost/asio/signal_set_service.hpp +++ /dev/null @@ -1,144 +0,0 @@ -// -// signal_set_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_SIGNAL_SET_SERVICE_HPP -#define BOOST_ASIO_SIGNAL_SET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/signal_set_service.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a signal set. -class signal_set_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<signal_set_service> -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - -public: - /// The type of a signal set implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef detail::signal_set_service::implementation_type implementation_type; -#endif - - /// Construct a new signal set service for the specified io_context. - explicit signal_set_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base<signal_set_service>(io_context), - service_impl_(io_context) - { - } - - /// Construct a new signal set implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a signal set implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Add a signal to a signal_set. - BOOST_ASIO_SYNC_OP_VOID add(implementation_type& impl, - int signal_number, boost::system::error_code& ec) - { - service_impl_.add(impl, signal_number, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Remove a signal to a signal_set. - BOOST_ASIO_SYNC_OP_VOID remove(implementation_type& impl, - int signal_number, boost::system::error_code& ec) - { - service_impl_.remove(impl, signal_number, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Remove all signals from a signal_set. - BOOST_ASIO_SYNC_OP_VOID clear(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.clear(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Cancel all operations associated with the signal set. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - // Start an asynchronous operation to wait for a signal to be delivered. - template <typename SignalHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler, - void (boost::system::error_code, int)) - async_wait(implementation_type& impl, - BOOST_ASIO_MOVE_ARG(SignalHandler) handler) - { - async_completion<SignalHandler, - void (boost::system::error_code, int)> init(handler); - - service_impl_.async_wait(impl, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // Perform any fork-related housekeeping. - void notify_fork(boost::asio::io_context::fork_event event) - { - service_impl_.notify_fork(event); - } - - // The platform-specific implementation. - detail::signal_set_service service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_SIGNAL_SET_SERVICE_HPP diff --git a/boost/asio/socket_acceptor_service.hpp b/boost/asio/socket_acceptor_service.hpp deleted file mode 100644 index ed5c084401..0000000000 --- a/boost/asio/socket_acceptor_service.hpp +++ /dev/null @@ -1,374 +0,0 @@ -// -// socket_acceptor_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP -#define BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <boost/asio/basic_socket.hpp> -#include <boost/asio/detail/type_traits.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/null_socket_service.hpp> -#elif defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_socket_service.hpp> -#else -# include <boost/asio/detail/reactive_socket_service.hpp> -#endif - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a socket acceptor. -template <typename Protocol> -class socket_acceptor_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<socket_acceptor_service<Protocol> > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename protocol_type::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) - typedef detail::null_socket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#else - typedef detail::reactive_socket_service<Protocol> service_impl_type; -#endif - -public: - /// The native type of the socket acceptor. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native acceptor type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef typename service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new socket acceptor service for the specified io_context. - explicit socket_acceptor_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - socket_acceptor_service<Protocol> >(io_context), - service_impl_(io_context) - { - } - - /// Construct a new socket acceptor implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new socket acceptor implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another socket acceptor implementation. - void move_assign(implementation_type& impl, - socket_acceptor_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } - - // All acceptor services have access to each other's implementations. - template <typename Protocol1> friend class socket_acceptor_service; - - /// Move-construct a new socket acceptor implementation from another protocol - /// type. - template <typename Protocol1> - void converting_move_construct(implementation_type& impl, - socket_acceptor_service<Protocol1>& other_service, - typename socket_acceptor_service< - Protocol1>::implementation_type& other_impl, - typename enable_if<is_convertible< - Protocol1, Protocol>::value>::type* = 0) - { - service_impl_.template converting_move_construct<Protocol1>( - impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a socket acceptor implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a new socket acceptor implementation. - BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl, - const protocol_type& protocol, boost::system::error_code& ec) - { - service_impl_.open(impl, protocol, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Assign an existing native acceptor to a socket acceptor. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const protocol_type& protocol, const native_handle_type& native_acceptor, - boost::system::error_code& ec) - { - service_impl_.assign(impl, protocol, native_acceptor, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the acceptor is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Cancel all asynchronous operations associated with the acceptor. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Bind the socket acceptor to the specified local endpoint. - BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl, - const endpoint_type& endpoint, boost::system::error_code& ec) - { - service_impl_.bind(impl, endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Place the socket acceptor into the state where it will listen for new - /// connections. - BOOST_ASIO_SYNC_OP_VOID listen(implementation_type& impl, int backlog, - boost::system::error_code& ec) - { - service_impl_.listen(impl, backlog, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Close a socket acceptor implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Release ownership of the underlying acceptor. - native_handle_type release(implementation_type& impl, - boost::system::error_code& ec) - { - return service_impl_.release(impl, ec); - } - - /// Get the native acceptor implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Set a socket option. - template <typename SettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl, - const SettableSocketOption& option, boost::system::error_code& ec) - { - service_impl_.set_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get a socket option. - template <typename GettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl, - GettableSocketOption& option, boost::system::error_code& ec) const - { - service_impl_.get_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Perform an IO control command on the socket. - template <typename IoControlCommand> - BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl, - IoControlCommand& command, boost::system::error_code& ec) - { - service_impl_.io_control(impl, command, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the acceptor. - bool non_blocking(const implementation_type& impl) const - { - return service_impl_.non_blocking(impl); - } - - /// Sets the non-blocking mode of the acceptor. - BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the native acceptor implementation. - bool native_non_blocking(const implementation_type& impl) const - { - return service_impl_.native_non_blocking(impl); - } - - /// Sets the non-blocking mode of the native acceptor implementation. - BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.native_non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Wait for the acceptor to become ready to read, ready to write, or to have - /// pending error conditions. - BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl, - socket_base::wait_type w, boost::system::error_code& ec) - { - service_impl_.wait(impl, w, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Asynchronously wait for the acceptor to become ready to read, ready to - /// write, or to have pending error conditions. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, socket_base::wait_type w, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, w, init.completion_handler); - - return init.result.get(); - } - - /// Accept a new connection. - template <typename Protocol1, typename SocketService> - BOOST_ASIO_SYNC_OP_VOID accept(implementation_type& impl, - basic_socket<Protocol1, SocketService>& peer, - endpoint_type* peer_endpoint, boost::system::error_code& ec, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) - { - service_impl_.accept(impl, peer, peer_endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - -#if defined(BOOST_ASIO_HAS_MOVE) - /// Accept a new connection. - typename Protocol::socket accept(implementation_type& impl, - io_context* peer_io_context, endpoint_type* peer_endpoint, - boost::system::error_code& ec) - { - return service_impl_.accept(impl, peer_io_context, peer_endpoint, ec); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) - - /// Start an asynchronous accept. - template <typename Protocol1, typename SocketService, typename AcceptHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, - void (boost::system::error_code)) - async_accept(implementation_type& impl, - basic_socket<Protocol1, SocketService>& peer, - endpoint_type* peer_endpoint, - BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) - { - async_completion<AcceptHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_accept(impl, - peer, peer_endpoint, init.completion_handler); - - return init.result.get(); - } - -#if defined(BOOST_ASIO_HAS_MOVE) - /// Start an asynchronous accept. - template <typename MoveAcceptHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, - void (boost::system::error_code, typename Protocol::socket)) - async_accept(implementation_type& impl, - boost::asio::io_context* peer_io_context, endpoint_type* peer_endpoint, - BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler) - { - async_completion<MoveAcceptHandler, - void (boost::system::error_code, - typename Protocol::socket)> init(handler); - - service_impl_.async_accept(impl, - peer_io_context, peer_endpoint, init.completion_handler); - - return init.result.get(); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP diff --git a/boost/asio/socket_base.hpp b/boost/asio/socket_base.hpp index ee8aa6b262..c19f8d2742 100644 --- a/boost/asio/socket_base.hpp +++ b/boost/asio/socket_base.hpp @@ -2,7 +2,7 @@ // socket_base.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -99,7 +99,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::socket_base::broadcast option(true); * socket.set_option(option); @@ -108,7 +108,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::socket_base::broadcast option; * socket.get_option(option); @@ -133,7 +133,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::debug option(true); * socket.set_option(option); @@ -142,7 +142,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::debug option; * socket.get_option(option); @@ -166,7 +166,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::socket_base::do_not_route option(true); * socket.set_option(option); @@ -175,7 +175,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::udp::socket socket(io_context); + * boost::asio::ip::udp::socket socket(my_context); * ... * boost::asio::socket_base::do_not_route option; * socket.get_option(option); @@ -200,7 +200,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::keep_alive option(true); * socket.set_option(option); @@ -209,7 +209,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::keep_alive option; * socket.get_option(option); @@ -233,7 +233,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::send_buffer_size option(8192); * socket.set_option(option); @@ -242,7 +242,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::send_buffer_size option; * socket.get_option(option); @@ -267,7 +267,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::send_low_watermark option(1024); * socket.set_option(option); @@ -276,7 +276,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::send_low_watermark option; * socket.get_option(option); @@ -301,7 +301,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::receive_buffer_size option(8192); * socket.set_option(option); @@ -310,7 +310,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::receive_buffer_size option; * socket.get_option(option); @@ -335,7 +335,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::receive_low_watermark option(1024); * socket.set_option(option); @@ -344,7 +344,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::receive_low_watermark option; * socket.get_option(option); @@ -370,7 +370,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::socket_base::reuse_address option(true); * acceptor.set_option(option); @@ -379,7 +379,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::socket_base::reuse_address option; * acceptor.get_option(option); @@ -405,7 +405,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::linger option(true, 30); * socket.set_option(option); @@ -414,7 +414,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::linger option; * socket.get_option(option); @@ -440,7 +440,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::out_of_band_inline option(true); * socket.set_option(option); @@ -449,7 +449,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::out_of_band_inline option; * socket.get_option(option); @@ -476,7 +476,7 @@ public: * @par Examples * Setting the option: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::socket_base::enable_connection_aborted option(true); * acceptor.set_option(option); @@ -485,7 +485,7 @@ public: * @par * Getting the current option value: * @code - * boost::asio::ip::tcp::acceptor acceptor(io_context); + * boost::asio::ip::tcp::acceptor acceptor(my_context); * ... * boost::asio::socket_base::enable_connection_aborted option; * acceptor.get_option(option); @@ -511,7 +511,7 @@ public: * * @par Example * @code - * boost::asio::ip::tcp::socket socket(io_context); + * boost::asio::ip::tcp::socket socket(my_context); * ... * boost::asio::socket_base::bytes_readable command(true); * socket.io_control(command); diff --git a/boost/asio/spawn.hpp b/boost/asio/spawn.hpp index b39cb90143..26fda32ff4 100644 --- a/boost/asio/spawn.hpp +++ b/boost/asio/spawn.hpp @@ -2,7 +2,7 @@ // spawn.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl.hpp b/boost/asio/ssl.hpp index 35138880ae..924f179503 100644 --- a/boost/asio/ssl.hpp +++ b/boost/asio/ssl.hpp @@ -2,7 +2,7 @@ // ssl.hpp // ~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/context.hpp b/boost/asio/ssl/context.hpp index 3d0cbfbfbc..60b92a8438 100644 --- a/boost/asio/ssl/context.hpp +++ b/boost/asio/ssl/context.hpp @@ -2,7 +2,7 @@ // ssl/context.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/context_base.hpp b/boost/asio/ssl/context_base.hpp index 625ccc7b5b..98fdedc2e5 100644 --- a/boost/asio/ssl/context_base.hpp +++ b/boost/asio/ssl/context_base.hpp @@ -2,7 +2,7 @@ // ssl/context_base.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/buffered_handshake_op.hpp b/boost/asio/ssl/detail/buffered_handshake_op.hpp index a8963ec590..812e4d7016 100644 --- a/boost/asio/ssl/detail/buffered_handshake_op.hpp +++ b/boost/asio/ssl/detail/buffered_handshake_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/buffered_handshake_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/engine.hpp b/boost/asio/ssl/detail/engine.hpp index 01717e789e..37e4d33016 100644 --- a/boost/asio/ssl/detail/engine.hpp +++ b/boost/asio/ssl/detail/engine.hpp @@ -2,7 +2,7 @@ // ssl/detail/engine.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/handshake_op.hpp b/boost/asio/ssl/detail/handshake_op.hpp index edb112eee2..846e33f253 100644 --- a/boost/asio/ssl/detail/handshake_op.hpp +++ b/boost/asio/ssl/detail/handshake_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/handshake_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/impl/engine.ipp b/boost/asio/ssl/detail/impl/engine.ipp index 9142a5df3a..cac7dfda56 100644 --- a/boost/asio/ssl/detail/impl/engine.ipp +++ b/boost/asio/ssl/detail/impl/engine.ipp @@ -2,7 +2,7 @@ // ssl/detail/impl/engine.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -241,14 +241,23 @@ engine::want engine::perform(int (engine::* op)(void*, std::size_t), { ec = boost::system::error_code(sys_error, boost::asio::error::get_ssl_category()); - return want_nothing; + return pending_output_after > pending_output_before + ? want_output : want_nothing; } if (ssl_error == SSL_ERROR_SYSCALL) { - ec = boost::system::error_code(sys_error, - boost::asio::error::get_system_category()); - return want_nothing; + if (sys_error == 0) + { + ec = boost::asio::ssl::error::unspecified_system_error; + } + else + { + ec = boost::system::error_code(sys_error, + boost::asio::error::get_ssl_category()); + } + return pending_output_after > pending_output_before + ? want_output : want_nothing; } if (result > 0 && bytes_transferred) @@ -269,16 +278,21 @@ engine::want engine::perform(int (engine::* op)(void*, std::size_t), ec = boost::system::error_code(); return want_input_and_retry; } - else if (::SSL_get_shutdown(ssl_) & SSL_RECEIVED_SHUTDOWN) + else if (ssl_error == SSL_ERROR_ZERO_RETURN) { ec = boost::asio::error::eof; return want_nothing; } - else + else if (ssl_error == SSL_ERROR_NONE) { ec = boost::system::error_code(); return want_nothing; } + else + { + ec = boost::asio::ssl::error::unexpected_result; + return want_nothing; + } } int engine::do_accept(void*, std::size_t) diff --git a/boost/asio/ssl/detail/impl/openssl_init.ipp b/boost/asio/ssl/detail/impl/openssl_init.ipp index 1608138e9d..5e80dd2556 100644 --- a/boost/asio/ssl/detail/impl/openssl_init.ipp +++ b/boost/asio/ssl/detail/impl/openssl_init.ipp @@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005-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) diff --git a/boost/asio/ssl/detail/io.hpp b/boost/asio/ssl/detail/io.hpp index 604148c795..f1c2e5317a 100644 --- a/boost/asio/ssl/detail/io.hpp +++ b/boost/asio/ssl/detail/io.hpp @@ -2,7 +2,7 @@ // ssl/detail/io.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -32,6 +32,7 @@ template <typename Stream, typename Operation> std::size_t io(Stream& next_layer, stream_core& core, const Operation& op, boost::system::error_code& ec) { + boost::system::error_code io_ec; std::size_t bytes_transferred = 0; do switch (op(core.engine_, ec, bytes_transferred)) { @@ -40,8 +41,12 @@ std::size_t io(Stream& next_layer, stream_core& core, // If the input buffer is empty then we need to read some more data from // the underlying transport. if (core.input_.size() == 0) + { core.input_ = boost::asio::buffer(core.input_buffer_, - next_layer.read_some(core.input_buffer_, ec)); + next_layer.read_some(core.input_buffer_, io_ec)); + if (!ec) + ec = io_ec; + } // Pass the new input data to the engine. core.input_ = core.engine_.put_input(core.input_); @@ -54,7 +59,9 @@ std::size_t io(Stream& next_layer, stream_core& core, // Get output data from the engine and write it to the underlying // transport. boost::asio::write(next_layer, - core.engine_.get_output(core.output_buffer_), ec); + core.engine_.get_output(core.output_buffer_), io_ec); + if (!ec) + ec = io_ec; // Try the operation again. continue; @@ -64,7 +71,9 @@ std::size_t io(Stream& next_layer, stream_core& core, // Get output data from the engine and write it to the underlying // transport. boost::asio::write(next_layer, - core.engine_.get_output(core.output_buffer_), ec); + core.engine_.get_output(core.output_buffer_), io_ec); + if (!ec) + ec = io_ec; // Operation is complete. Return result to caller. core.engine_.map_error_code(ec); diff --git a/boost/asio/ssl/detail/openssl_init.hpp b/boost/asio/ssl/detail/openssl_init.hpp index 05b1ea4a33..74556a233b 100644 --- a/boost/asio/ssl/detail/openssl_init.hpp +++ b/boost/asio/ssl/detail/openssl_init.hpp @@ -2,7 +2,7 @@ // ssl/detail/openssl_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/openssl_types.hpp b/boost/asio/ssl/detail/openssl_types.hpp index c955ac6013..494287a36e 100644 --- a/boost/asio/ssl/detail/openssl_types.hpp +++ b/boost/asio/ssl/detail/openssl_types.hpp @@ -2,7 +2,7 @@ // ssl/detail/openssl_types.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/password_callback.hpp b/boost/asio/ssl/detail/password_callback.hpp index 2a442f34d2..9e57e90e39 100644 --- a/boost/asio/ssl/detail/password_callback.hpp +++ b/boost/asio/ssl/detail/password_callback.hpp @@ -2,7 +2,7 @@ // ssl/detail/password_callback.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/read_op.hpp b/boost/asio/ssl/detail/read_op.hpp index 31929c9474..e0322aaa62 100644 --- a/boost/asio/ssl/detail/read_op.hpp +++ b/boost/asio/ssl/detail/read_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/shutdown_op.hpp b/boost/asio/ssl/detail/shutdown_op.hpp index e98430621e..d55058af37 100644 --- a/boost/asio/ssl/detail/shutdown_op.hpp +++ b/boost/asio/ssl/detail/shutdown_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/shutdown_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -42,7 +42,17 @@ public: const boost::system::error_code& ec, const std::size_t&) const { - handler(ec); + if (ec == boost::asio::error::eof) + { + // The engine only generates an eof when the shutdown notification has + // been received from the peer. This indicates that the shutdown has + // completed successfully, and thus need not be passed on to the handler. + handler(boost::system::error_code()); + } + else + { + handler(ec); + } } }; diff --git a/boost/asio/ssl/detail/stream_core.hpp b/boost/asio/ssl/detail/stream_core.hpp index fc0a6ffffc..eba283618f 100644 --- a/boost/asio/ssl/detail/stream_core.hpp +++ b/boost/asio/ssl/detail/stream_core.hpp @@ -2,7 +2,7 @@ // ssl/detail/stream_core.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -38,10 +38,11 @@ struct stream_core // sufficient to hold the largest possible TLS record. enum { max_tls_record_size = 17 * 1024 }; - stream_core(SSL_CTX* context, boost::asio::io_context& io_context) + template <typename Executor> + stream_core(SSL_CTX* context, const Executor& ex) : engine_(context), - pending_read_(io_context), - pending_write_(io_context), + pending_read_(ex), + pending_write_(ex), output_buffer_space_(max_tls_record_size), output_buffer_(boost::asio::buffer(output_buffer_space_)), input_buffer_space_(max_tls_record_size), diff --git a/boost/asio/ssl/detail/verify_callback.hpp b/boost/asio/ssl/detail/verify_callback.hpp index 1e96b2554b..b4cfdcedc0 100644 --- a/boost/asio/ssl/detail/verify_callback.hpp +++ b/boost/asio/ssl/detail/verify_callback.hpp @@ -2,7 +2,7 @@ // ssl/detail/verify_callback.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/detail/write_op.hpp b/boost/asio/ssl/detail/write_op.hpp index 17ab95d67e..ec50cff54a 100644 --- a/boost/asio/ssl/detail/write_op.hpp +++ b/boost/asio/ssl/detail/write_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/error.hpp b/boost/asio/ssl/error.hpp index 4a68d71703..e9ce78718c 100644 --- a/boost/asio/ssl/error.hpp +++ b/boost/asio/ssl/error.hpp @@ -2,7 +2,7 @@ // ssl/error.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -45,12 +45,24 @@ enum stream_errors { #if defined(GENERATING_DOCUMENTATION) /// The underlying stream closed before the ssl stream gracefully shut down. - stream_truncated -#elif (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_IS_BORINGSSL) - stream_truncated = ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ) -#else - stream_truncated = 1 -#endif + stream_truncated, + + /// The underlying SSL library returned a system error without providing + /// further information. + unspecified_system_error, + + /// The underlying SSL library generated an unexpected result from a function + /// call. + unexpected_result +#else // defined(GENERATING_DOCUMENTATION) +# if (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_IS_BORINGSSL) + stream_truncated = ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), +# else + stream_truncated = 1, +# endif + unspecified_system_error = 2, + unexpected_result = 3 +#endif // defined(GENERATING_DOCUMENTATION) }; extern BOOST_ASIO_DECL diff --git a/boost/asio/ssl/impl/context.hpp b/boost/asio/ssl/impl/context.hpp index 8f016830f9..f9ab3ad779 100644 --- a/boost/asio/ssl/impl/context.hpp +++ b/boost/asio/ssl/impl/context.hpp @@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005-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) diff --git a/boost/asio/ssl/impl/context.ipp b/boost/asio/ssl/impl/context.ipp index b331dea45d..0947a87564 100644 --- a/boost/asio/ssl/impl/context.ipp +++ b/boost/asio/ssl/impl/context.ipp @@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005-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) diff --git a/boost/asio/ssl/impl/error.ipp b/boost/asio/ssl/impl/error.ipp index a359619765..d77c051c9e 100644 --- a/boost/asio/ssl/impl/error.ipp +++ b/boost/asio/ssl/impl/error.ipp @@ -2,7 +2,7 @@ // ssl/impl/error.ipp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -77,6 +77,8 @@ public: switch (value) { case stream_truncated: return "stream truncated"; + case unspecified_system_error: return "unspecified system error"; + case unexpected_result: return "unexpected result"; default: return "asio.ssl.stream error"; } } diff --git a/boost/asio/ssl/impl/rfc2818_verification.ipp b/boost/asio/ssl/impl/rfc2818_verification.ipp index 63ce663bdc..3720509258 100644 --- a/boost/asio/ssl/impl/rfc2818_verification.ipp +++ b/boost/asio/ssl/impl/rfc2818_verification.ipp @@ -2,7 +2,7 @@ // ssl/impl/rfc2818_verification.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/impl/src.hpp b/boost/asio/ssl/impl/src.hpp index 2e8859ea2b..4f965ed4ab 100644 --- a/boost/asio/ssl/impl/src.hpp +++ b/boost/asio/ssl/impl/src.hpp @@ -2,7 +2,7 @@ // impl/ssl/src.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/rfc2818_verification.hpp b/boost/asio/ssl/rfc2818_verification.hpp index 047688b007..1e4e411658 100644 --- a/boost/asio/ssl/rfc2818_verification.hpp +++ b/boost/asio/ssl/rfc2818_verification.hpp @@ -2,7 +2,7 @@ // ssl/rfc2818_verification.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/stream.hpp b/boost/asio/ssl/stream.hpp index 1acaceea45..2ae8c13a4a 100644 --- a/boost/asio/ssl/stream.hpp +++ b/boost/asio/ssl/stream.hpp @@ -2,7 +2,7 @@ // ssl/stream.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -20,6 +20,7 @@ #include <boost/asio/async_result.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> #include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/non_const_lvalue.hpp> #include <boost/asio/detail/noncopyable.hpp> #include <boost/asio/detail/type_traits.hpp> #include <boost/asio/ssl/context.hpp> @@ -52,9 +53,9 @@ namespace ssl { * @par Example * To use the SSL stream template with an ip::tcp::socket, you would write: * @code - * boost::asio::io_context io_context; + * boost::asio::io_context my_context; * boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); - * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx); + * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx); * @endcode * * @par Concepts: @@ -97,16 +98,14 @@ public: template <typename Arg> stream(Arg&& arg, context& ctx) : next_layer_(BOOST_ASIO_MOVE_CAST(Arg)(arg)), - core_(ctx.native_handle(), - next_layer_.lowest_layer().get_executor().context()) + core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) { } #else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) template <typename Arg> stream(Arg& arg, context& ctx) : next_layer_(arg), - core_(ctx.native_handle(), - next_layer_.lowest_layer().get_executor().context()) + core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) { } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -132,22 +131,6 @@ public: return next_layer_.lowest_layer().get_executor(); } -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - boost::asio::io_context& get_io_context() - { - return next_layer_.lowest_layer().get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - boost::asio::io_context& get_io_service() - { - return next_layer_.lowest_layer().get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - /// Get the underlying implementation in the native type. /** * This function may be used to obtain the underlying implementation of the @@ -159,7 +142,7 @@ public: * suitable for passing to functions such as @c SSL_get_verify_result and * @c SSL_get_peer_certificate: * @code - * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx); + * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx); * * // ... establish connection and perform handshake ... * @@ -454,17 +437,9 @@ public: async_handshake(handshake_type type, BOOST_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. - BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check; - - boost::asio::async_completion<HandshakeHandler, - void (boost::system::error_code)> init(handler); - - detail::async_io(next_layer_, core_, - detail::handshake_op(type), init.completion_handler); - - return init.result.get(); + return async_initiate<HandshakeHandler, + void (boost::system::error_code)>( + initiate_async_handshake(), handler, this, type); } /// Start an asynchronous SSL handshake. @@ -494,19 +469,9 @@ public: async_handshake(handshake_type type, const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( - BufferedHandshakeHandler, handler) type_check; - - boost::asio::async_completion<BufferedHandshakeHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::async_io(next_layer_, core_, - detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), - init.completion_handler); - - return init.result.get(); + return async_initiate<BufferedHandshakeHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_buffered_handshake(), handler, this, type, buffers); } /// Shut down SSL on the stream. @@ -553,17 +518,9 @@ public: void (boost::system::error_code)) async_shutdown(BOOST_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. - BOOST_ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, handler) type_check; - - boost::asio::async_completion<ShutdownHandler, - void (boost::system::error_code)> init(handler); - - detail::async_io(next_layer_, core_, detail::shutdown_op(), - init.completion_handler); - - return init.result.get(); + return async_initiate<ShutdownHandler, + void (boost::system::error_code)>( + initiate_async_shutdown(), handler, this); } /// Write some data to the stream. @@ -644,18 +601,9 @@ public: async_write_some(const ConstBufferSequence& buffers, BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - boost::asio::async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - detail::async_io(next_layer_, core_, - detail::write_op<ConstBufferSequence>(buffers), - init.completion_handler); - - return init.result.get(); + return async_initiate<WriteHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_write_some(), handler, this, buffers); } /// Read some data from the stream. @@ -736,21 +684,97 @@ public: async_read_some(const MutableBufferSequence& buffers, BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + return async_initiate<ReadHandler, + void (boost::system::error_code, std::size_t)>( + initiate_async_read_some(), handler, this, buffers); + } - boost::asio::async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); +private: + struct initiate_async_handshake + { + template <typename HandshakeHandler> + void operator()(BOOST_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. + BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check; + + boost::asio::detail::non_const_lvalue<HandshakeHandler> handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::handshake_op(type), handler2.value); + } + }; - detail::async_io(next_layer_, core_, - detail::read_op<MutableBufferSequence>(buffers), - init.completion_handler); + struct initiate_async_buffered_handshake + { + template <typename BufferedHandshakeHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( + BufferedHandshakeHandler, handler) type_check; + + boost::asio::detail::non_const_lvalue< + BufferedHandshakeHandler> handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), + handler2.value); + } + }; - return init.result.get(); - } + struct initiate_async_shutdown + { + template <typename ShutdownHandler> + void operator()(BOOST_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. + BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check; + + boost::asio::detail::non_const_lvalue<ShutdownHandler> handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::shutdown_op(), handler2.value); + } + }; + + struct initiate_async_write_some + { + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + boost::asio::detail::non_const_lvalue<WriteHandler> handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::write_op<ConstBufferSequence>(buffers), handler2.value); + } + }; + + struct initiate_async_read_some + { + template <typename ReadHandler, typename MutableBufferSequence> + void operator()(BOOST_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. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + boost::asio::detail::non_const_lvalue<ReadHandler> handler2(handler); + detail::async_io(self->next_layer_, self->core_, + detail::read_op<MutableBufferSequence>(buffers), handler2.value); + } + }; -private: Stream next_layer_; detail::stream_core core_; }; diff --git a/boost/asio/ssl/stream_base.hpp b/boost/asio/ssl/stream_base.hpp index 5847214894..0fefde54f1 100644 --- a/boost/asio/ssl/stream_base.hpp +++ b/boost/asio/ssl/stream_base.hpp @@ -2,7 +2,7 @@ // ssl/stream_base.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/verify_context.hpp b/boost/asio/ssl/verify_context.hpp index c5fdaf4adb..952ec917cd 100644 --- a/boost/asio/ssl/verify_context.hpp +++ b/boost/asio/ssl/verify_context.hpp @@ -2,7 +2,7 @@ // ssl/verify_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ssl/verify_mode.hpp b/boost/asio/ssl/verify_mode.hpp index 9ae6050442..0dcf18af96 100644 --- a/boost/asio/ssl/verify_mode.hpp +++ b/boost/asio/ssl/verify_mode.hpp @@ -2,7 +2,7 @@ // ssl/verify_mode.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/steady_timer.hpp b/boost/asio/steady_timer.hpp index ab30b9c8fd..5c88e975dc 100644 --- a/boost/asio/steady_timer.hpp +++ b/boost/asio/steady_timer.hpp @@ -2,7 +2,7 @@ // steady_timer.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/strand.hpp b/boost/asio/strand.hpp index b82e988fe4..d08801bd90 100644 --- a/boost/asio/strand.hpp +++ b/boost/asio/strand.hpp @@ -2,7 +2,7 @@ // strand.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -272,6 +272,33 @@ private: implementation_type impl_; }; +/** @defgroup make_strand boost::asio::make_strand + * + * @brief The boost::asio::make_strand function creates a @ref strand object for + * an executor or execution context. + */ +/*@{*/ + +/// Create a @ref strand object for an executor. +template <typename Executor> +inline strand<Executor> make_strand(const Executor& ex, + typename enable_if<is_executor<Executor>::value>::type* = 0) +{ + return strand<Executor>(ex); +} + +/// Create a @ref strand object for an execution context. +template <typename ExecutionContext> +inline strand<typename ExecutionContext::executor_type> +make_strand(ExecutionContext& ctx, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value>::type* = 0) +{ + return strand<typename ExecutionContext::executor_type>(ctx.get_executor()); +} + +/*@}*/ + } // namespace asio } // namespace boost diff --git a/boost/asio/stream_socket_service.hpp b/boost/asio/stream_socket_service.hpp deleted file mode 100644 index 04159ea66f..0000000000 --- a/boost/asio/stream_socket_service.hpp +++ /dev/null @@ -1,414 +0,0 @@ -// -// stream_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP -#define BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/type_traits.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) -# include <boost/asio/detail/winrt_ssocket_service.hpp> -#elif defined(BOOST_ASIO_HAS_IOCP) -# include <boost/asio/detail/win_iocp_socket_service.hpp> -#else -# include <boost/asio/detail/reactive_socket_service.hpp> -#endif - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a stream socket. -template <typename Protocol> -class stream_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<stream_socket_service<Protocol> > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(BOOST_ASIO_WINDOWS_RUNTIME) - typedef detail::winrt_ssocket_service<Protocol> service_impl_type; -#elif defined(BOOST_ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service<Protocol> service_impl_type; -#else - typedef detail::reactive_socket_service<Protocol> service_impl_type; -#endif - -public: - /// The type of a stream socket implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef typename service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new stream socket service for the specified io_context. - explicit stream_socket_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - stream_socket_service<Protocol> >(io_context), - service_impl_(io_context) - { - } - - /// Construct a new stream socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new stream socket implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another stream socket implementation. - void move_assign(implementation_type& impl, - stream_socket_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } - - // All socket services have access to each other's implementations. - template <typename Protocol1> friend class stream_socket_service; - - /// Move-construct a new stream socket implementation from another protocol - /// type. - template <typename Protocol1> - void converting_move_construct(implementation_type& impl, - stream_socket_service<Protocol1>& other_service, - typename stream_socket_service< - Protocol1>::implementation_type& other_impl, - typename enable_if<is_convertible< - Protocol1, Protocol>::value>::type* = 0) - { - service_impl_.template converting_move_construct<Protocol1>( - impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a stream socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a stream socket. - BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl, - const protocol_type& protocol, boost::system::error_code& ec) - { - if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_STREAM)) - service_impl_.open(impl, protocol, ec); - else - ec = boost::asio::error::invalid_argument; - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Assign an existing native socket to a stream socket. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const protocol_type& protocol, const native_handle_type& native_socket, - boost::system::error_code& ec) - { - service_impl_.assign(impl, protocol, native_socket, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a stream socket implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Release ownership of the underlying socket. - native_handle_type release(implementation_type& impl, - boost::system::error_code& ec) - { - return service_impl_.release(impl, ec); - } - - /// Get the native socket implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - /// Bind the stream socket to the specified local endpoint. - BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl, - const endpoint_type& endpoint, boost::system::error_code& ec) - { - service_impl_.bind(impl, endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Connect the stream socket to the specified endpoint. - BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl, - const endpoint_type& peer_endpoint, boost::system::error_code& ec) - { - service_impl_.connect(impl, peer_endpoint, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Start an asynchronous connect. - template <typename ConnectHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, - void (boost::system::error_code)) - async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, - BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) - { - async_completion<ConnectHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_connect(impl, peer_endpoint, init.completion_handler); - - return init.result.get(); - } - - /// Set a socket option. - template <typename SettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl, - const SettableSocketOption& option, boost::system::error_code& ec) - { - service_impl_.set_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get a socket option. - template <typename GettableSocketOption> - BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl, - GettableSocketOption& option, boost::system::error_code& ec) const - { - service_impl_.get_option(impl, option, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Perform an IO control command on the socket. - template <typename IoControlCommand> - BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl, - IoControlCommand& command, boost::system::error_code& ec) - { - service_impl_.io_control(impl, command, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the socket. - bool non_blocking(const implementation_type& impl) const - { - return service_impl_.non_blocking(impl); - } - - /// Sets the non-blocking mode of the socket. - BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Gets the non-blocking mode of the native socket implementation. - bool native_non_blocking(const implementation_type& impl) const - { - return service_impl_.native_non_blocking(impl); - } - - /// Sets the non-blocking mode of the native socket implementation. - BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl, - bool mode, boost::system::error_code& ec) - { - service_impl_.native_non_blocking(impl, mode, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl, - socket_base::shutdown_type what, boost::system::error_code& ec) - { - service_impl_.shutdown(impl, what, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Wait for the socket to become ready to read, ready to write, or to have - /// pending error conditions. - BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl, - socket_base::wait_type w, boost::system::error_code& ec) - { - service_impl_.wait(impl, w, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Asynchronously wait for the socket to become ready to read, ready to - /// write, or to have pending error conditions. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, socket_base::wait_type w, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, w, init.completion_handler); - - return init.result.get(); - } - - /// Send the given data to the peer. - template <typename ConstBufferSequence> - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_send(impl, buffers, flags, init.completion_handler); - - return init.result.get(); - } - - /// Receive some data from the peer. - template <typename MutableBufferSequence> - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, boost::system::error_code& ec) - { - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Start an asynchronous receive. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_receive(impl, buffers, flags, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP diff --git a/boost/asio/streambuf.hpp b/boost/asio/streambuf.hpp index 737a631151..a66600d0f7 100644 --- a/boost/asio/streambuf.hpp +++ b/boost/asio/streambuf.hpp @@ -2,7 +2,7 @@ // streambuf.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/system_context.hpp b/boost/asio/system_context.hpp index 22f6b19426..96d29f4249 100644 --- a/boost/asio/system_context.hpp +++ b/boost/asio/system_context.hpp @@ -2,7 +2,7 @@ // system_context.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -60,6 +60,9 @@ private: struct thread_function; + // Helper function to create the underlying scheduler. + BOOST_ASIO_DECL detail::scheduler& add_scheduler(detail::scheduler* s); + // The underlying scheduler. detail::scheduler& scheduler_; diff --git a/boost/asio/system_executor.hpp b/boost/asio/system_executor.hpp index d6f5b7def8..5125046e8a 100644 --- a/boost/asio/system_executor.hpp +++ b/boost/asio/system_executor.hpp @@ -2,7 +2,7 @@ // system_executor.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/system_timer.hpp b/boost/asio/system_timer.hpp index c2ff9947b9..880feac0d8 100644 --- a/boost/asio/system_timer.hpp +++ b/boost/asio/system_timer.hpp @@ -2,7 +2,7 @@ // system_timer.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/this_coro.hpp b/boost/asio/this_coro.hpp new file mode 100644 index 0000000000..19c50b20e8 --- /dev/null +++ b/boost/asio/this_coro.hpp @@ -0,0 +1,47 @@ +// +// this_coro.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_THIS_CORO_HPP +#define BOOST_ASIO_THIS_CORO_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace this_coro { + +/// Awaitable type that returns the executor of the current coroutine. +struct executor_t +{ + BOOST_ASIO_CONSTEXPR executor_t() + { + } +}; + +/// Awaitable object that returns the executor of the current coroutine. +#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) +constexpr executor_t executor; +#elif defined(BOOST_ASIO_MSVC) +__declspec(selectany) executor_t executor; +#endif + +} // namespace this_coro +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_THIS_CORO_HPP diff --git a/boost/asio/thread_pool.hpp b/boost/asio/thread_pool.hpp index ac5f00d091..765fa2aa21 100644 --- a/boost/asio/thread_pool.hpp +++ b/boost/asio/thread_pool.hpp @@ -2,7 +2,7 @@ // thread_pool.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -101,6 +101,9 @@ private: friend class executor_type; struct thread_function; + // Helper function to create the underlying scheduler. + BOOST_ASIO_DECL detail::scheduler& add_scheduler(detail::scheduler* s); + // The underlying scheduler. detail::scheduler& scheduler_; diff --git a/boost/asio/time_traits.hpp b/boost/asio/time_traits.hpp index d11ea0050f..b161f468b5 100644 --- a/boost/asio/time_traits.hpp +++ b/boost/asio/time_traits.hpp @@ -2,7 +2,7 @@ // time_traits.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ts/buffer.hpp b/boost/asio/ts/buffer.hpp index 2774935f1b..6357c34359 100644 --- a/boost/asio/ts/buffer.hpp +++ b/boost/asio/ts/buffer.hpp @@ -2,7 +2,7 @@ // ts/buffer.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ts/executor.hpp b/boost/asio/ts/executor.hpp index df52817a35..e7b01af6ef 100644 --- a/boost/asio/ts/executor.hpp +++ b/boost/asio/ts/executor.hpp @@ -2,7 +2,7 @@ // ts/executor.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -15,7 +15,6 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include <boost/asio/handler_type.hpp> #include <boost/asio/async_result.hpp> #include <boost/asio/associated_allocator.hpp> #include <boost/asio/execution_context.hpp> diff --git a/boost/asio/ts/internet.hpp b/boost/asio/ts/internet.hpp index 7448015734..1e1abce6b6 100644 --- a/boost/asio/ts/internet.hpp +++ b/boost/asio/ts/internet.hpp @@ -2,7 +2,7 @@ // ts/internet.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ts/io_context.hpp b/boost/asio/ts/io_context.hpp index aea646cc4a..9ffb06258d 100644 --- a/boost/asio/ts/io_context.hpp +++ b/boost/asio/ts/io_context.hpp @@ -2,7 +2,7 @@ // ts/io_context.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ts/net.hpp b/boost/asio/ts/net.hpp index dbac252849..dcafe69651 100644 --- a/boost/asio/ts/net.hpp +++ b/boost/asio/ts/net.hpp @@ -2,7 +2,7 @@ // ts/net.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ts/netfwd.hpp b/boost/asio/ts/netfwd.hpp index 10800baea4..d165e5bfeb 100644 --- a/boost/asio/ts/netfwd.hpp +++ b/boost/asio/ts/netfwd.hpp @@ -2,7 +2,7 @@ // ts/netfwd.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -59,26 +59,12 @@ struct time_traits; #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -template <typename Clock, typename WaitTraits> -class waitable_timer_service; - -#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) - -template <typename TimeType, typename TimeTraits> -class deadline_timer_service; - -#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL) #define BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL template <typename Clock, - typename WaitTraits = boost::asio::wait_traits<Clock> - BOOST_ASIO_SVC_TPARAM_DEF2(= waitable_timer_service<Clock, WaitTraits>)> + typename WaitTraits = wait_traits<Clock>, + typename Executor = executor> class basic_waitable_timer; #endif // !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL) @@ -94,33 +80,51 @@ typedef basic_waitable_timer<chrono::high_resolution_clock> #endif // defined(BOOST_ASIO_HAS_CHRONO) -template <class Protocol BOOST_ASIO_SVC_TPARAM> +#if !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_SOCKET_FWD_DECL + +template <typename Protocol, typename Executor = executor> class basic_socket; -template <typename Protocol BOOST_ASIO_SVC_TPARAM> +#endif // !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL) + +#if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL + +template <typename Protocol, typename Executor = executor> class basic_datagram_socket; -template <typename Protocol BOOST_ASIO_SVC_TPARAM> +#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL) + +#if !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Protocol, typename Executor = executor> class basic_stream_socket; -template <typename Protocol BOOST_ASIO_SVC_TPARAM> +#endif // !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL) + +#if !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL) +#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL + +template <typename Protocol, typename Executor = executor> class basic_socket_acceptor; +#endif // !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL) + #if !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL) #define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL // Forward declaration with defaulted arguments. -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>), +template <typename Protocol, #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ || defined(GENERATING_DOCUMENTATION) typename Clock = boost::posix_time::ptime, - typename WaitTraits = time_traits<Clock> - BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)> + typename WaitTraits = time_traits<Clock> > #else typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> - BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)> + typename WaitTraits = wait_traits<Clock> > #endif class basic_socket_streambuf; @@ -130,17 +134,14 @@ class basic_socket_streambuf; #define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL // Forward declaration with defaulted arguments. -template <typename Protocol - BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>), +template <typename Protocol, #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ || defined(GENERATING_DOCUMENTATION) typename Clock = boost::posix_time::ptime, - typename WaitTraits = time_traits<Clock> - BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)> + typename WaitTraits = time_traits<Clock> > #else typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> - BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)> + typename WaitTraits = wait_traits<Clock> > #endif class basic_socket_iostream; @@ -181,9 +182,14 @@ class basic_resolver_entry; template <typename InternetProtocol> class basic_resolver_results; -template <typename InternetProtocol BOOST_ASIO_SVC_TPARAM> +#if !defined(BOOST_ASIO_IP_BASIC_RESOLVER_FWD_DECL) +#define BOOST_ASIO_IP_BASIC_RESOLVER_FWD_DECL + +template <typename InternetProtocol, typename Executor = executor> class basic_resolver; +#endif // !defined(BOOST_ASIO_IP_BASIC_RESOLVER_FWD_DECL) + class tcp; class udp; diff --git a/boost/asio/ts/socket.hpp b/boost/asio/ts/socket.hpp index 01e6855332..be7e82351c 100644 --- a/boost/asio/ts/socket.hpp +++ b/boost/asio/ts/socket.hpp @@ -2,7 +2,7 @@ // ts/socket.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/ts/timer.hpp b/boost/asio/ts/timer.hpp index adc6bf99c4..fec6245e38 100644 --- a/boost/asio/ts/timer.hpp +++ b/boost/asio/ts/timer.hpp @@ -2,7 +2,7 @@ // ts/timer.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/unyield.hpp b/boost/asio/unyield.hpp index de3ed0275e..c6874d5cf3 100644 --- a/boost/asio/unyield.hpp +++ b/boost/asio/unyield.hpp @@ -2,7 +2,7 @@ // unyield.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/use_awaitable.hpp b/boost/asio/use_awaitable.hpp new file mode 100644 index 0000000000..8764b3d2d2 --- /dev/null +++ b/boost/asio/use_awaitable.hpp @@ -0,0 +1,73 @@ +// +// use_awaitable.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_USE_AWAITABLE_HPP +#define BOOST_ASIO_USE_AWAITABLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) + +#include <boost/asio/awaitable.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// A completion token that represents the currently executing coroutine. +/** + * The @c use_awaitable_t class, with its value @c use_awaitable, is used to + * represent the currently executing coroutine. This completion token may be + * passed as a handler to an asynchronous operation. For example: + * + * @code awaitable<void> my_coroutine() + * { + * std::size_t n = co_await my_socket.async_read_some(buffer, use_awaitable); + * ... + * } @endcode + * + * When used with co_await, the initiating function (@c async_read_some in the + * above example) suspends the current coroutine. The coroutine is resumed when + * the asynchronous operation completes, and the result of the operation is + * returned. + */ +template <typename Executor = executor> +struct use_awaitable_t +{ + BOOST_ASIO_CONSTEXPR use_awaitable_t() + { + } +}; + +/// A completion token object that represents the currently executing coroutine. +/** + * See the documentation for boost::asio::use_awaitable_t for a usage example. + */ +#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) +constexpr use_awaitable_t<> use_awaitable; +#elif defined(BOOST_ASIO_MSVC) +__declspec(selectany) use_awaitable_t<> use_awaitable; +#endif + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/impl/use_awaitable.hpp> + +#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_USE_AWAITABLE_HPP diff --git a/boost/asio/use_future.hpp b/boost/asio/use_future.hpp index 01fb2760f3..45497efa08 100644 --- a/boost/asio/use_future.hpp +++ b/boost/asio/use_future.hpp @@ -2,7 +2,7 @@ // use_future.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/uses_executor.hpp b/boost/asio/uses_executor.hpp index 6398816fab..fb55b6751e 100644 --- a/boost/asio/uses_executor.hpp +++ b/boost/asio/uses_executor.hpp @@ -2,7 +2,7 @@ // uses_executor.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/version.hpp b/boost/asio/version.hpp index bedf15bd0c..30d7b2348e 100644 --- a/boost/asio/version.hpp +++ b/boost/asio/version.hpp @@ -2,7 +2,7 @@ // version.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -18,6 +18,6 @@ // BOOST_ASIO_VERSION % 100 is the sub-minor version // BOOST_ASIO_VERSION / 100 % 1000 is the minor version // BOOST_ASIO_VERSION / 100000 is the major version -#define BOOST_ASIO_VERSION 101202 // 1.12.2 +#define BOOST_ASIO_VERSION 101400 // 1.14.0 #endif // BOOST_ASIO_VERSION_HPP diff --git a/boost/asio/wait_traits.hpp b/boost/asio/wait_traits.hpp index 9f5be813a7..66719f23a9 100644 --- a/boost/asio/wait_traits.hpp +++ b/boost/asio/wait_traits.hpp @@ -2,7 +2,7 @@ // wait_traits.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) diff --git a/boost/asio/waitable_timer_service.hpp b/boost/asio/waitable_timer_service.hpp deleted file mode 100644 index 164aae90c6..0000000000 --- a/boost/asio/waitable_timer_service.hpp +++ /dev/null @@ -1,212 +0,0 @@ -// -// waitable_timer_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_WAITABLE_TIMER_SERVICE_HPP -#define BOOST_ASIO_WAITABLE_TIMER_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/chrono_time_traits.hpp> -#include <boost/asio/detail/deadline_timer_service.hpp> -#include <boost/asio/io_context.hpp> -#include <boost/asio/wait_traits.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { - -/// Default service implementation for a timer. -template <typename Clock, - typename WaitTraits = boost::asio::wait_traits<Clock> > -class waitable_timer_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base< - waitable_timer_service<Clock, WaitTraits> > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - - /// The clock type. - typedef Clock clock_type; - - /// The duration type of the clock. - typedef typename clock_type::duration duration; - - /// The time point type of the clock. - typedef typename clock_type::time_point time_point; - - /// The wait traits type. - typedef WaitTraits traits_type; - -private: - // The type of the platform-specific implementation. - typedef detail::deadline_timer_service< - detail::chrono_time_traits<Clock, WaitTraits> > service_impl_type; - -public: - /// The implementation type of the waitable timer. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new timer service for the specified io_context. - explicit waitable_timer_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - waitable_timer_service<Clock, WaitTraits> >(io_context), - service_impl_(io_context) - { - } - - /// Construct a new timer implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a timer implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new timer implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another timer implementation. - void move_assign(implementation_type& impl, - waitable_timer_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Cancel any asynchronous wait operations associated with the timer. - std::size_t cancel(implementation_type& impl, boost::system::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Cancels one asynchronous wait operation associated with the timer. - std::size_t cancel_one(implementation_type& impl, - boost::system::error_code& ec) - { - return service_impl_.cancel_one(impl, ec); - } - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use expiry().) Get the expiry time for the timer as an - /// absolute time. - time_point expires_at(const implementation_type& impl) const - { - return service_impl_.expiry(impl); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - - /// Get the expiry time for the timer as an absolute time. - time_point expiry(const implementation_type& impl) const - { - return service_impl_.expiry(impl); - } - - /// Set the expiry time for the timer as an absolute time. - std::size_t expires_at(implementation_type& impl, - const time_point& expiry_time, boost::system::error_code& ec) - { - return service_impl_.expires_at(impl, expiry_time, ec); - } - - /// Set the expiry time for the timer relative to now. - std::size_t expires_after(implementation_type& impl, - const duration& expiry_time, boost::system::error_code& ec) - { - return service_impl_.expires_after(impl, expiry_time, ec); - } - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use expiry().) Get the expiry time for the timer relative to - /// now. - duration expires_from_now(const implementation_type& impl) const - { - typedef detail::chrono_time_traits<Clock, WaitTraits> traits; - return traits::subtract(service_impl_.expiry(impl), traits::now()); - } - - /// (Deprecated: Use expires_after().) Set the expiry time for the timer - /// relative to now. - std::size_t expires_from_now(implementation_type& impl, - const duration& expiry_time, boost::system::error_code& ec) - { - return service_impl_.expires_after(impl, expiry_time, ec); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - - // Perform a blocking wait on the timer. - void wait(implementation_type& impl, boost::system::error_code& ec) - { - service_impl_.wait(impl, ec); - } - - // Start an asynchronous wait on the timer. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_WAITABLE_TIMER_SERVICE_HPP diff --git a/boost/asio/windows/basic_handle.hpp b/boost/asio/windows/basic_handle.hpp deleted file mode 100644 index ce7d0e8fa0..0000000000 --- a/boost/asio/windows/basic_handle.hpp +++ /dev/null @@ -1,275 +0,0 @@ -// -// windows/basic_handle.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP -#define BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ - || defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ - || defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -#include <boost/asio/basic_io_object.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/error.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace windows { - -/// Provides Windows handle functionality. -/** - * The windows::basic_handle class template provides the ability to wrap a - * Windows handle. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template <typename HandleService> -class basic_handle - : public basic_io_object<HandleService> -{ -public: - /// The native representation of a handle. - typedef typename HandleService::native_handle_type native_handle_type; - - /// A basic_handle is always the lowest layer. - typedef basic_handle<HandleService> lowest_layer_type; - - /// Construct a basic_handle without opening it. - /** - * This constructor creates a handle without opening it. - * - * @param io_context The io_context object that the handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - */ - explicit basic_handle(boost::asio::io_context& io_context) - : basic_io_object<HandleService>(io_context) - { - } - - /// Construct a basic_handle on an existing native handle. - /** - * This constructor creates a handle object to hold an existing native handle. - * - * @param io_context The io_context object that the handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - * - * @param handle A native handle. - * - * @throws boost::system::system_error Thrown on failure. - */ - basic_handle(boost::asio::io_context& io_context, - const native_handle_type& handle) - : basic_io_object<HandleService>(io_context) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), handle, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a basic_handle from another. - /** - * This constructor moves a handle from one object to another. - * - * @param other The other basic_handle object from which the move will occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_handle(io_context&) constructor. - */ - basic_handle(basic_handle&& other) - : basic_io_object<HandleService>( - BOOST_ASIO_MOVE_CAST(basic_handle)(other)) - { - } - - /// Move-assign a basic_handle from another. - /** - * This assignment operator moves a handle from one object to another. - * - * @param other The other basic_handle object from which the move will occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_handle(io_context&) constructor. - */ - basic_handle& operator=(basic_handle&& other) - { - basic_io_object<HandleService>::operator=( - BOOST_ASIO_MOVE_CAST(basic_handle)(other)); - return *this; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since a basic_handle cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Get a const reference to the lowest layer. - /** - * This function returns a const reference to the lowest layer in a stack of - * layers. Since a basic_handle cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A const reference to the lowest layer in the stack of layers. - * Ownership is not transferred to the caller. - */ - const lowest_layer_type& lowest_layer() const - { - return *this; - } - - /// Assign an existing native handle to the handle. - /* - * This function opens the handle to hold an existing native handle. - * - * @param handle A native handle. - * - * @throws boost::system::system_error Thrown on failure. - */ - void assign(const native_handle_type& handle) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), handle, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - - /// Assign an existing native handle to the handle. - /* - * This function opens the handle to hold an existing native handle. - * - * @param handle A native handle. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle, - boost::system::error_code& ec) - { - this->get_service().assign(this->get_implementation(), handle, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the handle is open. - bool is_open() const - { - return this->get_service().is_open(this->get_implementation()); - } - - /// Close the handle. - /** - * This function is used to close the handle. Any asynchronous read or write - * operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void close() - { - boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "close"); - } - - /// Close the handle. - /** - * This function is used to close the handle. Any asynchronous read or write - * operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) - { - this->get_service().close(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native handle representation. - /** - * This function may be used to obtain the underlying representation of the - * handle. This is intended to allow access to native handle functionality - * that is not otherwise provided. - */ - native_handle_type native_handle() - { - return this->get_service().native_handle(this->get_implementation()); - } - - /// Cancel all asynchronous operations associated with the handle. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void cancel() - { - boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "cancel"); - } - - /// Cancel all asynchronous operations associated with the handle. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) - { - this->get_service().cancel(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - -protected: - /// Protected destructor to prevent deletion through this type. - ~basic_handle() - { - } -}; - -} // namespace windows -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) - // || defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) - // || defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP diff --git a/boost/asio/windows/basic_object_handle.hpp b/boost/asio/windows/basic_object_handle.hpp index b4a2565e23..9519bc735e 100644 --- a/boost/asio/windows/basic_object_handle.hpp +++ b/boost/asio/windows/basic_object_handle.hpp @@ -2,7 +2,7 @@ // windows/basic_object_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -18,15 +18,20 @@ #include <boost/asio/detail/config.hpp> -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \ || defined(GENERATING_DOCUMENTATION) +#include <boost/asio/async_result.hpp> +#include <boost/asio/detail/io_object_impl.hpp> #include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/detail/win_object_handle_service.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/windows/basic_handle.hpp> -#include <boost/asio/windows/object_handle_service.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> + +#if defined(BOOST_ASIO_HAS_MOVE) +# include <utility> +#endif // defined(BOOST_ASIO_HAS_MOVE) #include <boost/asio/detail/push_options.hpp> @@ -36,86 +41,284 @@ namespace windows { /// Provides object-oriented handle functionality. /** - * The windows::basic_object_handle class template provides asynchronous and - * blocking object-oriented handle functionality. + * The windows::basic_object_handle class provides asynchronous and blocking + * object-oriented handle functionality. * * @par Thread Safety * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename ObjectHandleService = object_handle_service> +template <typename Executor = executor> class basic_object_handle - : public basic_handle<ObjectHandleService> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + /// The native representation of a handle. - typedef typename ObjectHandleService::native_handle_type native_handle_type; +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef boost::asio::detail::win_object_handle_service::native_handle_type + native_handle_type; +#endif + + /// An object handle is always the lowest layer. + typedef basic_object_handle lowest_layer_type; - /// Construct a basic_object_handle without opening it. + /// Construct an object handle without opening it. /** * This constructor creates an object handle without opening it. * - * @param io_context The io_context object that the object handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. + * @param ex The I/O executor that the object handle will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * object handle. */ - explicit basic_object_handle(boost::asio::io_context& io_context) - : basic_handle<ObjectHandleService>(io_context) + explicit basic_object_handle(const executor_type& ex) + : impl_(ex) { } - /// Construct a basic_object_handle on an existing native handle. + /// Construct an object handle without opening it. + /** + * This constructor creates an object handle without opening it. + * + * @param context An execution context which provides the I/O executor that + * the object handle will use, by default, to dispatch handlers for any + * asynchronous operations performed on the object handle. + */ + template <typename ExecutionContext> + explicit basic_object_handle(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value, + basic_object_handle + >::type* = 0) + : impl_(context) + { + } + + /// Construct an object handle on an existing native handle. /** * This constructor creates an object handle object to hold an existing native * handle. * - * @param io_context The io_context object that the object handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. + * @param ex The I/O executor that the object handle will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * object handle. * * @param native_handle The new underlying handle implementation. * * @throws boost::system::system_error Thrown on failure. */ - basic_object_handle(boost::asio::io_context& io_context, + basic_object_handle(const executor_type& ex, const native_handle_type& native_handle) - : basic_handle<ObjectHandleService>(io_context, native_handle) + : impl_(ex) { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), native_handle, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct an object handle on an existing native handle. + /** + * This constructor creates an object handle object to hold an existing native + * handle. + * + * @param context An execution context which provides the I/O executor that + * the object handle will use, by default, to dispatch handlers for any + * asynchronous operations performed on the object handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_object_handle(ExecutionContext& context, + const native_handle_type& native_handle, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), native_handle, ec); + boost::asio::detail::throw_error(ec, "assign"); } #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a basic_object_handle from another. + /// Move-construct an object handle from another. /** * This constructor moves an object handle from one object to another. * - * @param other The other basic_object_handle object from which the move will + * @param other The other object handle object from which the move will * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_object_handle(io_context&) constructor. + * constructed using the @c basic_object_handle(const executor_type&) + * constructor. */ basic_object_handle(basic_object_handle&& other) - : basic_handle<ObjectHandleService>( - BOOST_ASIO_MOVE_CAST(basic_object_handle)(other)) + : impl_(std::move(other.impl_)) { } - /// Move-assign a basic_object_handle from another. + /// Move-assign an object handle from another. /** * This assignment operator moves an object handle from one object to another. * - * @param other The other basic_object_handle object from which the move will + * @param other The other object handle object from which the move will * occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_object_handle(io_context&) constructor. + * constructed using the @c basic_object_handle(const executor_type&) + * constructor. */ basic_object_handle& operator=(basic_object_handle&& other) { - basic_handle<ObjectHandleService>::operator=( - BOOST_ASIO_MOVE_CAST(basic_object_handle)(other)); + impl_ = std::move(other.impl_); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return impl_.get_executor(); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since an object handle cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since an object handle cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param handle A native handle. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_handle_type& handle) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), handle, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param handle A native handle. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle, + boost::system::error_code& ec) + { + impl_.get_service().assign(impl_.get_implementation(), handle, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the handle is open. + bool is_open() const + { + return impl_.get_service().is_open(impl_.get_implementation()); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + impl_.get_service().close(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "close"); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) + { + impl_.get_service().close(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get the native handle representation. + /** + * This function may be used to obtain the underlying representation of the + * handle. This is intended to allow access to native handle functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return impl_.get_service().native_handle(impl_.get_implementation()); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + impl_.get_service().cancel(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) + { + impl_.get_service().cancel(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + /// Perform a blocking wait on the object handle. /** * This function is used to wait for the object handle to be set to the @@ -127,7 +330,7 @@ public: void wait() { boost::system::error_code ec; - this->get_service().wait(this->get_implementation(), ec); + impl_.get_service().wait(impl_.get_implementation(), ec); boost::asio::detail::throw_error(ec, "wait"); } @@ -141,7 +344,7 @@ public: */ void wait(boost::system::error_code& ec) { - this->get_service().wait(this->get_implementation(), ec); + impl_.get_service().wait(impl_.get_implementation(), ec); } /// Start an asynchronous wait on the object handle. @@ -156,18 +359,31 @@ public: * const boost::system::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename WaitHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, void (boost::system::error_code)) async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler) { - return this->get_service().async_wait(this->get_implementation(), - BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); + boost::asio::async_completion<WaitHandler, + void (boost::system::error_code)> init(handler); + + impl_.get_service().async_wait(impl_.get_implementation(), + init.completion_handler, impl_.get_implementation_executor()); + + return init.result.get(); } + +private: + // Disallow copying and assignment. + basic_object_handle(const basic_object_handle&) BOOST_ASIO_DELETED; + basic_object_handle& operator=(const basic_object_handle&) BOOST_ASIO_DELETED; + + boost::asio::detail::io_object_impl< + boost::asio::detail::win_object_handle_service, Executor> impl_; }; } // namespace windows @@ -179,6 +395,4 @@ public: #endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) // || defined(GENERATING_DOCUMENTATION) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP diff --git a/boost/asio/windows/basic_overlapped_handle.hpp b/boost/asio/windows/basic_overlapped_handle.hpp new file mode 100644 index 0000000000..ccce21fecb --- /dev/null +++ b/boost/asio/windows/basic_overlapped_handle.hpp @@ -0,0 +1,355 @@ +// +// windows/basic_overlapped_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_BASIC_OVERLAPPED_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_BASIC_OVERLAPPED_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +#include <cstddef> +#include <boost/asio/async_result.hpp> +#include <boost/asio/detail/io_object_impl.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/detail/win_iocp_handle_service.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/execution_context.hpp> +#include <boost/asio/executor.hpp> + +#if defined(BOOST_ASIO_HAS_MOVE) +# include <utility> +#endif // defined(BOOST_ASIO_HAS_MOVE) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace windows { + +/// Provides Windows handle functionality for objects that support +/// overlapped I/O. +/** + * The windows::overlapped_handle class provides the ability to wrap a Windows + * handle. The underlying object referred to by the handle must support + * overlapped I/O. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Executor = executor> +class basic_overlapped_handle +{ +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// The native representation of a handle. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef boost::asio::detail::win_iocp_handle_service::native_handle_type + native_handle_type; +#endif + + /// An overlapped_handle is always the lowest layer. + typedef basic_overlapped_handle lowest_layer_type; + + /// Construct an overlapped handle without opening it. + /** + * This constructor creates an overlapped handle without opening it. + * + * @param ex The I/O executor that the overlapped handle will use, by default, + * to dispatch handlers for any asynchronous operations performed on the + * overlapped handle. + */ + explicit basic_overlapped_handle(const executor_type& ex) + : impl_(ex) + { + } + + /// Construct an overlapped handle without opening it. + /** + * This constructor creates an overlapped handle without opening it. + * + * @param context An execution context which provides the I/O executor that + * the overlapped handle will use, by default, to dispatch handlers for any + * asynchronous operations performed on the overlapped handle. + */ + template <typename ExecutionContext> + explicit basic_overlapped_handle(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value, + basic_overlapped_handle + >::type* = 0) + : impl_(context) + { + } + + /// Construct an overlapped handle on an existing native handle. + /** + * This constructor creates an overlapped handle object to hold an existing + * native handle. + * + * @param ex The I/O executor that the overlapped handle will use, by default, + * to dispatch handlers for any asynchronous operations performed on the + * overlapped handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_overlapped_handle(const executor_type& ex, + const native_handle_type& native_handle) + : impl_(ex) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), native_handle, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Construct an overlapped handle on an existing native handle. + /** + * This constructor creates an overlapped handle object to hold an existing + * native handle. + * + * @param context An execution context which provides the I/O executor that + * the overlapped handle will use, by default, to dispatch handlers for any + * asynchronous operations performed on the overlapped handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_overlapped_handle(ExecutionContext& context, + const native_handle_type& native_handle, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), native_handle, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct an overlapped handle from another. + /** + * This constructor moves a handle from one object to another. + * + * @param other The other overlapped handle object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c overlapped_handle(const executor_type&) + * constructor. + */ + basic_overlapped_handle(basic_overlapped_handle&& other) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign an overlapped handle from another. + /** + * This assignment operator moves a handle from one object to another. + * + * @param other The other overlapped handle object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c overlapped_handle(const executor_type&) + * constructor. + */ + basic_overlapped_handle& operator=(basic_overlapped_handle&& other) + { + impl_ = std::move(other.impl_); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Get the executor associated with the object. + executor_type get_executor() BOOST_ASIO_NOEXCEPT + { + return impl_.get_executor(); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since an overlapped_handle cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since an overlapped_handle cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param handle A native handle. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_handle_type& handle) + { + boost::system::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), handle, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param handle A native handle. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle, + boost::system::error_code& ec) + { + impl_.get_service().assign(impl_.get_implementation(), handle, ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the handle is open. + bool is_open() const + { + return impl_.get_service().is_open(impl_.get_implementation()); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + impl_.get_service().close(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "close"); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) + { + impl_.get_service().close(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get the native handle representation. + /** + * This function may be used to obtain the underlying representation of the + * handle. This is intended to allow access to native handle functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return impl_.get_service().native_handle(impl_.get_implementation()); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + impl_.get_service().cancel(impl_.get_implementation(), ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) + { + impl_.get_service().cancel(impl_.get_implementation(), ec); + BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + /** + * This function destroys the handle, cancelling any outstanding asynchronous + * wait operations associated with the handle as if by calling @c cancel. + */ + ~basic_overlapped_handle() + { + } + + boost::asio::detail::io_object_impl< + boost::asio::detail::win_iocp_handle_service, Executor> impl_; + +private: + // Disallow copying and assignment. + basic_overlapped_handle(const basic_overlapped_handle&) BOOST_ASIO_DELETED; + basic_overlapped_handle& operator=( + const basic_overlapped_handle&) BOOST_ASIO_DELETED; +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_WINDOWS_BASIC_OVERLAPPED_HANDLE_HPP diff --git a/boost/asio/windows/basic_random_access_handle.hpp b/boost/asio/windows/basic_random_access_handle.hpp index 53765e1766..5f0d6d48c6 100644 --- a/boost/asio/windows/basic_random_access_handle.hpp +++ b/boost/asio/windows/basic_random_access_handle.hpp @@ -2,7 +2,7 @@ // windows/basic_random_access_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -16,19 +16,11 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +#include <boost/asio/windows/basic_overlapped_handle.hpp> #if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ || defined(GENERATING_DOCUMENTATION) -#include <cstddef> -#include <boost/asio/detail/handler_type_requirements.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/windows/basic_handle.hpp> -#include <boost/asio/windows/random_access_handle_service.hpp> - #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -37,89 +29,136 @@ namespace windows { /// Provides random-access handle functionality. /** - * The windows::basic_random_access_handle class template provides asynchronous - * and blocking random-access handle functionality. + * The windows::basic_random_access_handle class provides asynchronous and + * blocking random-access handle functionality. * * @par Thread Safety * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template <typename RandomAccessHandleService = random_access_handle_service> +template <typename Executor = executor> class basic_random_access_handle - : public basic_handle<RandomAccessHandleService> + : public basic_overlapped_handle<Executor> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + /// The native representation of a handle. - typedef typename RandomAccessHandleService::native_handle_type +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef boost::asio::detail::win_iocp_handle_service::native_handle_type native_handle_type; +#endif - /// Construct a basic_random_access_handle without opening it. + /// Construct a random-access handle without opening it. + /** + * This constructor creates a random-access handle without opening it. + * + * @param ex The I/O executor that the random-access handle will use, by + * default, to dispatch handlers for any asynchronous operations performed on + * the random-access handle. + */ + explicit basic_random_access_handle(const executor_type& ex) + : basic_overlapped_handle<Executor>(ex) + { + } + + /// Construct a random-access handle without opening it. /** * This constructor creates a random-access handle without opening it. The - * handle needs to be opened before data can be written to or read from it. + * handle needs to be opened or assigned before data can be sent or received + * on it. * - * @param io_context The io_context object that the random-access handle will - * use to dispatch handlers for any asynchronous operations performed on the - * handle. + * @param context An execution context which provides the I/O executor that + * the random-access handle will use, by default, to dispatch handlers for any + * asynchronous operations performed on the random-access handle. */ - explicit basic_random_access_handle(boost::asio::io_context& io_context) - : basic_handle<RandomAccessHandleService>(io_context) + template <typename ExecutionContext> + explicit basic_random_access_handle(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value, + basic_random_access_handle + >::type* = 0) + : basic_overlapped_handle<Executor>(context) { } - /// Construct a basic_random_access_handle on an existing native handle. + /// Construct a random-access handle on an existing native handle. /** * This constructor creates a random-access handle object to hold an existing * native handle. * - * @param io_context The io_context object that the random-access handle will - * use to dispatch handlers for any asynchronous operations performed on the - * handle. + * @param ex The I/O executor that the random-access handle will use, by + * default, to dispatch handlers for any asynchronous operations performed on + * the random-access handle. * * @param handle The new underlying handle implementation. * * @throws boost::system::system_error Thrown on failure. */ - basic_random_access_handle(boost::asio::io_context& io_context, + basic_random_access_handle(const executor_type& ex, const native_handle_type& handle) - : basic_handle<RandomAccessHandleService>(io_context, handle) + : basic_overlapped_handle<Executor>(ex, handle) + { + } + + /// Construct a random-access handle on an existing native handle. + /** + * This constructor creates a random-access handle object to hold an existing + * native handle. + * + * @param context An execution context which provides the I/O executor that + * the random-access handle will use, by default, to dispatch handlers for any + * asynchronous operations performed on the random-access handle. + * + * @param handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_random_access_handle(ExecutionContext& context, + const native_handle_type& handle, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_overlapped_handle<Executor>(context, handle) { } #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a basic_random_access_handle from another. + /// Move-construct a random-access handle from another. /** * This constructor moves a random-access handle from one object to another. * - * @param other The other basic_random_access_handle object from which the + * @param other The other random-access handle object from which the * move will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_random_access_handle(io_context&) + * constructed using the @c basic_random_access_handle(const executor_type&) * constructor. */ basic_random_access_handle(basic_random_access_handle&& other) - : basic_handle<RandomAccessHandleService>( - BOOST_ASIO_MOVE_CAST(basic_random_access_handle)(other)) + : basic_overlapped_handle<Executor>(std::move(other)) { } - /// Move-assign a basic_random_access_handle from another. + /// Move-assign a random-access handle from another. /** * This assignment operator moves a random-access handle from one object to * another. * - * @param other The other basic_random_access_handle object from which the + * @param other The other random-access handle object from which the * move will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_random_access_handle(io_context&) + * constructed using the @c basic_random_access_handle(const executor_type&) * constructor. */ basic_random_access_handle& operator=(basic_random_access_handle&& other) { - basic_handle<RandomAccessHandleService>::operator=( - BOOST_ASIO_MOVE_CAST(basic_random_access_handle)(other)); + basic_overlapped_handle<Executor>::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -158,8 +197,8 @@ public: const ConstBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().write_some_at( - this->get_implementation(), offset, buffers, ec); + std::size_t s = this->impl_.get_service().write_some_at( + this->impl_.get_implementation(), offset, buffers, ec); boost::asio::detail::throw_error(ec, "write_some_at"); return s; } @@ -186,8 +225,8 @@ public: std::size_t write_some_at(uint64_t offset, const ConstBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().write_some_at( - this->get_implementation(), offset, buffers, ec); + return this->impl_.get_service().write_some_at( + this->impl_.get_implementation(), offset, buffers, ec); } /// Start an asynchronous write at the specified offset. @@ -210,9 +249,9 @@ public: * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write_at function if you need to ensure that @@ -238,8 +277,15 @@ public: // not meet the documented type requirements for a WriteHandler. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - return this->get_service().async_write_some_at(this->get_implementation(), - offset, buffers, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + boost::asio::async_completion<WriteHandler, + void (boost::system::error_code, std::size_t)> init(handler); + + this->impl_.get_service().async_write_some_at( + this->impl_.get_implementation(), offset, + buffers, init.completion_handler, + this->impl_.get_implementation_executor()); + + return init.result.get(); } /// Read some data from the handle at the specified offset. @@ -277,8 +323,8 @@ public: const MutableBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().read_some_at( - this->get_implementation(), offset, buffers, ec); + std::size_t s = this->impl_.get_service().read_some_at( + this->impl_.get_implementation(), offset, buffers, ec); boost::asio::detail::throw_error(ec, "read_some_at"); return s; } @@ -306,8 +352,8 @@ public: std::size_t read_some_at(uint64_t offset, const MutableBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().read_some_at( - this->get_implementation(), offset, buffers, ec); + return this->impl_.get_service().read_some_at( + this->impl_.get_implementation(), offset, buffers, ec); } /// Start an asynchronous read at the specified offset. @@ -330,9 +376,9 @@ public: * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read_at function if you need to ensure that @@ -359,8 +405,15 @@ public: // not meet the documented type requirements for a ReadHandler. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - return this->get_service().async_read_some_at(this->get_implementation(), - offset, buffers, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + boost::asio::async_completion<ReadHandler, + void (boost::system::error_code, std::size_t)> init(handler); + + this->impl_.get_service().async_read_some_at( + this->impl_.get_implementation(), offset, + buffers, init.completion_handler, + this->impl_.get_implementation_executor()); + + return init.result.get(); } }; @@ -373,6 +426,4 @@ public: #endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) // || defined(GENERATING_DOCUMENTATION) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP diff --git a/boost/asio/windows/basic_stream_handle.hpp b/boost/asio/windows/basic_stream_handle.hpp index 8063987983..f8d50d552c 100644 --- a/boost/asio/windows/basic_stream_handle.hpp +++ b/boost/asio/windows/basic_stream_handle.hpp @@ -2,7 +2,7 @@ // windows/basic_stream_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -16,19 +16,11 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +#include <boost/asio/windows/basic_overlapped_handle.hpp> #if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ || defined(GENERATING_DOCUMENTATION) -#include <cstddef> -#include <boost/asio/detail/handler_type_requirements.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/windows/basic_handle.hpp> -#include <boost/asio/windows/stream_handle_service.hpp> - #include <boost/asio/detail/push_options.hpp> namespace boost { @@ -37,8 +29,8 @@ namespace windows { /// Provides stream-oriented handle functionality. /** - * The windows::basic_stream_handle class template provides asynchronous and - * blocking stream-oriented handle functionality. + * The windows::basic_stream_handle class provides asynchronous and blocking + * stream-oriented handle functionality. * * @par Thread Safety * @e Distinct @e objects: Safe.@n @@ -47,78 +39,126 @@ namespace windows { * @par Concepts: * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. */ -template <typename StreamHandleService = stream_handle_service> +template <typename Executor = executor> class basic_stream_handle - : public basic_handle<StreamHandleService> + : public basic_overlapped_handle<Executor> { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + /// The native representation of a handle. - typedef typename StreamHandleService::native_handle_type native_handle_type; +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef boost::asio::detail::win_iocp_handle_service::native_handle_type + native_handle_type; +#endif - /// Construct a basic_stream_handle without opening it. + /// Construct a stream handle without opening it. + /** + * This constructor creates a stream handle without opening it. + * + * @param ex The I/O executor that the stream handle will use, by default, to + * dispatch handlers for any asynchronous operations performed on the stream + * handle. + */ + explicit basic_stream_handle(const executor_type& ex) + : basic_overlapped_handle<Executor>(ex) + { + } + + /// Construct a stream handle without opening it. /** * This constructor creates a stream handle without opening it. The handle - * needs to be opened and then connected or accepted before data can be sent - * or received on it. + * needs to be opened or assigned before data can be sent or received on it. * - * @param io_context The io_context object that the stream handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. + * @param context An execution context which provides the I/O executor that + * the stream handle will use, by default, to dispatch handlers for any + * asynchronous operations performed on the stream handle. */ - explicit basic_stream_handle(boost::asio::io_context& io_context) - : basic_handle<StreamHandleService>(io_context) + template <typename ExecutionContext> + explicit basic_stream_handle(ExecutionContext& context, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value, + basic_stream_handle + >::type* = 0) + : basic_overlapped_handle<Executor>(context) { } - /// Construct a basic_stream_handle on an existing native handle. + /// Construct a stream handle on an existing native handle. /** * This constructor creates a stream handle object to hold an existing native * handle. * - * @param io_context The io_context object that the stream handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. + * @param ex The I/O executor that the stream handle will use, by default, to + * dispatch handlers for any asynchronous operations performed on the stream + * handle. * * @param handle The new underlying handle implementation. * * @throws boost::system::system_error Thrown on failure. */ - basic_stream_handle(boost::asio::io_context& io_context, - const native_handle_type& handle) - : basic_handle<StreamHandleService>(io_context, handle) + basic_stream_handle(const executor_type& ex, const native_handle_type& handle) + : basic_overlapped_handle<Executor>(ex, handle) + { + } + + /// Construct a stream handle on an existing native handle. + /** + * This constructor creates a stream handle object to hold an existing native + * handle. + * + * @param context An execution context which provides the I/O executor that + * the stream handle will use, by default, to dispatch handlers for any + * asynchronous operations performed on the stream handle. + * + * @param handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_stream_handle(ExecutionContext& context, + const native_handle_type& handle, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : basic_overlapped_handle<Executor>(context, handle) { } #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a basic_stream_handle from another. + /// Move-construct a stream handle from another. /** * This constructor moves a stream handle from one object to another. * - * @param other The other basic_stream_handle object from which the move + * @param other The other stream handle object from which the move * will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_stream_handle(io_context&) constructor. + * constructed using the @c basic_stream_handle(const executor_type&) + * constructor. */ basic_stream_handle(basic_stream_handle&& other) - : basic_handle<StreamHandleService>( - BOOST_ASIO_MOVE_CAST(basic_stream_handle)(other)) + : basic_overlapped_handle<Executor>(std::move(other)) { } - /// Move-assign a basic_stream_handle from another. + /// Move-assign a stream handle from another. /** * This assignment operator moves a stream handle from one object to * another. * - * @param other The other basic_stream_handle object from which the move - * will occur. + * @param other The other stream handle object from which the move will occur. * * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c basic_stream_handle(io_context&) constructor. + * constructed using the @c basic_stream_handle(const executor_type&) + * constructor. */ basic_stream_handle& operator=(basic_stream_handle&& other) { - basic_handle<StreamHandleService>::operator=( - BOOST_ASIO_MOVE_CAST(basic_stream_handle)(other)); + basic_overlapped_handle<Executor>::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -154,8 +194,8 @@ public: std::size_t write_some(const ConstBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().write_some( - this->get_implementation(), buffers, ec); + std::size_t s = this->impl_.get_service().write_some( + this->impl_.get_implementation(), buffers, ec); boost::asio::detail::throw_error(ec, "write_some"); return s; } @@ -180,8 +220,8 @@ public: std::size_t write_some(const ConstBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().write_some( - this->get_implementation(), buffers, ec); + return this->impl_.get_service().write_some( + this->impl_.get_implementation(), buffers, ec); } /// Start an asynchronous write. @@ -202,9 +242,9 @@ public: * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all @@ -229,8 +269,15 @@ public: // not meet the documented type requirements for a WriteHandler. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - return this->get_service().async_write_some(this->get_implementation(), - buffers, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + boost::asio::async_completion<WriteHandler, + void (boost::system::error_code, std::size_t)> 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(); } /// Read some data from the handle. @@ -265,8 +312,8 @@ public: std::size_t read_some(const MutableBufferSequence& buffers) { boost::system::error_code ec; - std::size_t s = this->get_service().read_some( - this->get_implementation(), buffers, ec); + std::size_t s = this->impl_.get_service().read_some( + this->impl_.get_implementation(), buffers, ec); boost::asio::detail::throw_error(ec, "read_some"); return s; } @@ -292,8 +339,8 @@ public: std::size_t read_some(const MutableBufferSequence& buffers, boost::system::error_code& ec) { - return this->get_service().read_some( - this->get_implementation(), buffers, ec); + return this->impl_.get_service().read_some( + this->impl_.get_implementation(), buffers, ec); } /// Start an asynchronous read. @@ -314,9 +361,9 @@ public: * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the @@ -342,8 +389,15 @@ public: // not meet the documented type requirements for a ReadHandler. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - return this->get_service().async_read_some(this->get_implementation(), - buffers, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + boost::asio::async_completion<ReadHandler, + void (boost::system::error_code, std::size_t)> 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(); } }; @@ -356,6 +410,4 @@ public: #endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) // || defined(GENERATING_DOCUMENTATION) -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP diff --git a/boost/asio/windows/object_handle.hpp b/boost/asio/windows/object_handle.hpp index 45eb23f4d8..6cde16627a 100644 --- a/boost/asio/windows/object_handle.hpp +++ b/boost/asio/windows/object_handle.hpp @@ -2,7 +2,7 @@ // windows/object_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -21,362 +21,19 @@ #if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \ || defined(GENERATING_DOCUMENTATION) -#include <boost/asio/async_result.hpp> -#include <boost/asio/basic_io_object.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/detail/win_object_handle_service.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#if defined(BOOST_ASIO_HAS_MOVE) -# include <utility> -#endif // defined(BOOST_ASIO_HAS_MOVE) - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/windows/basic_object_handle.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#define BOOST_ASIO_SVC_T boost::asio::detail::win_object_handle_service - -#include <boost/asio/detail/push_options.hpp> +#include <boost/asio/windows/basic_object_handle.hpp> namespace boost { namespace asio { namespace windows { -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -// Typedef for the typical usage of an object handle. +/// Typedef for the typical usage of an object handle. typedef basic_object_handle<> object_handle; -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -/// Provides object-oriented handle functionality. -/** - * The windows::object_handle class provides asynchronous and blocking - * object-oriented handle functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class object_handle - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T> -{ -public: - /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; - - /// The native representation of a handle. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type; -#endif - - /// An object_handle is always the lowest layer. - typedef object_handle lowest_layer_type; - - /// Construct an object_handle without opening it. - /** - * This constructor creates an object handle without opening it. - * - * @param io_context The io_context object that the object handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - */ - explicit object_handle(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - } - - /// Construct an object_handle on an existing native handle. - /** - * This constructor creates an object handle object to hold an existing native - * handle. - * - * @param io_context The io_context object that the object handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - * - * @param native_handle The new underlying handle implementation. - * - * @throws boost::system::system_error Thrown on failure. - */ - object_handle(boost::asio::io_context& io_context, - const native_handle_type& native_handle) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), native_handle, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct an object_handle from another. - /** - * This constructor moves an object handle from one object to another. - * - * @param other The other object_handle object from which the move will - * occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c object_handle(io_context&) constructor. - */ - object_handle(object_handle&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) - { - } - - /// Move-assign an object_handle from another. - /** - * This assignment operator moves an object handle from one object to another. - * - * @param other The other object_handle object from which the move will - * occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c object_handle(io_context&) constructor. - */ - object_handle& operator=(object_handle&& other) - { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); - return *this; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - - /// Get the executor associated with the object. - executor_type get_executor() BOOST_ASIO_NOEXCEPT - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since an object_handle cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Get a const reference to the lowest layer. - /** - * This function returns a const reference to the lowest layer in a stack of - * layers. Since an object_handle cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A const reference to the lowest layer in the stack of layers. - * Ownership is not transferred to the caller. - */ - const lowest_layer_type& lowest_layer() const - { - return *this; - } - - /// Assign an existing native handle to the handle. - /* - * This function opens the handle to hold an existing native handle. - * - * @param handle A native handle. - * - * @throws boost::system::system_error Thrown on failure. - */ - void assign(const native_handle_type& handle) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), handle, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - - /// Assign an existing native handle to the handle. - /* - * This function opens the handle to hold an existing native handle. - * - * @param handle A native handle. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle, - boost::system::error_code& ec) - { - this->get_service().assign(this->get_implementation(), handle, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the handle is open. - bool is_open() const - { - return this->get_service().is_open(this->get_implementation()); - } - - /// Close the handle. - /** - * This function is used to close the handle. Any asynchronous read or write - * operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void close() - { - boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "close"); - } - - /// Close the handle. - /** - * This function is used to close the handle. Any asynchronous read or write - * operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) - { - this->get_service().close(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native handle representation. - /** - * This function may be used to obtain the underlying representation of the - * handle. This is intended to allow access to native handle functionality - * that is not otherwise provided. - */ - native_handle_type native_handle() - { - return this->get_service().native_handle(this->get_implementation()); - } - - /// Cancel all asynchronous operations associated with the handle. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void cancel() - { - boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "cancel"); - } - - /// Cancel all asynchronous operations associated with the handle. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) - { - this->get_service().cancel(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Perform a blocking wait on the object handle. - /** - * This function is used to wait for the object handle to be set to the - * signalled state. This function blocks and does not return until the object - * handle has been set to the signalled state. - * - * @throws boost::system::system_error Thrown on failure. - */ - void wait() - { - boost::system::error_code ec; - this->get_service().wait(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "wait"); - } - - /// Perform a blocking wait on the object handle. - /** - * This function is used to wait for the object handle to be set to the - * signalled state. This function blocks and does not return until the object - * handle has been set to the signalled state. - * - * @param ec Set to indicate what error occurred, if any. - */ - void wait(boost::system::error_code& ec) - { - this->get_service().wait(this->get_implementation(), ec); - } - - /// Start an asynchronous wait on the object handle. - /** - * This function is be used to initiate an asynchronous wait against the - * object handle. It always returns immediately. - * - * @param handler The handler to be called when the object handle is set to - * the signalled state. Copies will be made of the handler as required. The - * function signature of the handler must be: - * @code void handler( - * const boost::system::error_code& error // Result of operation. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - */ - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - boost::asio::async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - this->get_service().async_wait(this->get_implementation(), - init.completion_handler); - - return init.result.get(); - } -}; -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } // namespace windows } // namespace asio } // namespace boost -#include <boost/asio/detail/pop_options.hpp> - -#undef BOOST_ASIO_SVC_T - #endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) // || defined(GENERATING_DOCUMENTATION) diff --git a/boost/asio/windows/object_handle_service.hpp b/boost/asio/windows/object_handle_service.hpp deleted file mode 100644 index 6ff8197990..0000000000 --- a/boost/asio/windows/object_handle_service.hpp +++ /dev/null @@ -1,185 +0,0 @@ -// -// windows/object_handle_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2011 Boris Schaeling (boris@highscore.de) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_WINDOWS_OBJECT_HANDLE_SERVICE_HPP -#define BOOST_ASIO_WINDOWS_OBJECT_HANDLE_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/win_object_handle_service.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace windows { - -/// Default service implementation for an object handle. -class object_handle_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<object_handle_service> -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - -private: - // The type of the platform-specific implementation. - typedef detail::win_object_handle_service service_impl_type; - -public: - /// The type of an object handle implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native handle type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new object handle service for the specified io_context. - explicit object_handle_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base<object_handle_service>(io_context), - service_impl_(io_context) - { - } - - /// Construct a new object handle implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new object handle implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another object handle implementation. - void move_assign(implementation_type& impl, - object_handle_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy an object handle implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Assign an existing native handle to an object handle. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const native_handle_type& handle, boost::system::error_code& ec) - { - service_impl_.assign(impl, handle, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close an object handle implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native handle implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Cancel all asynchronous operations associated with the handle. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - // Wait for a signaled state. - void wait(implementation_type& impl, boost::system::error_code& ec) - { - service_impl_.wait(impl, ec); - } - - /// Start an asynchronous wait. - template <typename WaitHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, - void (boost::system::error_code)) - async_wait(implementation_type& impl, - BOOST_ASIO_MOVE_ARG(WaitHandler) handler) - { - boost::asio::async_completion<WaitHandler, - void (boost::system::error_code)> init(handler); - - service_impl_.async_wait(impl, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace windows -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_WINDOWS_OBJECT_HANDLE_SERVICE_HPP diff --git a/boost/asio/windows/overlapped_handle.hpp b/boost/asio/windows/overlapped_handle.hpp index 16dcbedbb6..e87e7b35c0 100644 --- a/boost/asio/windows/overlapped_handle.hpp +++ b/boost/asio/windows/overlapped_handle.hpp @@ -2,7 +2,7 @@ // windows/overlapped_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -17,317 +17,25 @@ #include <boost/asio/detail/config.hpp> -#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ || defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ || defined(GENERATING_DOCUMENTATION) -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/basic_io_object.hpp> -#include <boost/asio/detail/throw_error.hpp> -#include <boost/asio/detail/win_iocp_handle_service.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#if defined(BOOST_ASIO_HAS_MOVE) -# include <utility> -#endif // defined(BOOST_ASIO_HAS_MOVE) - -#define BOOST_ASIO_SVC_T boost::asio::detail::win_iocp_handle_service - -#include <boost/asio/detail/push_options.hpp> +#include <boost/asio/windows/basic_overlapped_handle.hpp> namespace boost { namespace asio { namespace windows { -/// Provides Windows handle functionality for objects that support -/// overlapped I/O. -/** - * The windows::overlapped_handle class provides the ability to wrap a Windows - * handle. The underlying object referred to by the handle must support - * overlapped I/O. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class overlapped_handle - : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T> -{ -public: - /// The type of the executor associated with the object. - typedef io_context::executor_type executor_type; - - /// The native representation of a handle. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type; -#endif - - /// An overlapped_handle is always the lowest layer. - typedef overlapped_handle lowest_layer_type; - - /// Construct an overlapped_handle without opening it. - /** - * This constructor creates a handle without opening it. - * - * @param io_context The io_context object that the handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - */ - explicit overlapped_handle(boost::asio::io_context& io_context) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - } - - /// Construct an overlapped_handle on an existing native handle. - /** - * This constructor creates a handle object to hold an existing native handle. - * - * @param io_context The io_context object that the handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - * - * @param handle A native handle. - * - * @throws boost::system::system_error Thrown on failure. - */ - overlapped_handle(boost::asio::io_context& io_context, - const native_handle_type& handle) - : basic_io_object<BOOST_ASIO_SVC_T>(io_context) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), handle, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct an overlapped_handle from another. - /** - * This constructor moves a handle from one object to another. - * - * @param other The other overlapped_handle object from which the move will - * occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c overlapped_handle(io_context&) constructor. - */ - overlapped_handle(overlapped_handle&& other) - : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) - { - } - - /// Move-assign an overlapped_handle from another. - /** - * This assignment operator moves a handle from one object to another. - * - * @param other The other overlapped_handle object from which the move will - * occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c overlapped_handle(io_context&) constructor. - */ - overlapped_handle& operator=(overlapped_handle&& other) - { - basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); - return *this; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - -#if !defined(BOOST_ASIO_NO_DEPRECATED) - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_context() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); - } - - /// (Deprecated: Use get_executor().) Get the io_context associated with the - /// object. - /** - * This function may be used to obtain the io_context object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_context object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - boost::asio::io_context& get_io_service() - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(BOOST_ASIO_NO_DEPRECATED) - - /// Get the executor associated with the object. - executor_type get_executor() BOOST_ASIO_NOEXCEPT - { - return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since an overlapped_handle cannot contain any further layers, it - * simply returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Get a const reference to the lowest layer. - /** - * This function returns a const reference to the lowest layer in a stack of - * layers. Since an overlapped_handle cannot contain any further layers, it - * simply returns a reference to itself. - * - * @return A const reference to the lowest layer in the stack of layers. - * Ownership is not transferred to the caller. - */ - const lowest_layer_type& lowest_layer() const - { - return *this; - } - - /// Assign an existing native handle to the handle. - /* - * This function opens the handle to hold an existing native handle. - * - * @param handle A native handle. - * - * @throws boost::system::system_error Thrown on failure. - */ - void assign(const native_handle_type& handle) - { - boost::system::error_code ec; - this->get_service().assign(this->get_implementation(), handle, ec); - boost::asio::detail::throw_error(ec, "assign"); - } - - /// Assign an existing native handle to the handle. - /* - * This function opens the handle to hold an existing native handle. - * - * @param handle A native handle. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle, - boost::system::error_code& ec) - { - this->get_service().assign(this->get_implementation(), handle, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the handle is open. - bool is_open() const - { - return this->get_service().is_open(this->get_implementation()); - } - - /// Close the handle. - /** - * This function is used to close the handle. Any asynchronous read or write - * operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void close() - { - boost::system::error_code ec; - this->get_service().close(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "close"); - } - - /// Close the handle. - /** - * This function is used to close the handle. Any asynchronous read or write - * operations will be cancelled immediately, and will complete with the - * boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) - { - this->get_service().close(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native handle representation. - /** - * This function may be used to obtain the underlying representation of the - * handle. This is intended to allow access to native handle functionality - * that is not otherwise provided. - */ - native_handle_type native_handle() - { - return this->get_service().native_handle(this->get_implementation()); - } - - /// Cancel all asynchronous operations associated with the handle. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @throws boost::system::system_error Thrown on failure. - */ - void cancel() - { - boost::system::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); - boost::asio::detail::throw_error(ec, "cancel"); - } - - /// Cancel all asynchronous operations associated with the handle. - /** - * This function causes all outstanding asynchronous read or write operations - * to finish immediately, and the handlers for cancelled operations will be - * passed the boost::asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) - { - this->get_service().cancel(this->get_implementation(), ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - -protected: - /// Protected destructor to prevent deletion through this type. - /** - * This function destroys the handle, cancelling any outstanding asynchronous - * wait operations associated with the handle as if by calling @c cancel. - */ - ~overlapped_handle() - { - } -}; +/// Typedef for the typical usage of an overlapped handle. +typedef basic_overlapped_handle<> overlapped_handle; } // namespace windows } // namespace asio } // namespace boost -#include <boost/asio/detail/pop_options.hpp> - -#undef BOOST_ASIO_SVC_T - #endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) // || defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) // || defined(GENERATING_DOCUMENTATION) -#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - #endif // BOOST_ASIO_WINDOWS_OVERLAPPED_HANDLE_HPP diff --git a/boost/asio/windows/overlapped_ptr.hpp b/boost/asio/windows/overlapped_ptr.hpp index 8c95ce45f9..a891248ceb 100644 --- a/boost/asio/windows/overlapped_ptr.hpp +++ b/boost/asio/windows/overlapped_ptr.hpp @@ -2,7 +2,7 @@ // windows/overlapped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -50,10 +50,24 @@ public: } /// Construct an overlapped_ptr to contain the specified handler. - template <typename Handler> - explicit overlapped_ptr(boost::asio::io_context& io_context, - BOOST_ASIO_MOVE_ARG(Handler) handler) - : impl_(io_context, BOOST_ASIO_MOVE_CAST(Handler)(handler)) + template <typename ExecutionContext, typename Handler> + explicit overlapped_ptr(ExecutionContext& context, + BOOST_ASIO_MOVE_ARG(Handler) handler, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + : impl_(context.get_executor(), BOOST_ASIO_MOVE_CAST(Handler)(handler)) + { + } + + /// Construct an overlapped_ptr to contain the specified handler. + template <typename Executor, typename Handler> + explicit overlapped_ptr(const Executor& ex, + BOOST_ASIO_MOVE_ARG(Handler) handler, + typename enable_if< + is_executor<Executor>::value + >::type* = 0) + : impl_(ex, BOOST_ASIO_MOVE_CAST(Handler)(handler)) { } @@ -70,11 +84,24 @@ public: /// Reset to contain the specified handler, freeing any current OVERLAPPED /// object. - template <typename Handler> - void reset(boost::asio::io_context& io_context, - BOOST_ASIO_MOVE_ARG(Handler) handler) + template <typename ExecutionContext, typename Handler> + void reset(ExecutionContext& context, BOOST_ASIO_MOVE_ARG(Handler) handler, + typename enable_if< + is_convertible<ExecutionContext&, execution_context&>::value + >::type* = 0) + { + impl_.reset(context.get_executor(), BOOST_ASIO_MOVE_CAST(Handler)(handler)); + } + + /// Reset to contain the specified handler, freeing any current OVERLAPPED + /// object. + template <typename Executor, typename Handler> + void reset(const Executor& ex, BOOST_ASIO_MOVE_ARG(Handler) handler, + typename enable_if< + is_executor<Executor>::value + >::type* = 0) { - impl_.reset(io_context, BOOST_ASIO_MOVE_CAST(Handler)(handler)); + impl_.reset(ex, BOOST_ASIO_MOVE_CAST(Handler)(handler)); } /// Get the contained OVERLAPPED object. diff --git a/boost/asio/windows/random_access_handle.hpp b/boost/asio/windows/random_access_handle.hpp index 4ff62d39df..77ae022f5d 100644 --- a/boost/asio/windows/random_access_handle.hpp +++ b/boost/asio/windows/random_access_handle.hpp @@ -2,7 +2,7 @@ // windows/random_access_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -16,364 +16,23 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> -#include <boost/asio/windows/overlapped_handle.hpp> #if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ || defined(GENERATING_DOCUMENTATION) -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/windows/basic_random_access_handle.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <boost/asio/detail/push_options.hpp> +#include <boost/asio/windows/basic_random_access_handle.hpp> namespace boost { namespace asio { namespace windows { -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -// Typedef for the typical usage of a random-access handle. +/// Typedef for the typical usage of a random-access handle. typedef basic_random_access_handle<> random_access_handle; -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -/// Provides random-access handle functionality. -/** - * The windows::random_access_handle class provides asynchronous and - * blocking random-access handle functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class random_access_handle - : public overlapped_handle -{ -public: - /// Construct a random_access_handle without opening it. - /** - * This constructor creates a random-access handle without opening it. The - * handle needs to be opened before data can be written to or read from it. - * - * @param io_context The io_context object that the random-access handle will - * use to dispatch handlers for any asynchronous operations performed on the - * handle. - */ - explicit random_access_handle(boost::asio::io_context& io_context) - : overlapped_handle(io_context) - { - } - - /// Construct a random_access_handle on an existing native handle. - /** - * This constructor creates a random-access handle object to hold an existing - * native handle. - * - * @param io_context The io_context object that the random-access handle will - * use to dispatch handlers for any asynchronous operations performed on the - * handle. - * - * @param handle The new underlying handle implementation. - * - * @throws boost::system::system_error Thrown on failure. - */ - random_access_handle(boost::asio::io_context& io_context, - const native_handle_type& handle) - : overlapped_handle(io_context, handle) - { - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a random_access_handle from another. - /** - * This constructor moves a random-access handle from one object to another. - * - * @param other The other random_access_handle object from which the - * move will occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c random_access_handle(io_context&) - * constructor. - */ - random_access_handle(random_access_handle&& other) - : overlapped_handle(std::move(other)) - { - } - - /// Move-assign a random_access_handle from another. - /** - * This assignment operator moves a random-access handle from one object to - * another. - * - * @param other The other random_access_handle object from which the - * move will occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c random_access_handle(io_context&) - * constructor. - */ - random_access_handle& operator=(random_access_handle&& other) - { - overlapped_handle::operator=(std::move(other)); - return *this; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Write some data to the handle at the specified offset. - /** - * This function is used to write data to the random-access handle. The - * function call will block until one or more bytes of the data has been - * written successfully, or until an error occurs. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more data buffers to be written to the handle. - * - * @returns The number of bytes written. - * - * @throws boost::system::system_error Thrown on failure. An error code of - * boost::asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some_at operation may not write all of the data. Consider - * using the @ref write_at function if you need to ensure that all data is - * written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * handle.write_some_at(42, boost::asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename ConstBufferSequence> - std::size_t write_some_at(uint64_t offset, - const ConstBufferSequence& buffers) - { - boost::system::error_code ec; - std::size_t s = this->get_service().write_some_at( - this->get_implementation(), offset, buffers, ec); - boost::asio::detail::throw_error(ec, "write_some_at"); - return s; - } - - /// Write some data to the handle at the specified offset. - /** - * This function is used to write data to the random-access handle. The - * function call will block until one or more bytes of the data has been - * written successfully, or until an error occurs. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more data buffers to be written to the handle. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write_at function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template <typename ConstBufferSequence> - std::size_t write_some_at(uint64_t offset, - const ConstBufferSequence& buffers, boost::system::error_code& ec) - { - return this->get_service().write_some_at( - this->get_implementation(), offset, buffers, ec); - } - - /// Start an asynchronous write at the specified offset. - /** - * This function is used to asynchronously write data to the random-access - * handle. The function call always returns immediately. - * - * @param offset The offset at which the data will be written. - * - * @param buffers One or more data buffers to be written to the handle. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write_at function if you need to ensure that - * all data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * handle.async_write_some_at(42, boost::asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_write_some_at(uint64_t offset, - const ConstBufferSequence& buffers, - BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - boost::asio::async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_write_some_at(this->get_implementation(), - offset, buffers, init.completion_handler); - - return init.result.get(); - } - - /// Read some data from the handle at the specified offset. - /** - * This function is used to read data from the random-access handle. The - * function call will block until one or more bytes of data has been read - * successfully, or until an error occurs. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws boost::system::system_error Thrown on failure. An error code of - * boost::asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read_at function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * handle.read_some_at(42, boost::asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename MutableBufferSequence> - std::size_t read_some_at(uint64_t offset, - const MutableBufferSequence& buffers) - { - boost::system::error_code ec; - std::size_t s = this->get_service().read_some_at( - this->get_implementation(), offset, buffers, ec); - boost::asio::detail::throw_error(ec, "read_some_at"); - return s; - } - - /// Read some data from the handle at the specified offset. - /** - * This function is used to read data from the random-access handle. The - * function call will block until one or more bytes of data has been read - * successfully, or until an error occurs. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read_at function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template <typename MutableBufferSequence> - std::size_t read_some_at(uint64_t offset, - const MutableBufferSequence& buffers, boost::system::error_code& ec) - { - return this->get_service().read_some_at( - this->get_implementation(), offset, buffers, ec); - } - - /// Start an asynchronous read at the specified offset. - /** - * This function is used to asynchronously read data from the random-access - * handle. The function call always returns immediately. - * - * @param offset The offset at which the data will be read. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read_at function if you need to ensure that - * the requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * handle.async_read_some_at(42, boost::asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_read_some_at(uint64_t offset, - const MutableBufferSequence& buffers, - BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - boost::asio::async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_read_some_at(this->get_implementation(), - offset, buffers, init.completion_handler); - - return init.result.get(); - } -}; -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } // namespace windows } // namespace asio } // namespace boost -#include <boost/asio/detail/pop_options.hpp> - #endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) // || defined(GENERATING_DOCUMENTATION) diff --git a/boost/asio/windows/random_access_handle_service.hpp b/boost/asio/windows/random_access_handle_service.hpp deleted file mode 100644 index 0ec0773acb..0000000000 --- a/boost/asio/windows/random_access_handle_service.hpp +++ /dev/null @@ -1,216 +0,0 @@ -// -// windows/random_access_handle_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP -#define BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/cstdint.hpp> -#include <boost/asio/detail/win_iocp_handle_service.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace windows { - -/// Default service implementation for a random-access handle. -class random_access_handle_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<random_access_handle_service> -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - -private: - // The type of the platform-specific implementation. - typedef detail::win_iocp_handle_service service_impl_type; - -public: - /// The type of a random-access handle implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native handle type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new random-access handle service for the specified io_context. - explicit random_access_handle_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base< - random_access_handle_service>(io_context), - service_impl_(io_context) - { - } - - /// Construct a new random-access handle implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new random-access handle implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another random-access handle implementation. - void move_assign(implementation_type& impl, - random_access_handle_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a random-access handle implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Assign an existing native handle to a random-access handle. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const native_handle_type& handle, boost::system::error_code& ec) - { - service_impl_.assign(impl, handle, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a random-access handle implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native handle implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Cancel all asynchronous operations associated with the handle. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Write the given data at the specified offset. - template <typename ConstBufferSequence> - std::size_t write_some_at(implementation_type& impl, uint64_t offset, - const ConstBufferSequence& buffers, boost::system::error_code& ec) - { - return service_impl_.write_some_at(impl, offset, buffers, ec); - } - - /// Start an asynchronous write at the specified offset. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_write_some_at(implementation_type& impl, - uint64_t offset, const ConstBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - boost::asio::async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_write_some_at(impl, - offset, buffers, init.completion_handler); - - return init.result.get(); - } - - /// Read some data from the specified offset. - template <typename MutableBufferSequence> - std::size_t read_some_at(implementation_type& impl, uint64_t offset, - const MutableBufferSequence& buffers, boost::system::error_code& ec) - { - return service_impl_.read_some_at(impl, offset, buffers, ec); - } - - /// Start an asynchronous read at the specified offset. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_read_some_at(implementation_type& impl, - uint64_t offset, const MutableBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - boost::asio::async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_read_some_at(impl, - offset, buffers, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace windows -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP diff --git a/boost/asio/windows/stream_handle.hpp b/boost/asio/windows/stream_handle.hpp index a8962b6b12..56e7db033b 100644 --- a/boost/asio/windows/stream_handle.hpp +++ b/boost/asio/windows/stream_handle.hpp @@ -2,7 +2,7 @@ // windows/stream_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -16,348 +16,23 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <boost/asio/detail/config.hpp> -#include <boost/asio/windows/overlapped_handle.hpp> #if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ || defined(GENERATING_DOCUMENTATION) -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -# include <boost/asio/windows/basic_stream_handle.hpp> -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#include <boost/asio/detail/push_options.hpp> +#include <boost/asio/windows/basic_stream_handle.hpp> namespace boost { namespace asio { namespace windows { -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -// Typedef for the typical usage of a stream-oriented handle. +/// Typedef for the typical usage of a stream-oriented handle. typedef basic_stream_handle<> stream_handle; -#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) -/// Provides stream-oriented handle functionality. -/** - * The windows::stream_handle class provides asynchronous and blocking - * stream-oriented handle functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -class stream_handle - : public overlapped_handle -{ -public: - /// Construct a stream_handle without opening it. - /** - * This constructor creates a stream handle without opening it. The handle - * needs to be opened and then connected or accepted before data can be sent - * or received on it. - * - * @param io_context The io_context object that the stream handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - */ - explicit stream_handle(boost::asio::io_context& io_context) - : overlapped_handle(io_context) - { - } - - /// Construct a stream_handle on an existing native handle. - /** - * This constructor creates a stream handle object to hold an existing native - * handle. - * - * @param io_context The io_context object that the stream handle will use to - * dispatch handlers for any asynchronous operations performed on the handle. - * - * @param handle The new underlying handle implementation. - * - * @throws boost::system::system_error Thrown on failure. - */ - stream_handle(boost::asio::io_context& io_context, - const native_handle_type& handle) - : overlapped_handle(io_context, handle) - { - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a stream_handle from another. - /** - * This constructor moves a stream handle from one object to another. - * - * @param other The other stream_handle object from which the move - * will occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c stream_handle(io_context&) constructor. - */ - stream_handle(stream_handle&& other) - : overlapped_handle(std::move(other)) - { - } - - /// Move-assign a stream_handle from another. - /** - * This assignment operator moves a stream handle from one object to - * another. - * - * @param other The other stream_handle object from which the move - * will occur. - * - * @note Following the move, the moved-from object is in the same state as if - * constructed using the @c stream_handle(io_context&) constructor. - */ - stream_handle& operator=(stream_handle&& other) - { - overlapped_handle::operator=(std::move(other)); - return *this; - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Write some data to the handle. - /** - * This function is used to write data to the stream handle. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the handle. - * - * @returns The number of bytes written. - * - * @throws boost::system::system_error Thrown on failure. An error code of - * boost::asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * handle.write_some(boost::asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename ConstBufferSequence> - std::size_t write_some(const ConstBufferSequence& buffers) - { - boost::system::error_code ec; - std::size_t s = this->get_service().write_some( - this->get_implementation(), buffers, ec); - boost::asio::detail::throw_error(ec, "write_some"); - return s; - } - - /// Write some data to the handle. - /** - * This function is used to write data to the stream handle. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the handle. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template <typename ConstBufferSequence> - std::size_t write_some(const ConstBufferSequence& buffers, - boost::system::error_code& ec) - { - return this->get_service().write_some( - this->get_implementation(), buffers, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write data to the stream handle. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be written to the handle. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * handle.async_write_some(boost::asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - BOOST_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. - BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; - - boost::asio::async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_write_some( - this->get_implementation(), buffers, init.completion_handler); - - return init.result.get(); - } - - /// Read some data from the handle. - /** - * This function is used to read data from the stream handle. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws boost::system::system_error Thrown on failure. An error code of - * boost::asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * handle.read_some(boost::asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename MutableBufferSequence> - std::size_t read_some(const MutableBufferSequence& buffers) - { - boost::system::error_code ec; - std::size_t s = this->get_service().read_some( - this->get_implementation(), buffers, ec); - boost::asio::detail::throw_error(ec, "read_some"); - return s; - } - - /// Read some data from the handle. - /** - * This function is used to read data from the stream handle. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template <typename MutableBufferSequence> - std::size_t read_some(const MutableBufferSequence& buffers, - boost::system::error_code& ec) - { - return this->get_service().read_some( - this->get_implementation(), buffers, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read data from the stream handle. - * The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const boost::system::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read function if you need to ensure that the - * requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * handle.async_read_some(boost::asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - BOOST_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. - BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; - - boost::asio::async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - this->get_service().async_read_some( - this->get_implementation(), buffers, init.completion_handler); - - return init.result.get(); - } -}; -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } // namespace windows } // namespace asio } // namespace boost -#include <boost/asio/detail/pop_options.hpp> - #endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) // || defined(GENERATING_DOCUMENTATION) diff --git a/boost/asio/windows/stream_handle_service.hpp b/boost/asio/windows/stream_handle_service.hpp deleted file mode 100644 index d3d47d2236..0000000000 --- a/boost/asio/windows/stream_handle_service.hpp +++ /dev/null @@ -1,212 +0,0 @@ -// -// windows/stream_handle_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP -#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include <boost/asio/detail/config.hpp> - -#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ - || defined(GENERATING_DOCUMENTATION) - -#include <cstddef> -#include <boost/asio/async_result.hpp> -#include <boost/asio/detail/win_iocp_handle_service.hpp> -#include <boost/asio/error.hpp> -#include <boost/asio/io_context.hpp> - -#include <boost/asio/detail/push_options.hpp> - -namespace boost { -namespace asio { -namespace windows { - -/// Default service implementation for a stream handle. -class stream_handle_service -#if defined(GENERATING_DOCUMENTATION) - : public boost::asio::io_context::service -#else - : public boost::asio::detail::service_base<stream_handle_service> -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static boost::asio::io_context::id id; -#endif - -private: - // The type of the platform-specific implementation. - typedef detail::win_iocp_handle_service service_impl_type; - -public: - /// The type of a stream handle implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef service_impl_type::implementation_type implementation_type; -#endif - - /// The native handle type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_handle_type; -#else - typedef service_impl_type::native_handle_type native_handle_type; -#endif - - /// Construct a new stream handle service for the specified io_context. - explicit stream_handle_service(boost::asio::io_context& io_context) - : boost::asio::detail::service_base<stream_handle_service>(io_context), - service_impl_(io_context) - { - } - - /// Construct a new stream handle implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - -#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move-construct a new stream handle implementation. - void move_construct(implementation_type& impl, - implementation_type& other_impl) - { - service_impl_.move_construct(impl, other_impl); - } - - /// Move-assign from another stream handle implementation. - void move_assign(implementation_type& impl, - stream_handle_service& other_service, - implementation_type& other_impl) - { - service_impl_.move_assign(impl, other_service.service_impl_, other_impl); - } -#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - - /// Destroy a stream handle implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Assign an existing native handle to a stream handle. - BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl, - const native_handle_type& handle, boost::system::error_code& ec) - { - service_impl_.assign(impl, handle, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Determine whether the handle is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a stream handle implementation. - BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.close(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Get the native handle implementation. - native_handle_type native_handle(implementation_type& impl) - { - return service_impl_.native_handle(impl); - } - - /// Cancel all asynchronous operations associated with the handle. - BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl, - boost::system::error_code& ec) - { - service_impl_.cancel(impl, ec); - BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); - } - - /// Write the given data to the stream. - template <typename ConstBufferSequence> - std::size_t write_some(implementation_type& impl, - const ConstBufferSequence& buffers, boost::system::error_code& ec) - { - return service_impl_.write_some(impl, buffers, ec); - } - - /// Start an asynchronous write. - template <typename ConstBufferSequence, typename WriteHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, - void (boost::system::error_code, std::size_t)) - async_write_some(implementation_type& impl, - const ConstBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(WriteHandler) handler) - { - boost::asio::async_completion<WriteHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_write_some(impl, buffers, init.completion_handler); - - return init.result.get(); - } - - /// Read some data from the stream. - template <typename MutableBufferSequence> - std::size_t read_some(implementation_type& impl, - const MutableBufferSequence& buffers, boost::system::error_code& ec) - { - return service_impl_.read_some(impl, buffers, ec); - } - - /// Start an asynchronous read. - template <typename MutableBufferSequence, typename ReadHandler> - BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, - void (boost::system::error_code, std::size_t)) - async_read_some(implementation_type& impl, - const MutableBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(ReadHandler) handler) - { - boost::asio::async_completion<ReadHandler, - void (boost::system::error_code, std::size_t)> init(handler); - - service_impl_.async_read_some(impl, buffers, init.completion_handler); - - return init.result.get(); - } - -private: - // Destroy all user-defined handler objects owned by the service. - void shutdown() - { - service_impl_.shutdown(); - } - - // The platform-specific implementation. - service_impl_type service_impl_; -}; - -} // namespace windows -} // namespace asio -} // namespace boost - -#include <boost/asio/detail/pop_options.hpp> - -#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) - // || defined(GENERATING_DOCUMENTATION) - -#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) - -#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP diff --git a/boost/asio/write.hpp b/boost/asio/write.hpp index e3f4d09cb7..041f163b40 100644 --- a/boost/asio/write.hpp +++ b/boost/asio/write.hpp @@ -2,7 +2,7 @@ // write.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -224,6 +224,8 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, is_const_buffer_sequence<ConstBufferSequence>::value >::type* = 0); +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// Write all of the supplied data to a stream before returning. /** * This function is used to write a certain number of bytes of data to a stream. @@ -251,11 +253,12 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, * s, buffers, * boost::asio::transfer_all()); @endcode */ -template <typename SyncWriteStream, typename DynamicBuffer> +template <typename SyncWriteStream, typename DynamicBuffer_v1> std::size_t write(SyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); /// Write all of the supplied data to a stream before returning. @@ -285,12 +288,13 @@ std::size_t write(SyncWriteStream& s, * s, buffers, * boost::asio::transfer_all(), ec); @endcode */ -template <typename SyncWriteStream, typename DynamicBuffer> +template <typename SyncWriteStream, typename DynamicBuffer_v1> std::size_t write(SyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, boost::system::error_code& ec, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); /// Write a certain amount of data to a stream before returning. @@ -329,13 +333,14 @@ std::size_t write(SyncWriteStream& s, * * @throws boost::system::system_error Thrown on failure. */ -template <typename SyncWriteStream, typename DynamicBuffer, +template <typename SyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t write(SyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); /// Write a certain amount of data to a stream before returning. @@ -375,13 +380,14 @@ std::size_t write(SyncWriteStream& s, * @returns The number of bytes written. If an error occurs, returns the total * number of bytes successfully transferred prior to the error. */ -template <typename SyncWriteStream, typename DynamicBuffer, +template <typename SyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t write(SyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, boost::system::error_code& ec, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -529,6 +535,163 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b, #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +/// Write all of the supplied data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied dynamic buffer sequence has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers The dynamic buffer sequence from which data will be written. + * Successfully written data is automatically consumed from the buffers. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code boost::asio::write( + * s, buffers, + * boost::asio::transfer_all()); @endcode + */ +template <typename SyncWriteStream, typename DynamicBuffer_v2> +std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Write all of the supplied data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied dynamic buffer sequence has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers The dynamic buffer sequence from which data will be written. + * Successfully written data is automatically consumed from the buffers. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes transferred. + * + * @note This overload is equivalent to calling: + * @code boost::asio::write( + * s, buffers, + * boost::asio::transfer_all(), ec); @endcode + */ +template <typename SyncWriteStream, typename DynamicBuffer_v2> +std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, + boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Write a certain amount of data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied dynamic buffer sequence has been written. + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers The dynamic buffer sequence from which data will be written. + * Successfully written data is automatically consumed from the buffers. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest write_some operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the write operation is complete. A + * non-zero return value indicates the maximum number of bytes to be written on + * the next call to the stream's write_some function. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + */ +template <typename SyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition> +std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Write a certain amount of data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied dynamic buffer sequence has been written. + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers The dynamic buffer sequence from which data will be written. + * Successfully written data is automatically consumed from the buffers. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest write_some operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the write operation is complete. A + * non-zero return value indicates the maximum number of bytes to be written on + * the next call to the stream's write_some function. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template <typename SyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition> +std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, boost::system::error_code& ec, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); /*@}*/ /** @@ -578,9 +741,9 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b, * // of the buffer sizes. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To write a single data buffer use the @ref buffer function as follows: @@ -654,9 +817,9 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, * // of the buffer sizes. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To write a single data buffer use the @ref buffer function as follows: @@ -679,6 +842,8 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, is_const_buffer_sequence<ConstBufferSequence>::value >::type* = 0); +#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + /// Start an asynchronous operation to write all of the supplied data to a /// stream. /** @@ -718,19 +883,20 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, * // of the buffer sizes. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename AsyncWriteStream, - typename DynamicBuffer, typename WriteHandler> + typename DynamicBuffer_v1, typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) async_write(AsyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); /// Start an asynchronous operation to write a certain amount of data to a @@ -786,20 +952,21 @@ async_write(AsyncWriteStream& s, * // of the buffer sizes. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ -template <typename AsyncWriteStream, typename DynamicBuffer, +template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (boost::system::error_code, std::size_t)) async_write(AsyncWriteStream& s, - BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, + BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, BOOST_ASIO_MOVE_ARG(WriteHandler) handler, typename enable_if< - is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value + is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value + && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value >::type* = 0); #if !defined(BOOST_ASIO_NO_EXTENSIONS) @@ -842,9 +1009,9 @@ async_write(AsyncWriteStream& s, * // of the buffer sizes. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename AsyncWriteStream, typename Allocator, typename WriteHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, @@ -903,9 +1070,9 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, * // of the buffer sizes. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename AsyncWriteStream, typename Allocator, typename CompletionCondition, typename WriteHandler> @@ -917,6 +1084,128 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, #endif // !defined(BOOST_ASIO_NO_IOSTREAM) #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) +#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) + +/// Start an asynchronous operation to write all of the supplied data to a +/// stream. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li All of the data in the supplied dynamic buffer sequence has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_write_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other write operations (such + * as async_write, the stream's async_write_some function, or any other composed + * operations that perform writes) until this operation completes. + * + * @param s The stream to which the data is to be written. The type must support + * the AsyncWriteStream concept. + * + * @param buffers The dynamic buffer sequence from which data will be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. Successfully written + * data is automatically consumed from the buffers. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes written from the + * // buffers. If an error occurred, + * // this will be less than the sum + * // of the buffer sizes. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + */ +template <typename AsyncWriteStream, + typename DynamicBuffer_v2, typename WriteHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) +async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); + +/// Start an asynchronous operation to write a certain amount of data to a +/// stream. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li All of the data in the supplied dynamic buffer sequence has been written. + * + * @li The completion_condition function object returns 0. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_write_some function, and is known as a <em>composed operation</em>. The + * program must ensure that the stream performs no other write operations (such + * as async_write, the stream's async_write_some function, or any other composed + * operations that perform writes) until this operation completes. + * + * @param s The stream to which the data is to be written. The type must support + * the AsyncWriteStream concept. + * + * @param buffers The dynamic buffer sequence from which data will be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. Successfully written + * data is automatically consumed from the buffers. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code std::size_t completion_condition( + * // Result of latest async_write_some operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of 0 indicates that the write operation is complete. A + * non-zero return value indicates the maximum number of bytes to be written on + * the next call to the stream's async_write_some function. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes written from the + * // buffers. If an error occurred, + * // this will be less than the sum + * // of the buffer sizes. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). + */ +template <typename AsyncWriteStream, typename DynamicBuffer_v2, + typename CompletionCondition, typename WriteHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) +async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler, + typename enable_if< + is_dynamic_buffer_v2<DynamicBuffer_v2>::value + >::type* = 0); /*@}*/ diff --git a/boost/asio/write_at.hpp b/boost/asio/write_at.hpp index 6330214bd3..d874327c5a 100644 --- a/boost/asio/write_at.hpp +++ b/boost/asio/write_at.hpp @@ -2,7 +2,7 @@ // write_at.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) @@ -443,9 +443,9 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To write a single data buffer use the @ref buffer function as follows: @@ -521,9 +521,9 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To write a single data buffer use the @ref buffer function as follows: @@ -588,9 +588,9 @@ async_write_at(AsyncRandomAccessWriteDevice& d, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename AsyncRandomAccessWriteDevice, typename Allocator, typename WriteHandler> @@ -654,9 +654,9 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template <typename AsyncRandomAccessWriteDevice, typename Allocator, typename CompletionCondition, typename WriteHandler> diff --git a/boost/asio/yield.hpp b/boost/asio/yield.hpp index 5ed7f9ae4f..36628ff98b 100644 --- a/boost/asio/yield.hpp +++ b/boost/asio/yield.hpp @@ -2,7 +2,7 @@ // yield.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 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) |