diff options
Diffstat (limited to 'boost/asio/basic_socket.hpp')
-rw-r--r-- | boost/asio/basic_socket.hpp | 539 |
1 files changed, 319 insertions, 220 deletions
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 |