diff options
Diffstat (limited to '3rdparty/asio/include/asio/basic_socket_acceptor.hpp')
-rw-r--r-- | 3rdparty/asio/include/asio/basic_socket_acceptor.hpp | 1586 |
1 files changed, 1124 insertions, 462 deletions
diff --git a/3rdparty/asio/include/asio/basic_socket_acceptor.hpp b/3rdparty/asio/include/asio/basic_socket_acceptor.hpp index 9554bb9ed30..baa0c53ae6c 100644 --- a/3rdparty/asio/include/asio/basic_socket_acceptor.hpp +++ b/3rdparty/asio/include/asio/basic_socket_acceptor.hpp @@ -2,7 +2,7 @@ // basic_socket_acceptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the 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,37 +16,42 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" -#include "asio/basic_io_object.hpp" +#include "asio/any_io_executor.hpp" #include "asio/basic_socket.hpp" #include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" +#include "asio/execution_context.hpp" #include "asio/socket_base.hpp" +#if defined(ASIO_WINDOWS_RUNTIME) +# include "asio/detail/null_socket_service.hpp" +#elif defined(ASIO_HAS_IOCP) +# include "asio/detail/win_iocp_socket_service.hpp" +#else +# include "asio/detail/reactive_socket_service.hpp" +#endif + #if defined(ASIO_HAS_MOVE) # include <utility> #endif // defined(ASIO_HAS_MOVE) -#if defined(ASIO_ENABLE_OLD_SERVICES) -# include "asio/socket_acceptor_service.hpp" -#else // defined(ASIO_ENABLE_OLD_SERVICES) -# if defined(ASIO_WINDOWS_RUNTIME) -# include "asio/detail/null_socket_service.hpp" -# define ASIO_SVC_T detail::null_socket_service<Protocol> -# elif defined(ASIO_HAS_IOCP) -# include "asio/detail/win_iocp_socket_service.hpp" -# define ASIO_SVC_T detail::win_iocp_socket_service<Protocol> -# else -# include "asio/detail/reactive_socket_service.hpp" -# define ASIO_SVC_T detail::reactive_socket_service<Protocol> -# endif -#endif // defined(ASIO_ENABLE_OLD_SERVICES) - #include "asio/detail/push_options.hpp" namespace asio { +#if !defined(ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL) +#define ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Protocol, typename Executor = any_io_executor> +class basic_socket_acceptor; + +#endif // !defined(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 @@ -56,10 +61,16 @@ namespace asio { * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. * + * Synchronous @c accept operations are thread safe, if the underlying + * operating system calls are also thread safe. This means that it is permitted + * to perform concurrent calls to synchronous @c accept operations on a single + * socket object. Other synchronous operations, such as @c open or @c close, are + * not thread safe. + * * @par Example * Opening a socket acceptor with the SO_REUSEADDR option enabled: * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port); * acceptor.open(endpoint.protocol()); * acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true)); @@ -67,21 +78,34 @@ namespace asio { * acceptor.listen(); * @endcode */ -template <typename Protocol - ASIO_SVC_TPARAM_DEF1(= socket_acceptor_service<Protocol>)> +template <typename Protocol, typename Executor> class basic_socket_acceptor - : ASIO_SVC_ACCESS basic_io_object<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 acceptor type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_socket_acceptor<Protocol, Executor1> other; + }; /// The native representation of an acceptor. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type; +#elif defined(ASIO_WINDOWS_RUNTIME) + typedef typename detail::null_socket_service< + Protocol>::native_handle_type native_handle_type; +#elif defined(ASIO_HAS_IOCP) + typedef typename detail::win_iocp_socket_service< + Protocol>::native_handle_type native_handle_type; #else - typedef typename 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. @@ -96,12 +120,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(asio::io_context& io_context) - : basic_io_object<ASIO_SVC_T>(io_context) + explicit basic_socket_acceptor(const executor_type& ex) + : impl_(0, 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 constraint< + is_convertible<ExecutionContext&, execution_context&>::value + >::type = 0) + : impl_(0, 0, context) { } @@ -109,7 +152,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. * @@ -117,12 +160,37 @@ public: * * @throws asio::system_error Thrown on failure. */ - basic_socket_acceptor(asio::io_context& io_context, - const protocol_type& protocol) - : basic_io_object<ASIO_SVC_T>(io_context) + basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol) + : impl_(0, ex) { asio::error_code ec; - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + 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 asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_socket_acceptor(ExecutionContext& context, + const protocol_type& protocol, + typename constraint< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + >::type = defaulted_constraint()) + : impl_(0, 0, context) + { + asio::error_code ec; + impl_.get_service().open(impl_.get_implementation(), protocol, ec); asio::detail::throw_error(ec, "open"); } @@ -131,7 +199,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. * @@ -145,31 +213,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(asio::io_context& io_context, + basic_socket_acceptor(const executor_type& ex, const endpoint_type& endpoint, bool reuse_addr = true) - : basic_io_object<ASIO_SVC_T>(io_context) + : impl_(0, ex) { asio::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); 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); 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); 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); + 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 asio::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 constraint< + is_convertible<ExecutionContext&, execution_context&>::value + >::type = 0) + : impl_(0, 0, context) + { + asio::error_code ec; + const protocol_type protocol = endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); + asio::detail::throw_error(ec, "open"); + if (reuse_addr) + { + impl_.get_service().set_option(impl_.get_implementation(), + socket_base::reuse_address(true), ec); + asio::detail::throw_error(ec, "set_option"); + } + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); + asio::detail::throw_error(ec, "bind"); + impl_.get_service().listen(impl_.get_implementation(), socket_base::max_listen_connections, ec); asio::detail::throw_error(ec, "listen"); } @@ -179,7 +299,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. * @@ -189,12 +309,41 @@ public: * * @throws asio::system_error Thrown on failure. */ - basic_socket_acceptor(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<ASIO_SVC_T>(io_context) + : impl_(0, ex) + { + asio::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + protocol, native_acceptor, ec); + 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 asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_socket_acceptor(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_acceptor, + typename constraint< + is_convertible<ExecutionContext&, execution_context&>::value + >::type = 0) + : impl_(0, 0, context) { asio::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), protocol, native_acceptor, ec); asio::detail::throw_error(ec, "assign"); } @@ -208,10 +357,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<ASIO_SVC_T>(std::move(other)) + basic_socket_acceptor(basic_socket_acceptor&& other) ASIO_NOEXCEPT + : impl_(std::move(other.impl_)) { } @@ -223,16 +373,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<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 ASIO_SVC_TPARAM1> + template <typename Protocol1, typename Executor1> friend class basic_socket_acceptor; /// Move-construct a basic_socket_acceptor from an acceptor of another @@ -244,17 +395,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(io_context&) constructor. + * constructed using the @c basic_socket_acceptor(const executor_type&) + * constructor. */ - template <typename Protocol1 ASIO_SVC_TPARAM1> - basic_socket_acceptor( - basic_socket_acceptor<Protocol1 ASIO_SVC_TARG1>&& other, - typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) - : basic_io_object<ASIO_SVC_T>( - other.get_service().get_io_context()) + template <typename Protocol1, typename Executor1> + basic_socket_acceptor(basic_socket_acceptor<Protocol1, Executor1>&& other, + typename constraint< + is_convertible<Protocol1, Protocol>::value + && is_convertible<Executor1, Executor>::value + >::type = 0) + : impl_(std::move(other.impl_)) { - this->get_service().template converting_move_construct<Protocol1>( - this->get_implementation(), other.get_implementation()); } /// Move-assign a basic_socket_acceptor from an acceptor of another protocol @@ -266,15 +417,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 ASIO_SVC_TPARAM1> - typename enable_if<is_convertible<Protocol1, Protocol>::value, - basic_socket_acceptor>::type& operator=( - basic_socket_acceptor<Protocol1 ASIO_SVC_TARG1>&& other) + template <typename Protocol1, typename Executor1> + typename constraint< + 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<ASIO_SVC_T>::operator=(std::move(tmp)); + impl_ = std::move(tmp.impl_); return *this; } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -289,45 +443,11 @@ public: { } -#if defined(ASIO_ENABLE_OLD_SERVICES) - // These functions are provided by basic_io_object<>. -#else // defined(ASIO_ENABLE_OLD_SERVICES) -#if !defined(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. - */ - asio::io_context& get_io_context() - { - return basic_io_object<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. - */ - asio::io_context& get_io_service() - { - return basic_io_object<ASIO_SVC_T>::get_io_service(); - } -#endif // !defined(ASIO_NO_DEPRECATED) - /// Get the executor associated with the object. executor_type get_executor() ASIO_NOEXCEPT { - return basic_io_object<ASIO_SVC_T>::get_executor(); + return impl_.get_executor(); } -#endif // defined(ASIO_ENABLE_OLD_SERVICES) /// Open the acceptor using the specified protocol. /** @@ -340,14 +460,14 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * acceptor.open(asio::ip::tcp::v4()); * @endcode */ void open(const protocol_type& protocol = protocol_type()) { asio::error_code ec; - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); asio::detail::throw_error(ec, "open"); } @@ -362,7 +482,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * asio::error_code ec; * acceptor.open(asio::ip::tcp::v4(), ec); * if (ec) @@ -374,7 +494,7 @@ public: ASIO_SYNC_OP_VOID open(const protocol_type& protocol, asio::error_code& ec) { - this->get_service().open(this->get_implementation(), protocol, ec); + impl_.get_service().open(impl_.get_implementation(), protocol, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -392,7 +512,7 @@ public: const native_handle_type& native_acceptor) { asio::error_code ec; - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), protocol, native_acceptor, ec); asio::detail::throw_error(ec, "assign"); } @@ -410,7 +530,7 @@ public: ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, const native_handle_type& native_acceptor, asio::error_code& ec) { - this->get_service().assign(this->get_implementation(), + impl_.get_service().assign(impl_.get_implementation(), protocol, native_acceptor, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -418,7 +538,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. @@ -433,7 +553,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 12345); * acceptor.open(endpoint.protocol()); * acceptor.bind(endpoint); @@ -442,7 +562,7 @@ public: void bind(const endpoint_type& endpoint) { asio::error_code ec; - this->get_service().bind(this->get_implementation(), endpoint, ec); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); asio::detail::throw_error(ec, "bind"); } @@ -458,7 +578,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 12345); * acceptor.open(endpoint.protocol()); * asio::error_code ec; @@ -472,7 +592,7 @@ public: ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, asio::error_code& ec) { - this->get_service().bind(this->get_implementation(), endpoint, ec); + impl_.get_service().bind(impl_.get_implementation(), endpoint, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -489,7 +609,7 @@ public: void listen(int backlog = socket_base::max_listen_connections) { asio::error_code ec; - this->get_service().listen(this->get_implementation(), backlog, ec); + impl_.get_service().listen(impl_.get_implementation(), backlog, ec); asio::detail::throw_error(ec, "listen"); } @@ -505,7 +625,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::error_code ec; * acceptor.listen(asio::socket_base::max_listen_connections, ec); @@ -517,7 +637,7 @@ public: */ ASIO_SYNC_OP_VOID listen(int backlog, asio::error_code& ec) { - this->get_service().listen(this->get_implementation(), backlog, ec); + impl_.get_service().listen(impl_.get_implementation(), backlog, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -534,7 +654,7 @@ public: void close() { asio::error_code ec; - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); asio::detail::throw_error(ec, "close"); } @@ -550,7 +670,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::error_code ec; * acceptor.close(ec); @@ -562,10 +682,62 @@ public: */ ASIO_SYNC_OP_VOID close(asio::error_code& ec) { - this->get_service().close(this->get_implementation(), ec); + impl_.get_service().close(impl_.get_implementation(), ec); ASIO_SYNC_OP_VOID_RETURN(ec); } + /// Release ownership of the underlying native acceptor. + /** + * This function causes all outstanding asynchronous accept operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. Ownership of the + * native acceptor is then transferred to the caller. + * + * @throws asio::system_error Thrown on failure. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release() + { + asio::error_code ec; + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "release"); + return s; + } + + /// Release ownership of the underlying native acceptor. + /** + * This function causes all outstanding asynchronous accept operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. Ownership of the + * native acceptor is then transferred to the caller. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release(asio::error_code& ec) + { + return impl_.get_service().release(impl_.get_implementation(), ec); + } + /// Get the native acceptor representation. /** * This function may be used to obtain the underlying representation of the @@ -574,7 +746,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. @@ -588,7 +760,7 @@ public: void cancel() { asio::error_code ec; - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); asio::detail::throw_error(ec, "cancel"); } @@ -602,7 +774,7 @@ public: */ ASIO_SYNC_OP_VOID cancel(asio::error_code& ec) { - this->get_service().cancel(this->get_implementation(), ec); + impl_.get_service().cancel(impl_.get_implementation(), ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -621,7 +793,7 @@ public: * @par Example * Setting the SOL_SOCKET/SO_REUSEADDR option: * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::acceptor::reuse_address option(true); * acceptor.set_option(option); @@ -631,7 +803,7 @@ public: void set_option(const SettableSocketOption& option) { asio::error_code ec; - this->get_service().set_option(this->get_implementation(), option, ec); + impl_.get_service().set_option(impl_.get_implementation(), option, ec); asio::detail::throw_error(ec, "set_option"); } @@ -650,7 +822,7 @@ public: * @par Example * Setting the SOL_SOCKET/SO_REUSEADDR option: * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::acceptor::reuse_address option(true); * asio::error_code ec; @@ -665,7 +837,7 @@ public: ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, asio::error_code& ec) { - this->get_service().set_option(this->get_implementation(), option, ec); + impl_.get_service().set_option(impl_.get_implementation(), option, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -684,7 +856,7 @@ public: * @par Example * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::acceptor::reuse_address option; * acceptor.get_option(option); @@ -692,10 +864,10 @@ public: * @endcode */ template <typename GettableSocketOption> - void get_option(GettableSocketOption& option) + void get_option(GettableSocketOption& option) const { asio::error_code ec; - this->get_service().get_option(this->get_implementation(), option, ec); + impl_.get_service().get_option(impl_.get_implementation(), option, ec); asio::detail::throw_error(ec, "get_option"); } @@ -714,7 +886,7 @@ public: * @par Example * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::acceptor::reuse_address option; * asio::error_code ec; @@ -728,9 +900,9 @@ public: */ template <typename GettableSocketOption> ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, - asio::error_code& ec) + asio::error_code& ec) const { - this->get_service().get_option(this->get_implementation(), option, ec); + impl_.get_service().get_option(impl_.get_implementation(), option, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -748,7 +920,7 @@ public: * @par Example * Getting the number of bytes ready to read: * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::acceptor::non_blocking_io command(true); * socket.io_control(command); @@ -758,7 +930,7 @@ public: void io_control(IoControlCommand& command) { asio::error_code ec; - this->get_service().io_control(this->get_implementation(), command, ec); + impl_.get_service().io_control(impl_.get_implementation(), command, ec); asio::detail::throw_error(ec, "io_control"); } @@ -776,7 +948,7 @@ public: * @par Example * Getting the number of bytes ready to read: * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::acceptor::non_blocking_io command(true); * asio::error_code ec; @@ -791,7 +963,7 @@ public: ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, asio::error_code& ec) { - this->get_service().io_control(this->get_implementation(), command, ec); + impl_.get_service().io_control(impl_.get_implementation(), command, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -808,7 +980,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. @@ -827,7 +999,7 @@ public: void non_blocking(bool mode) { asio::error_code ec; - this->get_service().non_blocking(this->get_implementation(), mode, ec); + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); asio::detail::throw_error(ec, "non_blocking"); } @@ -847,7 +1019,7 @@ public: ASIO_SYNC_OP_VOID non_blocking( bool mode, asio::error_code& ec) { - this->get_service().non_blocking(this->get_implementation(), mode, ec); + impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -867,7 +1039,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. @@ -888,8 +1060,8 @@ public: void native_non_blocking(bool mode) { asio::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); asio::detail::throw_error(ec, "native_non_blocking"); } @@ -911,8 +1083,8 @@ public: ASIO_SYNC_OP_VOID native_non_blocking( bool mode, asio::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); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -926,7 +1098,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); * @endcode @@ -934,8 +1106,8 @@ public: endpoint_type local_endpoint() const { asio::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); asio::detail::throw_error(ec, "local_endpoint"); return ep; } @@ -952,7 +1124,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::error_code ec; * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); @@ -964,7 +1136,7 @@ public: */ endpoint_type local_endpoint(asio::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 @@ -978,7 +1150,7 @@ public: * @par Example * Waiting for an acceptor to become readable. * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * acceptor.wait(asio::ip::tcp::acceptor::wait_read); * @endcode @@ -986,7 +1158,7 @@ public: void wait(wait_type w) { asio::error_code ec; - this->get_service().wait(this->get_implementation(), w, ec); + impl_.get_service().wait(impl_.get_implementation(), w, ec); asio::detail::throw_error(ec, "wait"); } @@ -1003,7 +1175,7 @@ public: * @par Example * Waiting for an acceptor to become readable. * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::error_code ec; * acceptor.wait(asio::ip::tcp::acceptor::wait_read, ec); @@ -1011,7 +1183,7 @@ public: */ ASIO_SYNC_OP_VOID wait(wait_type w, asio::error_code& ec) { - this->get_service().wait(this->get_implementation(), w, ec); + impl_.get_service().wait(impl_.get_implementation(), w, ec); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1030,9 +1202,9 @@ public: * const asio::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 - * 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 asio::post(). * * @par Example * @code @@ -1046,34 +1218,34 @@ public: * * ... * - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * acceptor.async_wait( * asio::ip::tcp::acceptor::wait_read, * wait_handler); * @endcode + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ - template <typename WaitHandler> - ASIO_INITFN_RESULT_TYPE(WaitHandler, + template < + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) + WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (asio::error_code)) - async_wait(wait_type w, ASIO_MOVE_ARG(WaitHandler) handler) + async_wait(wait_type w, + ASIO_MOVE_ARG(WaitHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a WaitHandler. - ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; - -#if defined(ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_wait(this->get_implementation(), - w, ASIO_MOVE_CAST(WaitHandler)(handler)); -#else // defined(ASIO_ENABLE_OLD_SERVICES) - async_completion<WaitHandler, - void (asio::error_code)> init(handler); - - this->get_service().async_wait(this->get_implementation(), - w, init.completion_handler); - - return init.result.get(); -#endif // defined(ASIO_ENABLE_OLD_SERVICES) + return async_initiate<WaitHandler, void (asio::error_code)>( + initiate_async_wait(this), handler, w); } #if !defined(ASIO_NO_EXTENSIONS) @@ -1089,24 +1261,20 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... - * asio::ip::tcp::socket socket(io_context); + * asio::ip::tcp::socket socket(my_context); * acceptor.accept(socket); * @endcode */ -#if defined(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(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(ASIO_ENABLE_OLD_SERVICES) + template <typename Protocol1, typename Executor1> + void accept(basic_socket<Protocol1, Executor1>& peer, + typename constraint< + is_convertible<Protocol, Protocol1>::value + >::type = 0) { asio::error_code ec; - this->get_service().accept(this->get_implementation(), + impl_.get_service().accept(impl_.get_implementation(), peer, static_cast<endpoint_type*>(0), ec); asio::detail::throw_error(ec, "accept"); } @@ -1123,9 +1291,9 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... - * asio::ip::tcp::socket socket(io_context); + * asio::ip::tcp::socket socket(my_context); * asio::error_code ec; * acceptor.accept(socket, ec); * if (ec) @@ -1134,20 +1302,14 @@ public: * } * @endcode */ -#if defined(ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1, typename SocketService> + template <typename Protocol1, typename Executor1> ASIO_SYNC_OP_VOID accept( - basic_socket<Protocol1, SocketService>& peer, - asio::error_code& ec, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#else // defined(ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1> - ASIO_SYNC_OP_VOID accept( - basic_socket<Protocol1>& peer, asio::error_code& ec, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#endif // defined(ASIO_ENABLE_OLD_SERVICES) + basic_socket<Protocol1, Executor1>& peer, asio::error_code& ec, + typename constraint< + 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); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1168,9 +1330,9 @@ public: * const asio::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 - * 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 asio::post(). * * @par Example * @code @@ -1184,45 +1346,37 @@ public: * * ... * - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... - * asio::ip::tcp::socket socket(io_context); + * asio::ip::tcp::socket socket(my_context); * acceptor.async_accept(socket, accept_handler); * @endcode + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ -#if defined(ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1, typename SocketService, typename AcceptHandler> - ASIO_INITFN_RESULT_TYPE(AcceptHandler, - void (asio::error_code)) - async_accept(basic_socket<Protocol1, SocketService>& peer, - ASIO_MOVE_ARG(AcceptHandler) handler, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#else // defined(ASIO_ENABLE_OLD_SERVICES) - template <typename Protocol1, typename AcceptHandler> - ASIO_INITFN_RESULT_TYPE(AcceptHandler, + template <typename Protocol1, typename Executor1, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) + AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler, void (asio::error_code)) - async_accept(basic_socket<Protocol1>& peer, - ASIO_MOVE_ARG(AcceptHandler) handler, - typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) -#endif // defined(ASIO_ENABLE_OLD_SERVICES) + async_accept(basic_socket<Protocol1, Executor1>& peer, + ASIO_MOVE_ARG(AcceptHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), + typename constraint< + 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. - ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; - -#if defined(ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept(this->get_implementation(), - peer, static_cast<endpoint_type*>(0), - ASIO_MOVE_CAST(AcceptHandler)(handler)); -#else // defined(ASIO_ENABLE_OLD_SERVICES) - async_completion<AcceptHandler, - void (asio::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(ASIO_ENABLE_OLD_SERVICES) + return async_initiate<AcceptHandler, void (asio::error_code)>( + initiate_async_accept(this), handler, + &peer, static_cast<endpoint_type*>(0)); } /// Accept a new connection and obtain the endpoint of the peer @@ -1241,23 +1395,19 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... - * asio::ip::tcp::socket socket(io_context); + * asio::ip::tcp::socket socket(my_context); * asio::ip::tcp::endpoint endpoint; * acceptor.accept(socket, endpoint); * @endcode */ -#if defined(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(ASIO_ENABLE_OLD_SERVICES) - void accept(basic_socket<protocol_type>& peer, endpoint_type& peer_endpoint) -#endif // defined(ASIO_ENABLE_OLD_SERVICES) { asio::error_code ec; - this->get_service().accept(this->get_implementation(), + impl_.get_service().accept(impl_.get_implementation(), peer, &peer_endpoint, ec); asio::detail::throw_error(ec, "accept"); } @@ -1278,9 +1428,9 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... - * asio::ip::tcp::socket socket(io_context); + * asio::ip::tcp::socket socket(my_context); * asio::ip::tcp::endpoint endpoint; * asio::error_code ec; * acceptor.accept(socket, endpoint, ec); @@ -1290,18 +1440,12 @@ public: * } * @endcode */ -#if defined(ASIO_ENABLE_OLD_SERVICES) - template <typename SocketService> - ASIO_SYNC_OP_VOID accept( - basic_socket<protocol_type, SocketService>& peer, - endpoint_type& peer_endpoint, asio::error_code& ec) -#else // defined(ASIO_ENABLE_OLD_SERVICES) - ASIO_SYNC_OP_VOID accept(basic_socket<protocol_type>& peer, + template <typename Executor1> + ASIO_SYNC_OP_VOID accept(basic_socket<protocol_type, Executor1>& peer, endpoint_type& peer_endpoint, asio::error_code& ec) -#endif // defined(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); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1327,40 +1471,32 @@ public: * const asio::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 - * 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 asio::post(). + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ -#if defined(ASIO_ENABLE_OLD_SERVICES) - template <typename SocketService, typename AcceptHandler> - ASIO_INITFN_RESULT_TYPE(AcceptHandler, - void (asio::error_code)) - async_accept(basic_socket<protocol_type, SocketService>& peer, - endpoint_type& peer_endpoint, ASIO_MOVE_ARG(AcceptHandler) handler) -#else // defined(ASIO_ENABLE_OLD_SERVICES) - template <typename AcceptHandler> - ASIO_INITFN_RESULT_TYPE(AcceptHandler, + template <typename Executor1, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) + AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler, void (asio::error_code)) - async_accept(basic_socket<protocol_type>& peer, - endpoint_type& peer_endpoint, ASIO_MOVE_ARG(AcceptHandler) handler) -#endif // defined(ASIO_ENABLE_OLD_SERVICES) + async_accept(basic_socket<protocol_type, Executor1>& peer, + endpoint_type& peer_endpoint, + ASIO_MOVE_ARG(AcceptHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a AcceptHandler. - ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; - -#if defined(ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept(this->get_implementation(), peer, - &peer_endpoint, ASIO_MOVE_CAST(AcceptHandler)(handler)); -#else // defined(ASIO_ENABLE_OLD_SERVICES) - async_completion<AcceptHandler, - void (asio::error_code)> init(handler); - - this->get_service().async_accept(this->get_implementation(), - peer, &peer_endpoint, init.completion_handler); - - return init.result.get(); -#endif // defined(ASIO_ENABLE_OLD_SERVICES) + return async_initiate<AcceptHandler, void (asio::error_code)>( + initiate_async_accept(this), handler, &peer, &peer_endpoint); } #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1380,17 +1516,18 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::socket socket(acceptor.accept()); * @endcode */ - typename Protocol::socket accept() + typename Protocol::socket::template rebind_executor<executor_type>::other + accept() { asio::error_code ec; - typename Protocol::socket peer( - this->get_service().accept( - this->get_implementation(), 0, 0, ec)); + typename Protocol::socket::template rebind_executor< + executor_type>::other peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); asio::detail::throw_error(ec, "accept"); return peer; } @@ -1411,7 +1548,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::socket socket(acceptor.accept(ec)); * if (ec) @@ -1420,9 +1557,13 @@ public: * } * @endcode */ - typename Protocol::socket accept(asio::error_code& ec) + typename Protocol::socket::template rebind_executor<executor_type>::other + accept(asio::error_code& ec) { - return this->get_service().accept(this->get_implementation(), 0, 0, ec); + typename Protocol::socket::template rebind_executor< + executor_type>::other peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + return peer; } /// Start an asynchronous accept. @@ -1437,13 +1578,16 @@ public: * completes. Copies will be made of the handler as required. The function * signature of the handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. - * typename Protocol::socket peer // On success, the newly accepted socket. + * // Result of operation. + * const asio::error_code& error, + * // On success, the newly accepted socket. + * typename Protocol::socket::template + * rebind_executor<executor_type>::other peer * ); @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 - * 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 asio::post(). * * @par Example * @code @@ -1458,37 +1602,80 @@ public: * * ... * - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * acceptor.async_accept(accept_handler); * @endcode + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ - template <typename MoveAcceptHandler> - ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, - void (asio::error_code, typename Protocol::socket)) - async_accept(ASIO_MOVE_ARG(MoveAcceptHandler) handler) - { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - -#if defined(ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept( - this->get_implementation(), static_cast<asio::io_context*>(0), - static_cast<endpoint_type*>(0), - ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); -#else // defined(ASIO_ENABLE_OLD_SERVICES) - async_completion<MoveAcceptHandler, + template < + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + typename Protocol::socket::template rebind_executor< + executor_type>::other)) MoveAcceptHandler + ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, void (asio::error_code, - typename Protocol::socket)> init(handler); - - this->get_service().async_accept( - this->get_implementation(), static_cast<asio::io_context*>(0), - static_cast<endpoint_type*>(0), init.completion_handler); + typename Protocol::socket::template + rebind_executor<executor_type>::other)) + async_accept( + ASIO_MOVE_ARG(MoveAcceptHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + { + return async_initiate<MoveAcceptHandler, + void (asio::error_code, typename Protocol::socket::template + rebind_executor<executor_type>::other)>( + initiate_async_move_accept(this), handler, + impl_.get_executor(), static_cast<endpoint_type*>(0), + static_cast<typename Protocol::socket::template + rebind_executor<executor_type>::other*>(0)); + } - return init.result.get(); -#endif // defined(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 asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(my_context); + * ... + * asio::ip::tcp::socket socket(acceptor.accept()); + * @endcode + */ + template <typename Executor1> + typename Protocol::socket::template rebind_executor<Executor1>::other + accept(const Executor1& ex, + typename constraint< + is_executor<Executor1>::value + || execution::is_executor<Executor1>::value + >::type = 0) + { + asio::error_code ec; + typename Protocol::socket::template + rebind_executor<Executor1>::other peer(ex); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + asio::detail::throw_error(ec, "accept"); + return peer; } /// Accept a new connection. @@ -1500,8 +1687,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. * @@ -1509,17 +1696,23 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::socket socket(acceptor.accept()); * @endcode */ - typename Protocol::socket accept(asio::io_context& io_context) + template <typename ExecutionContext> + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, + typename constraint< + is_convertible<ExecutionContext&, execution_context&>::value + >::type = 0) { asio::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); asio::detail::throw_error(ec, "accept"); return peer; } @@ -1533,7 +1726,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. @@ -1543,20 +1736,69 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); + * ... + * asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename Executor1> + typename Protocol::socket::template rebind_executor<Executor1>::other + accept(const Executor1& ex, asio::error_code& ec, + typename constraint< + is_executor<Executor1>::value + || execution::is_executor<Executor1>::value + >::type = 0) + { + 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 + * asio::ip::tcp::acceptor acceptor(my_context); * ... - * asio::ip::tcp::socket socket(acceptor.accept(io_context2, ec)); + * asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec)); * if (ec) * { * // An error occurred. * } * @endcode */ - typename Protocol::socket accept( - asio::io_context& io_context, asio::error_code& ec) + template <typename ExecutionContext> + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other + accept(ExecutionContext& context, asio::error_code& ec, + typename constraint< + is_convertible<ExecutionContext&, execution_context&>::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< + typename ExecutionContext::executor_type>::other peer(context); + impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec); + return peer; } /// Start an asynchronous accept. @@ -1567,7 +1809,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 @@ -1575,12 +1817,13 @@ public: * signature of the handler must be: * @code void handler( * const asio::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 - * 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 asio::post(). * * @par Example * @code @@ -1595,36 +1838,125 @@ public: * * ... * - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... - * acceptor.async_accept(io_context2, accept_handler); + * acceptor.async_accept(my_context2, accept_handler); * @endcode + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ - template <typename MoveAcceptHandler> - ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, - void (asio::error_code, typename Protocol::socket)) - async_accept(asio::io_context& io_context, - ASIO_MOVE_ARG(MoveAcceptHandler) handler) - { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - -#if defined(ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept(this->get_implementation(), - &io_context, static_cast<endpoint_type*>(0), - ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); -#else // defined(ASIO_ENABLE_OLD_SERVICES) - async_completion<MoveAcceptHandler, + template <typename Executor1, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + typename Protocol::socket::template rebind_executor< + Executor1>::other)) MoveAcceptHandler + ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, void (asio::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, + ASIO_MOVE_ARG(MoveAcceptHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), + typename constraint< + is_executor<Executor1>::value + || execution::is_executor<Executor1>::value + >::type = 0) + { + typedef typename Protocol::socket::template rebind_executor< + Executor1>::other other_socket_type; + + return async_initiate<MoveAcceptHandler, + void (asio::error_code, other_socket_type)>( + initiate_async_move_accept(this), handler, + ex, static_cast<endpoint_type*>(0), + static_cast<other_socket_type*>(0)); + } - return init.result.get(); -#endif // defined(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 asio::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 asio::post(). + * + * @par Example + * @code + * void accept_handler(const asio::error_code& error, + * asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * asio::ip::tcp::acceptor acceptor(my_context); + * ... + * acceptor.async_accept(my_context2, accept_handler); + * @endcode + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total + */ + template <typename ExecutionContext, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)) MoveAcceptHandler + ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, + void (asio::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)) + async_accept(ExecutionContext& context, + ASIO_MOVE_ARG(MoveAcceptHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), + typename constraint< + 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 (asio::error_code, other_socket_type)>( + initiate_async_move_accept(this), handler, + context.get_executor(), static_cast<endpoint_type*>(0), + static_cast<other_socket_type*>(0)); } /// Accept a new connection. @@ -1645,18 +1977,20 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::endpoint endpoint; * asio::ip::tcp::socket socket(acceptor.accept(endpoint)); * @endcode */ - typename Protocol::socket accept(endpoint_type& peer_endpoint) + typename Protocol::socket::template rebind_executor<executor_type>::other + accept(endpoint_type& peer_endpoint) { asio::error_code ec; - typename Protocol::socket peer( - this->get_service().accept(this->get_implementation(), - static_cast<asio::io_context*>(0), &peer_endpoint, ec)); + typename Protocol::socket::template rebind_executor< + executor_type>::other peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); asio::detail::throw_error(ec, "accept"); return peer; } @@ -1680,7 +2014,7 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::endpoint endpoint; * asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec)); @@ -1690,11 +2024,14 @@ public: * } * @endcode */ - typename Protocol::socket accept( - endpoint_type& peer_endpoint, asio::error_code& ec) + typename Protocol::socket::template rebind_executor<executor_type>::other + accept(endpoint_type& peer_endpoint, asio::error_code& ec) { - return this->get_service().accept(this->get_implementation(), - static_cast<asio::io_context*>(0), &peer_endpoint, ec); + typename Protocol::socket::template rebind_executor< + executor_type>::other peer(impl_.get_executor()); + impl_.get_service().accept(impl_.get_implementation(), + peer, &peer_endpoint, ec); + return peer; } /// Start an asynchronous accept. @@ -1714,13 +2051,16 @@ public: * completes. Copies will be made of the handler as required. The function * signature of the handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. - * typename Protocol::socket peer // On success, the newly accepted socket. + * // Result of operation. + * const asio::error_code& error, + * // On success, the newly accepted socket. + * typename Protocol::socket::template + * rebind_executor<executor_type>::other peer * ); @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 - * 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 asio::post(). * * @par Example * @code @@ -1735,38 +2075,42 @@ public: * * ... * - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::endpoint endpoint; * acceptor.async_accept(endpoint, accept_handler); * @endcode + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ - template <typename MoveAcceptHandler> - ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, - void (asio::error_code, typename Protocol::socket)) - async_accept(endpoint_type& peer_endpoint, - ASIO_MOVE_ARG(MoveAcceptHandler) handler) - { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - -#if defined(ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept(this->get_implementation(), - static_cast<asio::io_context*>(0), &peer_endpoint, - ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); -#else // defined(ASIO_ENABLE_OLD_SERVICES) - async_completion<MoveAcceptHandler, + template < + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + typename Protocol::socket::template rebind_executor< + executor_type>::other)) MoveAcceptHandler + ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, void (asio::error_code, - typename Protocol::socket)> init(handler); - - this->get_service().async_accept(this->get_implementation(), - static_cast<asio::io_context*>(0), &peer_endpoint, - init.completion_handler); - - return init.result.get(); -#endif // defined(ASIO_ENABLE_OLD_SERVICES) + typename Protocol::socket::template + rebind_executor<executor_type>::other)) + async_accept(endpoint_type& peer_endpoint, + ASIO_MOVE_ARG(MoveAcceptHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + { + return async_initiate<MoveAcceptHandler, + void (asio::error_code, typename Protocol::socket::template + rebind_executor<executor_type>::other)>( + initiate_async_move_accept(this), handler, + impl_.get_executor(), &peer_endpoint, + static_cast<typename Protocol::socket::template + rebind_executor<executor_type>::other*>(0)); } /// Accept a new connection. @@ -1778,7 +2122,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 @@ -1790,20 +2134,26 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::endpoint endpoint; * asio::ip::tcp::socket socket( - * acceptor.accept(io_context2, endpoint)); + * acceptor.accept(my_context2, endpoint)); * @endcode */ - typename Protocol::socket accept( - 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 constraint< + is_executor<Executor1>::value + || execution::is_executor<Executor1>::value + >::type = 0) { asio::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); asio::detail::throw_error(ec, "accept"); return peer; } @@ -1817,7 +2167,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 asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::ip::tcp::acceptor acceptor(my_context); + * ... + * asio::ip::tcp::endpoint endpoint; + * 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 constraint< + is_convertible<ExecutionContext&, execution_context&>::value + >::type = 0) + { + asio::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); + 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 @@ -1830,22 +2225,80 @@ public: * * @par Example * @code - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::endpoint endpoint; * 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(asio::io_context& io_context, - endpoint_type& peer_endpoint, asio::error_code& ec) + template <typename Executor1> + typename Protocol::socket::template rebind_executor<Executor1>::other + accept(const executor_type& ex, + endpoint_type& peer_endpoint, asio::error_code& ec, + typename constraint< + is_executor<Executor1>::value + || execution::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 + * asio::ip::tcp::acceptor acceptor(my_context); + * ... + * asio::ip::tcp::endpoint endpoint; + * 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, asio::error_code& ec, + typename constraint< + 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. @@ -1856,7 +2309,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 @@ -1869,12 +2322,13 @@ public: * signature of the handler must be: * @code void handler( * const asio::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 - * 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 asio::post(). * * @par Example * @code @@ -1889,48 +2343,256 @@ public: * * ... * - * asio::ip::tcp::acceptor acceptor(io_context); + * asio::ip::tcp::acceptor acceptor(my_context); * ... * asio::ip::tcp::endpoint endpoint; - * acceptor.async_accept(io_context2, endpoint, accept_handler); + * acceptor.async_accept(my_context2, endpoint, accept_handler); * @endcode + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ - template <typename MoveAcceptHandler> - ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, - void (asio::error_code, typename Protocol::socket)) - async_accept(asio::io_context& io_context, - endpoint_type& peer_endpoint, - ASIO_MOVE_ARG(MoveAcceptHandler) handler) - { - // If you get an error on the following line it means that your handler does - // not meet the documented type requirements for a MoveAcceptHandler. - ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler, - handler, typename Protocol::socket) type_check; - -#if defined(ASIO_ENABLE_OLD_SERVICES) - return this->get_service().async_accept( - this->get_implementation(), &io_context, &peer_endpoint, - ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); -#else // defined(ASIO_ENABLE_OLD_SERVICES) - async_completion<MoveAcceptHandler, + template <typename Executor1, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + typename Protocol::socket::template rebind_executor< + Executor1>::other)) MoveAcceptHandler + ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, void (asio::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, + ASIO_MOVE_ARG(MoveAcceptHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), + typename constraint< + is_executor<Executor1>::value + || execution::is_executor<Executor1>::value + >::type = 0) + { + typedef typename Protocol::socket::template rebind_executor< + Executor1>::other other_socket_type; + + return async_initiate<MoveAcceptHandler, + void (asio::error_code, other_socket_type)>( + initiate_async_move_accept(this), handler, + ex, &peer_endpoint, + static_cast<other_socket_type*>(0)); + } - return init.result.get(); -#endif // defined(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 asio::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 asio::post(). + * + * @par Example + * @code + * void accept_handler(const asio::error_code& error, + * asio::ip::tcp::socket peer) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * asio::ip::tcp::acceptor acceptor(my_context); + * ... + * asio::ip::tcp::endpoint endpoint; + * acceptor.async_accept(my_context2, endpoint, accept_handler); + * @endcode + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total + */ + template <typename ExecutionContext, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)) MoveAcceptHandler + ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, + void (asio::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)) + async_accept(ExecutionContext& context, + endpoint_type& peer_endpoint, + ASIO_MOVE_ARG(MoveAcceptHandler) handler + ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), + typename constraint< + 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 (asio::error_code, other_socket_type)>( + initiate_async_move_accept(this), handler, + context.get_executor(), &peer_endpoint, + static_cast<other_socket_type*>(0)); } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + +private: + // Disallow copying and assignment. + basic_socket_acceptor(const basic_socket_acceptor&) ASIO_DELETED; + basic_socket_acceptor& operator=( + const basic_socket_acceptor&) ASIO_DELETED; + + class initiate_async_wait + { + public: + typedef Executor executor_type; + + explicit initiate_async_wait(basic_socket_acceptor* self) + : self_(self) + { + } + + executor_type get_executor() const ASIO_NOEXCEPT + { + return self_->get_executor(); + } + + template <typename WaitHandler> + void operator()(ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WaitHandler. + ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + detail::non_const_lvalue<WaitHandler> handler2(handler); + self_->impl_.get_service().async_wait( + self_->impl_.get_implementation(), w, + handler2.value, self_->impl_.get_executor()); + } + + private: + basic_socket_acceptor* self_; + }; + + class initiate_async_accept + { + public: + typedef Executor executor_type; + + explicit initiate_async_accept(basic_socket_acceptor* self) + : self_(self) + { + } + + executor_type get_executor() const ASIO_NOEXCEPT + { + return self_->get_executor(); + } + + template <typename AcceptHandler, typename Protocol1, typename Executor1> + void operator()(ASIO_MOVE_ARG(AcceptHandler) handler, + 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. + 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_executor()); + } + + private: + basic_socket_acceptor* self_; + }; + + class initiate_async_move_accept + { + public: + typedef Executor executor_type; + + explicit initiate_async_move_accept(basic_socket_acceptor* self) + : self_(self) + { + } + + executor_type get_executor() const ASIO_NOEXCEPT + { + return self_->get_executor(); + } + + template <typename MoveAcceptHandler, typename Executor1, typename Socket> + void operator()(ASIO_MOVE_ARG(MoveAcceptHandler) handler, + const Executor1& peer_ex, endpoint_type* peer_endpoint, Socket*) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a MoveAcceptHandler. + ASIO_MOVE_ACCEPT_HANDLER_CHECK( + MoveAcceptHandler, handler, Socket) type_check; + + detail::non_const_lvalue<MoveAcceptHandler> handler2(handler); + self_->impl_.get_service().async_move_accept( + self_->impl_.get_implementation(), peer_ex, peer_endpoint, + handler2.value, self_->impl_.get_executor()); + } + + private: + basic_socket_acceptor* self_; + }; + +#if defined(ASIO_WINDOWS_RUNTIME) + detail::io_object_impl< + detail::null_socket_service<Protocol>, Executor> impl_; +#elif defined(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 #include "asio/detail/pop_options.hpp" -#if !defined(ASIO_ENABLE_OLD_SERVICES) -# undef ASIO_SVC_T -#endif // !defined(ASIO_ENABLE_OLD_SERVICES) - #endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP |