Finish implementation of move-enabled accept/async_accept.
diff --git a/asio/include/asio/basic_socket_acceptor.hpp b/asio/include/asio/basic_socket_acceptor.hpp index 287652d..983dd5b 100644 --- a/asio/include/asio/basic_socket_acceptor.hpp +++ b/asio/include/asio/basic_socket_acceptor.hpp
@@ -1308,8 +1308,7 @@ * * asio::ip::tcp::acceptor acceptor(io_service); * ... - * asio::ip::tcp::socket socket(io_service); - * acceptor.async_accept(socket, accept_handler); + * acceptor.async_accept(accept_handler); * @endcode */ template <typename MoveAcceptHandler> @@ -1323,7 +1322,405 @@ handler, typename Protocol::socket) type_check; return this->get_service().async_accept(this->get_implementation(), - static_cast<endpoint_type*>(0), + static_cast<asio::io_service*>(0), static_cast<endpoint_type*>(0), + ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); + } + + /// 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 io_service The io_service 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(io_service); + * ... + * asio::ip::tcp::socket socket(acceptor.accept()); + * @endcode + */ + typename Protocol::socket accept(asio::io_service& io_service) + { + asio::error_code ec; + typename Protocol::socket peer( + this->get_service().accept(this->get_implementation(), + &io_service, static_cast<endpoint_type*>(0), 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 io_service The io_service 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(io_service); + * ... + * asio::ip::tcp::socket socket(acceptor.accept(io_service2, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + typename Protocol::socket accept( + asio::io_service& io_service, asio::error_code& ec) + { + return this->get_service().accept(this->get_implementation(), + &io_service, static_cast<endpoint_type*>(0), ec); + } + + /// 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 io_service The io_service 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 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_service::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(io_service); + * ... + * acceptor.async_accept(io_service2, accept_handler); + * @endcode + */ + template <typename MoveAcceptHandler> + ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (asio::error_code, typename Protocol::socket)) + async_accept(asio::io_service& io_service, + 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; + + return this->get_service().async_accept(this->get_implementation(), + &io_service, static_cast<endpoint_type*>(0), + ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); + } + + /// 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 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(io_service); + * ... + * asio::ip::tcp::endpoint endpoint; + * asio::ip::tcp::socket socket(acceptor.accept(endpoint)); + * @endcode + */ + typename Protocol::socket accept(endpoint_type& peer_endpoint) + { + asio::error_code ec; + typename Protocol::socket peer( + this->get_service().accept(this->get_implementation(), + static_cast<asio::io_service*>(0), &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 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(io_service); + * ... + * asio::ip::tcp::endpoint endpoint; + * asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + typename Protocol::socket accept( + endpoint_type& peer_endpoint, asio::error_code& ec) + { + return this->get_service().accept(this->get_implementation(), + static_cast<asio::io_service*>(0), &peer_endpoint, ec); + } + + /// 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 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 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_service::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(io_service); + * ... + * asio::ip::tcp::endpoint endpoint; + * acceptor.async_accept(endpoint, accept_handler); + * @endcode + */ + 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; + + return this->get_service().async_accept(this->get_implementation(), + static_cast<asio::io_service*>(0), &peer_endpoint, + ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); + } + + /// 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 io_service The io_service 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(io_service); + * ... + * asio::ip::tcp::endpoint endpoint; + * asio::ip::tcp::socket socket( + * acceptor.accept(io_service2, endpoint)); + * @endcode + */ + typename Protocol::socket accept( + asio::io_service& io_service, endpoint_type& peer_endpoint) + { + asio::error_code ec; + typename Protocol::socket peer( + this->get_service().accept(this->get_implementation(), + &io_service, &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 io_service The io_service 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(io_service); + * ... + * asio::ip::tcp::endpoint endpoint; + * asio::ip::tcp::socket socket( + * acceptor.accept(io_service2, endpoint, ec)); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + typename Protocol::socket accept(asio::io_service& io_service, + endpoint_type& peer_endpoint, asio::error_code& ec) + { + return this->get_service().accept(this->get_implementation(), + &io_service, &peer_endpoint, ec); + } + + /// 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 io_service The io_service 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 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_service::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(io_service); + * ... + * asio::ip::tcp::endpoint endpoint; + * acceptor.async_accept(io_service2, endpoint, accept_handler); + * @endcode + */ + template <typename MoveAcceptHandler> + ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, + void (asio::error_code, typename Protocol::socket)) + async_accept(asio::io_service& io_service, + 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; + + return this->get_service().async_accept( + this->get_implementation(), &io_service, &peer_endpoint, ASIO_MOVE_CAST(MoveAcceptHandler)(handler)); } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
diff --git a/asio/include/asio/detail/reactive_socket_accept_op.hpp b/asio/include/asio/detail/reactive_socket_accept_op.hpp index ea83190..22620a6 100644 --- a/asio/include/asio/detail/reactive_socket_accept_op.hpp +++ b/asio/include/asio/detail/reactive_socket_accept_op.hpp
@@ -160,8 +160,6 @@ reactive_socket_move_accept_op* o( static_cast<reactive_socket_move_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; - typename Protocol::socket peer( - ASIO_MOVE_CAST(typename Protocol::socket)(*o)); handler_work<Handler> w(o->handler_); ASIO_HANDLER_COMPLETION((o)); @@ -172,9 +170,10 @@ // with the handler. Consequently, a local copy of the handler is required // to ensure that any owning sub-object remains valid until after we have // deallocated the memory here. - detail::move_binder2<Handler, asio::error_code, typename Protocol::socket> - handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_, - ASIO_MOVE_CAST(typename Protocol::socket)(peer)); + detail::move_binder2<Handler, + asio::error_code, typename Protocol::socket> + handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_, + ASIO_MOVE_CAST(typename Protocol::socket)(*o)); p.h = asio::detail::addressof(handler.handler_); p.reset();
diff --git a/asio/include/asio/detail/reactive_socket_service.hpp b/asio/include/asio/detail/reactive_socket_service.hpp index 4d3c723..432921b 100644 --- a/asio/include/asio/detail/reactive_socket_service.hpp +++ b/asio/include/asio/detail/reactive_socket_service.hpp
@@ -388,6 +388,7 @@ return ec; } +#if defined(ASIO_HAS_MOVE) // Accept a new connection. typename Protocol::socket accept(implementation_type& impl, io_service* peer_io_service, endpoint_type* peer_endpoint, @@ -412,6 +413,7 @@ return peer; } +#endif // defined(ASIO_HAS_MOVE) // Start an asynchronous accept. The peer and peer_endpoint objects must be // valid until the accept's handler is invoked. @@ -440,6 +442,7 @@ // the accept's handler is invoked. template <typename Handler> void async_accept(implementation_type& impl, + asio::io_service* peer_io_service, endpoint_type* peer_endpoint, Handler& handler) { bool is_continuation = @@ -449,8 +452,8 @@ typedef reactive_socket_move_accept_op<Protocol, Handler> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; - p.p = new (p.v) op(io_service_, impl.socket_, impl.state_, - impl.protocol_, peer_endpoint, handler); + p.p = new (p.v) op(peer_io_service ? *peer_io_service : io_service_, + impl.socket_, impl.state_, impl.protocol_, peer_endpoint, handler); ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
diff --git a/asio/include/asio/detail/win_iocp_socket_accept_op.hpp b/asio/include/asio/detail/win_iocp_socket_accept_op.hpp index d14c617..b6e4515 100644 --- a/asio/include/asio/detail/win_iocp_socket_accept_op.hpp +++ b/asio/include/asio/detail/win_iocp_socket_accept_op.hpp
@@ -157,6 +157,136 @@ Handler handler_; }; +#if defined(ASIO_HAS_MOVE) + +template <typename Protocol, typename Handler> +class win_iocp_socket_move_accept_op : public operation +{ +public: + ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_move_accept_op); + + win_iocp_socket_move_accept_op( + win_iocp_socket_service_base& socket_service, socket_type socket, + const Protocol& protocol, asio::io_service& peer_io_service, + typename Protocol::endpoint* peer_endpoint, + bool enable_connection_aborted, Handler& handler) + : operation(&win_iocp_socket_move_accept_op::do_complete), + socket_service_(socket_service), + socket_(socket), + peer_(peer_io_service), + protocol_(protocol), + peer_endpoint_(peer_endpoint), + enable_connection_aborted_(enable_connection_aborted), + handler_(ASIO_MOVE_CAST(Handler)(handler)) + { + handler_work<Handler>::start(handler_); + } + + socket_holder& new_socket() + { + return new_socket_; + } + + void* output_buffer() + { + return output_buffer_; + } + + DWORD address_length() + { + return sizeof(sockaddr_storage_type) + 16; + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& result_ec, + std::size_t /*bytes_transferred*/) + { + asio::error_code ec(result_ec); + + // Take ownership of the operation object. + win_iocp_socket_move_accept_op* o( + static_cast<win_iocp_socket_move_accept_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + handler_work<Handler> w(o->handler_); + + if (owner) + { + typename Protocol::endpoint peer_endpoint; + std::size_t addr_len = peer_endpoint.capacity(); + socket_ops::complete_iocp_accept(o->socket_, + o->output_buffer(), o->address_length(), + peer_endpoint.data(), &addr_len, + o->new_socket_.get(), ec); + + // Restart the accept operation if we got the connection_aborted error + // and the enable_connection_aborted socket option is not set. + if (ec == asio::error::connection_aborted + && !o->enable_connection_aborted_) + { + o->reset(); + o->socket_service_.restart_accept_op(o->socket_, + o->new_socket_, o->protocol_.family(), + o->protocol_.type(), o->protocol_.protocol(), + o->output_buffer(), o->address_length(), o); + p.v = p.p = 0; + return; + } + + // If the socket was successfully accepted, transfer ownership of the + // socket to the peer object. + if (!ec) + { + o->peer_.assign(o->protocol_, + typename Protocol::socket::native_handle_type( + o->new_socket_.get(), peer_endpoint), ec); + if (!ec) + o->new_socket_.release(); + } + + // Pass endpoint back to caller. + if (o->peer_endpoint_) + *o->peer_endpoint_ = peer_endpoint; + } + + ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::move_binder2<Handler, + asio::error_code, typename Protocol::socket> + handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), ec, + ASIO_MOVE_CAST(typename Protocol::socket)(o->peer_)); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + win_iocp_socket_service_base& socket_service_; + socket_type socket_; + socket_holder new_socket_; + typename Protocol::socket peer_; + Protocol protocol_; + typename Protocol::endpoint* peer_endpoint_; + unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; + bool enable_connection_aborted_; + Handler handler_; +}; + +#endif // defined(ASIO_HAS_MOVE) + } // namespace detail } // namespace asio
diff --git a/asio/include/asio/detail/win_iocp_socket_service.hpp b/asio/include/asio/detail/win_iocp_socket_service.hpp index 7903258..21f3e8d 100644 --- a/asio/include/asio/detail/win_iocp_socket_service.hpp +++ b/asio/include/asio/detail/win_iocp_socket_service.hpp
@@ -457,13 +457,14 @@ return ec; } +#if defined(ASIO_HAS_MOVE) // Accept a new connection. typename Protocol::socket accept(implementation_type& impl, io_service* peer_io_service, endpoint_type* peer_endpoint, asio::error_code& ec) { typename Protocol::socket peer( - peer_io_service ? *peer_io_service : get_io_service()); + peer_io_service ? *peer_io_service : io_service_); std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; socket_holder new_socket(socket_ops::sync_accept(impl.socket_, @@ -479,8 +480,9 @@ new_socket.release(); } - return ec; + return peer; } +#endif // defined(ASIO_HAS_MOVE) // Start an asynchronous accept. The peer and peer_endpoint objects // must be valid until the accept's handler is invoked. @@ -506,6 +508,34 @@ p.v = p.p = 0; } +#if defined(ASIO_HAS_MOVE) + // Start an asynchronous accept. The peer and peer_endpoint objects + // must be valid until the accept's handler is invoked. + template <typename Handler> + void async_accept(implementation_type& impl, + asio::io_service* peer_io_service, + endpoint_type* peer_endpoint, Handler& handler) + { + // Allocate and construct an operation to wrap the handler. + typedef win_iocp_socket_move_accept_op<protocol_type, Handler> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + bool enable_connection_aborted = + (impl.state_ & socket_ops::enable_connection_aborted) != 0; + p.p = new (p.v) op(*this, impl.socket_, impl.protocol_, + peer_io_service ? *peer_io_service : io_service_, + peer_endpoint, enable_connection_aborted, handler); + + ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept")); + + start_accept_op(impl, false, p.p->new_socket(), + impl.protocol_.family(), impl.protocol_.type(), + impl.protocol_.protocol(), p.p->output_buffer(), + p.p->address_length(), p.p); + p.v = p.p = 0; + } +#endif // defined(ASIO_HAS_MOVE) + // Connect the socket to the specified endpoint. asio::error_code connect(implementation_type& impl, const endpoint_type& peer_endpoint, asio::error_code& ec)
diff --git a/asio/include/asio/socket_acceptor_service.hpp b/asio/include/asio/socket_acceptor_service.hpp index a1fe502..39d431c 100644 --- a/asio/include/asio/socket_acceptor_service.hpp +++ b/asio/include/asio/socket_acceptor_service.hpp
@@ -310,13 +310,14 @@ ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler, void (asio::error_code, typename Protocol::socket)) async_accept(implementation_type& impl, - endpoint_type* peer_endpoint, + asio::io_service* peer_io_service, endpoint_type* peer_endpoint, ASIO_MOVE_ARG(MoveAcceptHandler) handler) { async_completion<MoveAcceptHandler, void (asio::error_code, typename Protocol::socket)> init(handler); - service_impl_.async_accept(impl, peer_endpoint, init.handler); + service_impl_.async_accept(impl, + peer_io_service, peer_endpoint, init.handler); return init.result.get(); }
diff --git a/asio/src/examples/cpp11/allocation/server.cpp b/asio/src/examples/cpp11/allocation/server.cpp index 35d4e9d..18f58b8 100644 --- a/asio/src/examples/cpp11/allocation/server.cpp +++ b/asio/src/examples/cpp11/allocation/server.cpp
@@ -167,8 +167,7 @@ { public: server(asio::io_service& io_service, short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) + : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) { do_accept(); } @@ -176,12 +175,12 @@ private: void do_accept() { - acceptor_.async_accept(socket_, - [this](std::error_code ec) + acceptor_.async_accept( + [this](std::error_code ec, tcp::socket socket) { if (!ec) { - std::make_shared<session>(std::move(socket_))->start(); + std::make_shared<session>(std::move(socket))->start(); } do_accept(); @@ -189,7 +188,6 @@ } tcp::acceptor acceptor_; - tcp::socket socket_; }; int main(int argc, char* argv[])
diff --git a/asio/src/examples/cpp11/buffers/reference_counted.cpp b/asio/src/examples/cpp11/buffers/reference_counted.cpp index da66385..32c0d8a 100644 --- a/asio/src/examples/cpp11/buffers/reference_counted.cpp +++ b/asio/src/examples/cpp11/buffers/reference_counted.cpp
@@ -73,8 +73,7 @@ { public: server(asio::io_service& io_service, short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) + : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) { do_accept(); } @@ -82,12 +81,12 @@ private: void do_accept() { - acceptor_.async_accept(socket_, - [this](std::error_code ec) + acceptor_.async_accept( + [this](std::error_code ec, tcp::socket socket) { if (!ec) { - std::make_shared<session>(std::move(socket_))->start(); + std::make_shared<session>(std::move(socket))->start(); } do_accept(); @@ -95,7 +94,6 @@ } tcp::acceptor acceptor_; - tcp::socket socket_; }; int main(int argc, char* argv[])
diff --git a/asio/src/examples/cpp11/chat/chat_server.cpp b/asio/src/examples/cpp11/chat/chat_server.cpp index 0fc20fb..d118576 100644 --- a/asio/src/examples/cpp11/chat/chat_server.cpp +++ b/asio/src/examples/cpp11/chat/chat_server.cpp
@@ -171,8 +171,7 @@ public: chat_server(asio::io_service& io_service, const tcp::endpoint& endpoint) - : acceptor_(io_service, endpoint), - socket_(io_service) + : acceptor_(io_service, endpoint) { do_accept(); } @@ -180,12 +179,12 @@ private: void do_accept() { - acceptor_.async_accept(socket_, - [this](std::error_code ec) + acceptor_.async_accept( + [this](std::error_code ec, tcp::socket socket) { if (!ec) { - std::make_shared<chat_session>(std::move(socket_), room_)->start(); + std::make_shared<chat_session>(std::move(socket), room_)->start(); } do_accept(); @@ -193,7 +192,6 @@ } tcp::acceptor acceptor_; - tcp::socket socket_; chat_room room_; };
diff --git a/asio/src/examples/cpp11/http/server/server.cpp b/asio/src/examples/cpp11/http/server/server.cpp index 72b2e03..9114792 100644 --- a/asio/src/examples/cpp11/http/server/server.cpp +++ b/asio/src/examples/cpp11/http/server/server.cpp
@@ -21,7 +21,6 @@ signals_(io_service_), acceptor_(io_service_), connection_manager_(), - socket_(io_service_), request_handler_(doc_root) { // Register to handle the signals that indicate when the server should exit. @@ -57,8 +56,8 @@ void server::do_accept() { - acceptor_.async_accept(socket_, - [this](std::error_code ec) + acceptor_.async_accept( + [this](std::error_code ec, asio::ip::tcp::socket socket) { // Check whether the server was stopped by a signal before this // completion handler had a chance to run. @@ -70,7 +69,7 @@ if (!ec) { connection_manager_.start(std::make_shared<connection>( - std::move(socket_), connection_manager_, request_handler_)); + std::move(socket), connection_manager_, request_handler_)); } do_accept();
diff --git a/asio/src/examples/cpp11/http/server/server.hpp b/asio/src/examples/cpp11/http/server/server.hpp index d82b5d3..88b8d75 100644 --- a/asio/src/examples/cpp11/http/server/server.hpp +++ b/asio/src/examples/cpp11/http/server/server.hpp
@@ -54,9 +54,6 @@ /// The connection manager which owns all live connections. connection_manager connection_manager_; - /// The next socket to be accepted. - asio::ip::tcp::socket socket_; - /// The handler for all incoming requests. request_handler request_handler_; };
diff --git a/asio/src/tests/unit/ip/tcp.cpp b/asio/src/tests/unit/ip/tcp.cpp index 1b0be8c..cc14f05 100644 --- a/asio/src/tests/unit/ip/tcp.cpp +++ b/asio/src/tests/unit/ip/tcp.cpp
@@ -700,6 +700,17 @@ #endif // defined(ASIO_HAS_MOVE) }; +#if defined(ASIO_HAS_MOVE) +struct move_accept_handler +{ + move_accept_handler() {} + void operator()(const asio::error_code&, asio::ip::tcp::socket) {} + move_accept_handler(move_accept_handler&&) {} +private: + move_accept_handler(const move_accept_handler&) {} +}; +#endif // defined(ASIO_HAS_MOVE) + void test() { using namespace asio; @@ -822,12 +833,27 @@ acceptor1.accept(peer_socket, peer_endpoint); acceptor1.accept(peer_socket, peer_endpoint, ec); +#if defined(ASIO_HAS_MOVE) + peer_socket = acceptor1.accept(); + peer_socket = acceptor1.accept(ios); + peer_socket = acceptor1.accept(peer_endpoint); + peer_socket = acceptor1.accept(ios, peer_endpoint); + (void)peer_socket; +#endif // defined(ASIO_HAS_MOVE) + acceptor1.async_accept(peer_socket, accept_handler()); acceptor1.async_accept(peer_socket, peer_endpoint, accept_handler()); int i2 = acceptor1.async_accept(peer_socket, lazy); (void)i2; int i3 = acceptor1.async_accept(peer_socket, peer_endpoint, lazy); (void)i3; + +#if defined(ASIO_HAS_MOVE) + acceptor1.async_accept(move_accept_handler()); + acceptor1.async_accept(ios, move_accept_handler()); + acceptor1.async_accept(peer_endpoint, move_accept_handler()); + acceptor1.async_accept(ios, peer_endpoint, move_accept_handler()); +#endif // defined(ASIO_HAS_MOVE) } catch (std::exception&) {