Initial implementation of move-enable accept/async_accept.
This commit adds support for the new form of accept and async_accept. In this form, rather than taking a socket by reference, the newly accepted socket is returned to the caller/callback as a movable socket object.
This commit is contained in:
parent
7eee8f1875
commit
f475b21437
@ -1029,7 +1029,7 @@ public:
|
||||
* @code
|
||||
* asio::ip::tcp::acceptor acceptor(io_service);
|
||||
* ...
|
||||
* asio::ip::tcp::soocket socket(io_service);
|
||||
* asio::ip::tcp::socket socket(io_service);
|
||||
* asio::error_code ec;
|
||||
* acceptor.accept(socket, ec);
|
||||
* if (ec)
|
||||
@ -1211,6 +1211,122 @@ public:
|
||||
return this->get_service().async_accept(this->get_implementation(), peer,
|
||||
&peer_endpoint, ASIO_MOVE_CAST(AcceptHandler)(handler));
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// 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.
|
||||
*
|
||||
* @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::error_code ec;
|
||||
typename Protocol::socket peer(
|
||||
this->get_service().accept(
|
||||
this->get_implementation(), 0, 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 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(ec));
|
||||
* if (ec)
|
||||
* {
|
||||
* // An error occurred.
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
typename Protocol::socket accept(asio::error_code& ec)
|
||||
{
|
||||
return this->get_service().accept(this->get_implementation(), 0, 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 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::socket socket(io_service);
|
||||
* acceptor.async_accept(socket, accept_handler);
|
||||
* @endcode
|
||||
*/
|
||||
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;
|
||||
|
||||
return this->get_service().async_accept(this->get_implementation(),
|
||||
static_cast<endpoint_type*>(0),
|
||||
ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
@ -220,6 +220,132 @@ inline binder2<Handler, Arg1, Arg2> bind_handler(
|
||||
ASIO_MOVE_CAST(Handler)(handler), arg1, arg2);
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
class move_binder1
|
||||
{
|
||||
public:
|
||||
move_binder1(int, ASIO_MOVE_ARG(Handler) handler,
|
||||
ASIO_MOVE_ARG(Arg1) arg1)
|
||||
: handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
arg1_(ASIO_MOVE_CAST(Arg1)(arg1))
|
||||
{
|
||||
}
|
||||
|
||||
move_binder1(move_binder1&& other)
|
||||
: handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),
|
||||
arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_))
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(ASIO_MOVE_CAST(Arg1)(arg1_));
|
||||
}
|
||||
|
||||
//private:
|
||||
Handler handler_;
|
||||
Arg1 arg1_;
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
move_binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
return asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
move_binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1>
|
||||
inline bool asio_handler_is_continuation(
|
||||
move_binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
return asio_handler_cont_helpers::is_continuation(
|
||||
this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1>
|
||||
inline void asio_handler_invoke(ASIO_MOVE_ARG(Function) function,
|
||||
move_binder1<Handler, Arg1>* this_handler)
|
||||
{
|
||||
asio_handler_invoke_helpers::invoke(
|
||||
ASIO_MOVE_CAST(Function)(function), this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
class move_binder2
|
||||
{
|
||||
public:
|
||||
move_binder2(int, ASIO_MOVE_ARG(Handler) handler,
|
||||
const Arg1& arg1, ASIO_MOVE_ARG(Arg2) arg2)
|
||||
: handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
arg1_(arg1),
|
||||
arg2_(ASIO_MOVE_CAST(Arg2)(arg2))
|
||||
{
|
||||
}
|
||||
|
||||
move_binder2(move_binder2&& other)
|
||||
: handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),
|
||||
arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),
|
||||
arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_))
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
handler_(static_cast<const Arg1&>(arg1_),
|
||||
ASIO_MOVE_CAST(Arg2)(arg2_));
|
||||
}
|
||||
|
||||
//private:
|
||||
Handler handler_;
|
||||
Arg1 arg1_;
|
||||
Arg2 arg2_;
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
move_binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
return asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
move_binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
inline bool asio_handler_is_continuation(
|
||||
move_binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
return asio_handler_cont_helpers::is_continuation(
|
||||
this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function, typename Handler, typename Arg1, typename Arg2>
|
||||
inline void asio_handler_invoke(ASIO_MOVE_ARG(Function) function,
|
||||
move_binder2<Handler, Arg1, Arg2>* this_handler)
|
||||
{
|
||||
asio_handler_invoke_helpers::invoke(
|
||||
ASIO_MOVE_CAST(Function)(function), this_handler->handler_);
|
||||
}
|
||||
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Handler, typename Arg1, typename Allocator>
|
||||
@ -270,6 +396,59 @@ struct associated_executor<detail::binder2<Handler, Arg1, Arg2>, Executor>
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
|
||||
template <typename Handler, typename Arg1, typename Allocator>
|
||||
struct associated_allocator<detail::move_binder1<Handler, Arg1>, Allocator>
|
||||
{
|
||||
typedef typename associated_allocator<Handler, Allocator>::type type;
|
||||
|
||||
static type get(const detail::move_binder1<Handler, Arg1>& h,
|
||||
const Allocator& a = Allocator()) ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Allocator>
|
||||
struct associated_allocator<
|
||||
detail::move_binder2<Handler, Arg1, Arg2>, Allocator>
|
||||
{
|
||||
typedef typename associated_allocator<Handler, Allocator>::type type;
|
||||
|
||||
static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
|
||||
const Allocator& a = Allocator()) ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Executor>
|
||||
struct associated_executor<detail::move_binder1<Handler, Arg1>, Executor>
|
||||
{
|
||||
typedef typename associated_executor<Handler, Executor>::type type;
|
||||
|
||||
static type get(const detail::move_binder1<Handler, Arg1>& h,
|
||||
const Executor& ex = Executor()) ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<Handler, Executor>::get(h.handler_, ex);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2, typename Executor>
|
||||
struct associated_executor<detail::move_binder2<Handler, Arg1, Arg2>, Executor>
|
||||
{
|
||||
typedef typename associated_executor<Handler, Executor>::type type;
|
||||
|
||||
static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
|
||||
const Executor& ex = Executor()) ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<Handler, Executor>::get(h.handler_, ex);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
@ -100,6 +100,16 @@ auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
|
||||
template <typename Handler>
|
||||
char (&two_arg_handler_test(Handler, ...))[2];
|
||||
|
||||
template <typename Handler, typename Arg1, typename Arg2>
|
||||
auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
|
||||
-> decltype(
|
||||
sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),
|
||||
((h)(*a1, ASIO_MOVE_CAST(Arg2)(*a2))),
|
||||
char(0));
|
||||
|
||||
template <typename Handler>
|
||||
char (&two_arg_move_handler_test(Handler, ...))[2];
|
||||
|
||||
# define ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
|
||||
static_assert(expr, msg);
|
||||
|
||||
@ -228,6 +238,33 @@ struct handler_type_requirements
|
||||
asio::detail::lvref<const asio::error_code>()), \
|
||||
char(0))> ASIO_UNUSED_TYPEDEF
|
||||
|
||||
#define ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
|
||||
handler_type, handler, socket_type) \
|
||||
\
|
||||
typedef ASIO_HANDLER_TYPE(handler_type, \
|
||||
void(asio::error_code, socket_type)) \
|
||||
asio_true_handler_type; \
|
||||
\
|
||||
ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
|
||||
sizeof(asio::detail::two_arg_move_handler_test( \
|
||||
asio::detail::rvref< \
|
||||
asio_true_handler_type>(), \
|
||||
static_cast<const asio::error_code*>(0), \
|
||||
static_cast<socket_type*>(0))) == 1, \
|
||||
"MoveAcceptHandler type requirements not met") \
|
||||
\
|
||||
typedef asio::detail::handler_type_requirements< \
|
||||
sizeof( \
|
||||
asio::detail::argbyv( \
|
||||
asio::detail::rvref< \
|
||||
asio_true_handler_type>())) + \
|
||||
sizeof( \
|
||||
asio::detail::lvref< \
|
||||
asio_true_handler_type>()( \
|
||||
asio::detail::lvref<const asio::error_code>(), \
|
||||
asio::detail::rvref<socket_type>()), \
|
||||
char(0))> ASIO_UNUSED_TYPEDEF
|
||||
|
||||
#define ASIO_CONNECT_HANDLER_CHECK( \
|
||||
handler_type, handler) \
|
||||
\
|
||||
|
@ -29,7 +29,8 @@ namespace detail {
|
||||
|
||||
reactive_socket_service_base::reactive_socket_service_base(
|
||||
asio::io_service& io_service)
|
||||
: reactor_(use_service<reactor>(io_service))
|
||||
: io_service_(io_service),
|
||||
reactor_(use_service<reactor>(io_service))
|
||||
{
|
||||
reactor_.init_task();
|
||||
}
|
||||
|
@ -130,6 +130,70 @@ private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
|
||||
template <typename Protocol, typename Handler>
|
||||
class reactive_socket_move_accept_op :
|
||||
private Protocol::socket,
|
||||
public reactive_socket_accept_op_base<typename Protocol::socket, Protocol>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op);
|
||||
|
||||
reactive_socket_move_accept_op(io_service& ios, socket_type socket,
|
||||
socket_ops::state_type state, const Protocol& protocol,
|
||||
typename Protocol::endpoint* peer_endpoint, Handler& handler)
|
||||
: Protocol::socket(ios),
|
||||
reactive_socket_accept_op_base<typename Protocol::socket, Protocol>(
|
||||
socket, state, *this, protocol, peer_endpoint,
|
||||
&reactive_socket_move_accept_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
const asio::error_code& /*ec*/,
|
||||
std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
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));
|
||||
|
||||
// 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_), o->ec_,
|
||||
ASIO_MOVE_CAST(typename Protocol::socket)(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:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
|
@ -388,8 +388,33 @@ public:
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Start an asynchronous accept. The peer and peer_endpoint objects
|
||||
// must be valid until the accept's handler is invoked.
|
||||
// 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 : io_service_);
|
||||
|
||||
std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
|
||||
socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
|
||||
impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
|
||||
peer_endpoint ? &addr_len : 0, ec));
|
||||
|
||||
// On success, assign new connection to peer socket object.
|
||||
if (new_socket.get() != invalid_socket)
|
||||
{
|
||||
if (peer_endpoint)
|
||||
peer_endpoint->resize(addr_len);
|
||||
if (!peer.assign(impl.protocol_, new_socket.get(), ec))
|
||||
new_socket.release();
|
||||
}
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
// Start an asynchronous accept. The peer and peer_endpoint objects must be
|
||||
// valid until the accept's handler is invoked.
|
||||
template <typename Socket, typename Handler>
|
||||
void async_accept(implementation_type& impl, Socket& peer,
|
||||
endpoint_type* peer_endpoint, Handler& handler)
|
||||
@ -410,6 +435,30 @@ public:
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
// Start an asynchronous accept. The peer_endpoint object must be valid until
|
||||
// the accept's handler is invoked.
|
||||
template <typename Handler>
|
||||
void async_accept(implementation_type& impl,
|
||||
endpoint_type* peer_endpoint, Handler& handler)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_move_accept_op<Protocol, Handler> op;
|
||||
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);
|
||||
|
||||
ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
|
||||
|
||||
start_accept_op(impl, p.p, is_continuation, false);
|
||||
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)
|
||||
|
@ -490,6 +490,9 @@ protected:
|
||||
reactor_op* op, bool is_continuation,
|
||||
const socket_addr_type* addr, size_t addrlen);
|
||||
|
||||
// The io_service that owns this socket service.
|
||||
io_service& io_service_;
|
||||
|
||||
// The selector that performs event demultiplexing for the service.
|
||||
reactor& reactor_;
|
||||
};
|
||||
|
@ -457,6 +457,31 @@ public:
|
||||
return ec;
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
|
||||
socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
|
||||
impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
|
||||
peer_endpoint ? &addr_len : 0, ec));
|
||||
|
||||
// On success, assign new connection to peer socket object.
|
||||
if (new_socket.get() != invalid_socket)
|
||||
{
|
||||
if (peer_endpoint)
|
||||
peer_endpoint->resize(addr_len);
|
||||
if (!peer.assign(impl.protocol_, new_socket.get(), ec))
|
||||
new_socket.release();
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Start an asynchronous accept. The peer and peer_endpoint objects
|
||||
// must be valid until the accept's handler is invoked.
|
||||
template <typename Socket, typename Handler>
|
||||
|
@ -276,6 +276,16 @@ public:
|
||||
return service_impl_.accept(impl, peer, peer_endpoint, 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)
|
||||
{
|
||||
return service_impl_.accept(impl, peer_io_service, peer_endpoint, ec);
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
/// Start an asynchronous accept.
|
||||
template <typename Protocol1, typename SocketService, typename AcceptHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(AcceptHandler,
|
||||
@ -294,6 +304,24 @@ public:
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
/// Start an asynchronous accept.
|
||||
template <typename MoveAcceptHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
|
||||
void (asio::error_code, typename Protocol::socket))
|
||||
async_accept(implementation_type& impl,
|
||||
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);
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
private:
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
void shutdown_service()
|
||||
|
@ -346,6 +346,7 @@
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Type Requirements</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="asio.reference.AcceptableProtocol">AcceptableProtocol</link></member>
|
||||
<member><link linkend="asio.reference.AcceptHandler">AcceptHandler</link></member>
|
||||
<member><link linkend="asio.reference.ComposedConnectHandler">ComposedConnectHandler</link></member>
|
||||
<member><link linkend="asio.reference.ConnectHandler">ConnectHandler</link></member>
|
||||
|
@ -37,6 +37,7 @@
|
||||
[xinclude quickref.xml]
|
||||
|
||||
[include requirements/asynchronous_operations.qbk]
|
||||
[include requirements/AcceptableProtocol.qbk]
|
||||
[include requirements/AcceptHandler.qbk]
|
||||
[include requirements/AsyncRandomAccessReadDevice.qbk]
|
||||
[include requirements/AsyncRandomAccessWriteDevice.qbk]
|
||||
|
25
asio/src/doc/requirements/AcceptableProtocol.qbk
Normal file
25
asio/src/doc/requirements/AcceptableProtocol.qbk
Normal file
@ -0,0 +1,25 @@
|
||||
[/
|
||||
/ Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
/]
|
||||
|
||||
[section:AcceptableProtocol Acceptable protocol requirements]
|
||||
|
||||
An acceptable protocol must meet the requirements for a [link
|
||||
asio.reference.Protocol protocol] as well as the additional requirements listed
|
||||
below.
|
||||
|
||||
In the table below, `X` denotes an acceptable protocol class.
|
||||
|
||||
[table AcceptableProtocol requirements
|
||||
[[expression] [return type] [assertion/note\npre/post-conditions]]
|
||||
[
|
||||
[`X::socket`]
|
||||
[`
|
||||
[The type of a socket for the protocol.]
|
||||
]
|
||||
]
|
||||
|
||||
[endsect]
|
41
asio/src/doc/requirements/MoveAcceptHandler.qbk
Normal file
41
asio/src/doc/requirements/MoveAcceptHandler.qbk
Normal file
@ -0,0 +1,41 @@
|
||||
[/
|
||||
/ Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
/]
|
||||
|
||||
[section:MoveAcceptHandler Move accept handler requirements]
|
||||
|
||||
A move accept handler must meet the requirements for a [link
|
||||
asio.reference.Handler handler]. A value `h` of a move accept handler class
|
||||
should work correctly in the expression `h(ec, s)`, where `ec` is an lvalue of
|
||||
type `const error_code` and `s` is an lvalue of the nested type
|
||||
`Protocol::socket` for the type `Protocol` of the socket class template.
|
||||
|
||||
[heading Examples]
|
||||
|
||||
A free function as a move accept handler:
|
||||
|
||||
void connect_handler(
|
||||
const asio::error_code& ec,
|
||||
asio::ip::tcp::socket s)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
A move accept handler function object:
|
||||
|
||||
struct connect_handler
|
||||
{
|
||||
...
|
||||
void operator()(
|
||||
const asio::error_code& ec,
|
||||
asio::ip::tcp::socket s)
|
||||
{
|
||||
...
|
||||
}
|
||||
...
|
||||
};
|
||||
|
||||
[endsect]
|
@ -66,8 +66,7 @@ class server
|
||||
{
|
||||
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();
|
||||
}
|
||||
@ -75,12 +74,12 @@ public:
|
||||
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();
|
||||
@ -88,7 +87,6 @@ private:
|
||||
}
|
||||
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
|
@ -47,9 +47,7 @@ void server(asio::io_service& io_service, unsigned short port)
|
||||
tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
|
||||
for (;;)
|
||||
{
|
||||
tcp::socket sock(io_service);
|
||||
a.accept(sock);
|
||||
std::thread(session, std::move(sock)).detach();
|
||||
std::thread(session, a.accept()).detach();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user