Add custom I/O executor support to I/O objects.
All I/O objects now have an additional Executor template parameter. This template parameter defaults to the asio::executor type (the polymorphic executor wrapper) but can be used to specify a user-defined executor type. I/O objects' constructors and functions that previously took an asio::io_context& now accept either an Executor or a reference to a concrete ExecutionContext (such as asio::io_context or asio::thread_pool). One potential point of breakage in existing user code is when reusing an I/O object's io_context for constructing another I/O object, as in: asio::steady_timer my_timer(my_socket.get_executor().context()); To fix this, either construct the second I/O object using the first I/O object's executor: asio::steady_timer my_timer(my_socket.get_executor()); or otherwise explicitly pass the io_context: asio::steady_timer my_timer(my_io_context);
This commit is contained in:
parent
2c689adc90
commit
cbe1c5e13d
3751
asio/asio.manifest
3751
asio/asio.manifest
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,8 @@ nobase_include_HEADERS = \
|
||||
asio/basic_io_object.hpp \
|
||||
asio/basic_raw_socket.hpp \
|
||||
asio/basic_seq_packet_socket.hpp \
|
||||
asio/basic_serial_port.hpp \
|
||||
asio/basic_signal_set.hpp \
|
||||
asio/basic_socket_acceptor.hpp \
|
||||
asio/basic_socket.hpp \
|
||||
asio/basic_socket_iostream.hpp \
|
||||
@ -51,6 +53,7 @@ nobase_include_HEADERS = \
|
||||
asio/detail/cstddef.hpp \
|
||||
asio/detail/cstdint.hpp \
|
||||
asio/detail/date_time_fwd.hpp \
|
||||
asio/detail/deadline_timer_service.hpp \
|
||||
asio/detail/dependent_type.hpp \
|
||||
asio/detail/descriptor_ops.hpp \
|
||||
asio/detail/descriptor_read_op.hpp \
|
||||
@ -128,6 +131,7 @@ nobase_include_HEADERS = \
|
||||
asio/detail/impl/win_thread.ipp \
|
||||
asio/detail/impl/win_tss_ptr.ipp \
|
||||
asio/detail/io_control.hpp \
|
||||
asio/detail/io_object_executor.hpp \
|
||||
asio/detail/io_object_impl.hpp \
|
||||
asio/detail/is_buffer_sequence.hpp \
|
||||
asio/detail/is_executor.hpp \
|
||||
@ -390,6 +394,8 @@ nobase_include_HEADERS = \
|
||||
asio/local/stream_protocol.hpp \
|
||||
asio/packaged_task.hpp \
|
||||
asio/placeholders.hpp \
|
||||
asio/posix/basic_descriptor.hpp \
|
||||
asio/posix/basic_stream_descriptor.hpp \
|
||||
asio/posix/descriptor_base.hpp \
|
||||
asio/posix/descriptor.hpp \
|
||||
asio/posix/stream_descriptor.hpp \
|
||||
@ -453,6 +459,10 @@ nobase_include_HEADERS = \
|
||||
asio/uses_executor.hpp \
|
||||
asio/version.hpp \
|
||||
asio/wait_traits.hpp \
|
||||
asio/windows/basic_object_handle.hpp \
|
||||
asio/windows/basic_overlapped_handle.hpp \
|
||||
asio/windows/basic_random_access_handle.hpp \
|
||||
asio/windows/basic_stream_handle.hpp \
|
||||
asio/windows/object_handle.hpp \
|
||||
asio/windows/overlapped_handle.hpp \
|
||||
asio/windows/overlapped_ptr.hpp \
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include "asio/basic_io_object.hpp"
|
||||
#include "asio/basic_raw_socket.hpp"
|
||||
#include "asio/basic_seq_packet_socket.hpp"
|
||||
#include "asio/basic_serial_port.hpp"
|
||||
#include "asio/basic_signal_set.hpp"
|
||||
#include "asio/basic_socket.hpp"
|
||||
#include "asio/basic_socket_acceptor.hpp"
|
||||
#include "asio/basic_socket_iostream.hpp"
|
||||
#include "asio/basic_socket_streambuf.hpp"
|
||||
@ -94,6 +97,8 @@
|
||||
#include "asio/local/stream_protocol.hpp"
|
||||
#include "asio/packaged_task.hpp"
|
||||
#include "asio/placeholders.hpp"
|
||||
#include "asio/posix/basic_descriptor.hpp"
|
||||
#include "asio/posix/basic_stream_descriptor.hpp"
|
||||
#include "asio/posix/descriptor.hpp"
|
||||
#include "asio/posix/descriptor_base.hpp"
|
||||
#include "asio/posix/stream_descriptor.hpp"
|
||||
@ -119,6 +124,10 @@
|
||||
#include "asio/uses_executor.hpp"
|
||||
#include "asio/version.hpp"
|
||||
#include "asio/wait_traits.hpp"
|
||||
#include "asio/windows/basic_object_handle.hpp"
|
||||
#include "asio/windows/basic_overlapped_handle.hpp"
|
||||
#include "asio/windows/basic_random_access_handle.hpp"
|
||||
#include "asio/windows/basic_stream_handle.hpp"
|
||||
#include "asio/windows/object_handle.hpp"
|
||||
#include "asio/windows/overlapped_handle.hpp"
|
||||
#include "asio/windows/overlapped_ptr.hpp"
|
||||
|
@ -27,6 +27,15 @@
|
||||
|
||||
namespace asio {
|
||||
|
||||
#if !defined(ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
|
||||
#define ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename Protocol, typename Executor = executor>
|
||||
class basic_datagram_socket;
|
||||
|
||||
#endif // !defined(ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
|
||||
|
||||
/// Provides datagram-oriented socket functionality.
|
||||
/**
|
||||
* The basic_datagram_socket class template provides asynchronous and blocking
|
||||
@ -36,17 +45,28 @@ namespace asio {
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename Protocol>
|
||||
template <typename Protocol, typename Executor>
|
||||
class basic_datagram_socket
|
||||
: public basic_socket<Protocol>
|
||||
: public basic_socket<Protocol, Executor>
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// Rebinds the socket type to another executor.
|
||||
template <typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_datagram_socket<Protocol, Executor1> other;
|
||||
};
|
||||
|
||||
/// The native representation of a socket.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_handle_type;
|
||||
#else
|
||||
typedef typename basic_socket<
|
||||
Protocol>::native_handle_type native_handle_type;
|
||||
typedef typename basic_socket<Protocol,
|
||||
Executor>::native_handle_type native_handle_type;
|
||||
#endif
|
||||
|
||||
/// The protocol type.
|
||||
@ -60,12 +80,29 @@ public:
|
||||
* This constructor creates a datagram socket without opening it. The open()
|
||||
* function must be called before data can be sent or received on the socket.
|
||||
*
|
||||
* @param io_context The io_context object that the datagram socket will use
|
||||
* to dispatch handlers for any asynchronous operations performed on the
|
||||
* socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*/
|
||||
explicit basic_datagram_socket(asio::io_context& io_context)
|
||||
: basic_socket<Protocol>(io_context)
|
||||
explicit basic_datagram_socket(const executor_type& ex)
|
||||
: basic_socket<Protocol, Executor>(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_datagram_socket without opening it.
|
||||
/**
|
||||
* This constructor creates a datagram socket without opening it. The open()
|
||||
* function must be called before data can be sent or received on the socket.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_datagram_socket(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -73,17 +110,37 @@ public:
|
||||
/**
|
||||
* This constructor creates and opens a datagram socket.
|
||||
*
|
||||
* @param io_context The io_context object that the datagram socket will use
|
||||
* to dispatch handlers for any asynchronous operations performed on the
|
||||
* socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_datagram_socket(asio::io_context& io_context,
|
||||
const protocol_type& protocol)
|
||||
: basic_socket<Protocol>(io_context, protocol)
|
||||
basic_datagram_socket(const executor_type& ex, const protocol_type& protocol)
|
||||
: basic_socket<Protocol, Executor>(ex, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct and open a basic_datagram_socket.
|
||||
/**
|
||||
* This constructor creates and opens a datagram socket.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_datagram_socket(ExecutionContext& context,
|
||||
const protocol_type& protocol,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
@ -94,18 +151,42 @@ public:
|
||||
* to the specified endpoint on the local machine. The protocol used is the
|
||||
* protocol associated with the given endpoint.
|
||||
*
|
||||
* @param io_context The io_context object that the datagram socket will use
|
||||
* to dispatch handlers for any asynchronous operations performed on the
|
||||
* socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the datagram
|
||||
* socket will be bound.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_datagram_socket(asio::io_context& io_context,
|
||||
const endpoint_type& endpoint)
|
||||
: basic_socket<Protocol>(io_context, endpoint)
|
||||
basic_datagram_socket(const executor_type& ex, const endpoint_type& endpoint)
|
||||
: basic_socket<Protocol, Executor>(ex, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_datagram_socket, opening it and binding it to the given
|
||||
/// local endpoint.
|
||||
/**
|
||||
* This constructor creates a datagram socket and automatically opens it bound
|
||||
* to the specified endpoint on the local machine. The protocol used is the
|
||||
* protocol associated with the given endpoint.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the datagram
|
||||
* socket will be bound.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_datagram_socket(ExecutionContext& context,
|
||||
const endpoint_type& endpoint,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
@ -114,9 +195,8 @@ public:
|
||||
* This constructor creates a datagram socket object to hold an existing
|
||||
* native socket.
|
||||
*
|
||||
* @param io_context The io_context object that the datagram socket will use
|
||||
* to dispatch handlers for any asynchronous operations performed on the
|
||||
* socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
@ -124,9 +204,34 @@ public:
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_datagram_socket(asio::io_context& io_context,
|
||||
basic_datagram_socket(const executor_type& ex,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket)
|
||||
: basic_socket<Protocol>(io_context, protocol, native_socket)
|
||||
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_datagram_socket on an existing native socket.
|
||||
/**
|
||||
* This constructor creates a datagram socket object to hold an existing
|
||||
* native socket.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @param native_socket The new underlying socket implementation.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_datagram_socket(ExecutionContext& context,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
@ -139,10 +244,11 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_datagram_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_datagram_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_datagram_socket(basic_datagram_socket&& other)
|
||||
: basic_socket<Protocol>(std::move(other))
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
@ -155,11 +261,12 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_datagram_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_datagram_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_datagram_socket& operator=(basic_datagram_socket&& other)
|
||||
{
|
||||
basic_socket<Protocol>::operator=(std::move(other));
|
||||
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -172,12 +279,16 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_datagram_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_datagram_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1>
|
||||
basic_datagram_socket(basic_datagram_socket<Protocol1>&& other,
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
|
||||
: basic_socket<Protocol>(std::move(other))
|
||||
template <typename Protocol1, typename Executor1>
|
||||
basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,
|
||||
typename enable_if<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
@ -191,14 +302,17 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_datagram_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_datagram_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1>
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value,
|
||||
basic_datagram_socket>::type& operator=(
|
||||
basic_datagram_socket<Protocol1>&& other)
|
||||
template <typename Protocol1, typename Executor1>
|
||||
typename enable_if<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value,
|
||||
basic_datagram_socket&
|
||||
>::type operator=(basic_datagram_socket<Protocol1, Executor1>&& other)
|
||||
{
|
||||
basic_socket<Protocol>::operator=(std::move(other));
|
||||
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
@ -315,9 +429,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The async_send operation can only be used with a connected socket.
|
||||
* Use the async_send_to function to send data on an unconnected datagram
|
||||
@ -346,7 +460,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send(this->impl_.get_implementation(),
|
||||
buffers, 0, init.completion_handler);
|
||||
buffers, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -371,9 +486,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The async_send operation can only be used with a connected socket.
|
||||
* Use the async_send_to function to send data on an unconnected datagram
|
||||
@ -394,7 +509,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send(this->impl_.get_implementation(),
|
||||
buffers, flags, init.completion_handler);
|
||||
buffers, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -508,9 +624,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* To send a single data buffer use the @ref buffer function as follows:
|
||||
@ -538,9 +654,9 @@ public:
|
||||
async_completion<WriteHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send_to(
|
||||
this->impl_.get_implementation(), buffers, destination, 0,
|
||||
init.completion_handler);
|
||||
this->impl_.get_service().async_send_to(this->impl_.get_implementation(),
|
||||
buffers, destination, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -568,9 +684,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*/
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
||||
@ -588,7 +704,7 @@ public:
|
||||
|
||||
this->impl_.get_service().async_send_to(
|
||||
this->impl_.get_implementation(), buffers, destination, flags,
|
||||
init.completion_handler);
|
||||
init.completion_handler, this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -700,9 +816,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The async_receive operation can only be used with a connected socket.
|
||||
* Use the async_receive_from function to receive data on an unconnected
|
||||
@ -732,7 +848,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_receive(this->impl_.get_implementation(),
|
||||
buffers, 0, init.completion_handler);
|
||||
buffers, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -757,9 +874,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The async_receive operation can only be used with a connected socket.
|
||||
* Use the async_receive_from function to receive data on an unconnected
|
||||
@ -780,7 +897,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_receive(this->impl_.get_implementation(),
|
||||
buffers, flags, init.completion_handler);
|
||||
buffers, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -897,9 +1015,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* To receive into a single data buffer use the @ref buffer function as
|
||||
@ -926,7 +1044,8 @@ public:
|
||||
|
||||
this->impl_.get_service().async_receive_from(
|
||||
this->impl_.get_implementation(), buffers,
|
||||
sender_endpoint, 0, init.completion_handler);
|
||||
sender_endpoint, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -956,9 +1075,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
||||
@ -976,7 +1095,8 @@ public:
|
||||
|
||||
this->impl_.get_service().async_receive_from(
|
||||
this->impl_.get_implementation(), buffers,
|
||||
sender_endpoint, flags, init.completion_handler);
|
||||
sender_endpoint, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "asio/detail/io_object_impl.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/executor.hpp"
|
||||
#include "asio/time_traits.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
@ -51,7 +53,7 @@ namespace asio {
|
||||
* Performing a blocking wait:
|
||||
* @code
|
||||
* // Construct a timer without setting an expiry time.
|
||||
* asio::deadline_timer timer(io_context);
|
||||
* asio::deadline_timer timer(my_context);
|
||||
*
|
||||
* // Set an expiry time relative to now.
|
||||
* timer.expires_from_now(boost::posix_time::seconds(5));
|
||||
@ -74,7 +76,7 @@ namespace asio {
|
||||
* ...
|
||||
*
|
||||
* // Construct a timer with an absolute expiry time.
|
||||
* asio::deadline_timer timer(io_context,
|
||||
* asio::deadline_timer timer(my_context,
|
||||
* boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
|
||||
*
|
||||
* // Start an asynchronous wait.
|
||||
@ -121,12 +123,13 @@ namespace asio {
|
||||
* it contains the value asio::error::operation_aborted.
|
||||
*/
|
||||
template <typename Time,
|
||||
typename TimeTraits = asio::time_traits<Time> >
|
||||
typename TimeTraits = asio::time_traits<Time>,
|
||||
typename Executor = executor>
|
||||
class basic_deadline_timer
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef io_context::executor_type executor_type;
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// The time traits type.
|
||||
typedef TimeTraits traits_type;
|
||||
@ -143,11 +146,30 @@ public:
|
||||
* expires_at() or expires_from_now() functions must be called to set an
|
||||
* expiry time before the timer can be waited on.
|
||||
*
|
||||
* @param io_context The io_context object that the timer will use to dispatch
|
||||
* handlers for any asynchronous operations performed on the timer.
|
||||
* @param ex The I/O executor that the timer will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||
*/
|
||||
explicit basic_deadline_timer(asio::io_context& io_context)
|
||||
: impl_(io_context)
|
||||
explicit basic_deadline_timer(const executor_type& ex)
|
||||
: impl_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
/**
|
||||
* This constructor creates a timer without setting an expiry time. The
|
||||
* expires_at() or expires_from_now() functions must be called to set an
|
||||
* expiry time before the timer can be waited on.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the timer.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_deadline_timer(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -155,15 +177,37 @@ public:
|
||||
/**
|
||||
* This constructor creates a timer and sets the expiry time.
|
||||
*
|
||||
* @param io_context The io_context object that the timer will use to dispatch
|
||||
* handlers for any asynchronous operations performed on the timer.
|
||||
* @param ex The I/O executor that the timer will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer, expressed
|
||||
* as an absolute time.
|
||||
*/
|
||||
basic_deadline_timer(asio::io_context& io_context,
|
||||
const time_type& expiry_time)
|
||||
: impl_(io_context)
|
||||
basic_deadline_timer(const executor_type& ex, const time_type& expiry_time)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
|
||||
asio::detail::throw_error(ec, "expires_at");
|
||||
}
|
||||
|
||||
/// Constructor to set a particular expiry time as an absolute time.
|
||||
/**
|
||||
* This constructor creates a timer and sets the expiry time.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the timer.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer, expressed
|
||||
* as an absolute time.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
|
||||
@ -174,15 +218,40 @@ public:
|
||||
/**
|
||||
* This constructor creates a timer and sets the expiry time.
|
||||
*
|
||||
* @param io_context The io_context object that the timer will use to dispatch
|
||||
* handlers for any asynchronous operations performed on the timer.
|
||||
* @param ex The I/O executor that the timer will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer, relative to
|
||||
* now.
|
||||
*/
|
||||
basic_deadline_timer(asio::io_context& io_context,
|
||||
basic_deadline_timer(const executor_type& ex,
|
||||
const duration_type& expiry_time)
|
||||
: impl_(io_context)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().expires_from_now(
|
||||
impl_.get_implementation(), expiry_time, ec);
|
||||
asio::detail::throw_error(ec, "expires_from_now");
|
||||
}
|
||||
|
||||
/// Constructor to set a particular expiry time relative to now.
|
||||
/**
|
||||
* This constructor creates a timer and sets the expiry time.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the timer.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer, relative to
|
||||
* now.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_deadline_timer(ExecutionContext& context,
|
||||
const duration_type& expiry_time,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().expires_from_now(
|
||||
@ -199,7 +268,8 @@ public:
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_deadline_timer(io_context&) constructor.
|
||||
* constructed using the @c basic_deadline_timer(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_deadline_timer(basic_deadline_timer&& other)
|
||||
: impl_(std::move(other.impl_))
|
||||
@ -215,7 +285,8 @@ public:
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_deadline_timer(io_context&) constructor.
|
||||
* constructed using the @c basic_deadline_timer(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_deadline_timer& operator=(basic_deadline_timer&& other)
|
||||
{
|
||||
@ -544,9 +615,9 @@ public:
|
||||
* const asio::error_code& error // Result of operation.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*/
|
||||
template <typename WaitHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WaitHandler,
|
||||
@ -561,7 +632,7 @@ public:
|
||||
void (asio::error_code)> init(handler);
|
||||
|
||||
impl_.get_service().async_wait(impl_.get_implementation(),
|
||||
init.completion_handler);
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -572,7 +643,8 @@ private:
|
||||
basic_deadline_timer& operator=(
|
||||
const basic_deadline_timer&) ASIO_DELETED;
|
||||
|
||||
detail::io_object_impl<detail::deadline_timer_service<TimeTraits> > impl_;
|
||||
detail::io_object_impl<
|
||||
detail::deadline_timer_service<TimeTraits>, Executor> impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
@ -27,6 +27,15 @@
|
||||
|
||||
namespace asio {
|
||||
|
||||
#if !defined(ASIO_BASIC_RAW_SOCKET_FWD_DECL)
|
||||
#define ASIO_BASIC_RAW_SOCKET_FWD_DECL
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename Protocol, typename Executor = executor>
|
||||
class basic_raw_socket;
|
||||
|
||||
#endif // !defined(ASIO_BASIC_RAW_SOCKET_FWD_DECL)
|
||||
|
||||
/// Provides raw-oriented socket functionality.
|
||||
/**
|
||||
* The basic_raw_socket class template provides asynchronous and blocking
|
||||
@ -36,17 +45,28 @@ namespace asio {
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename Protocol>
|
||||
template <typename Protocol, typename Executor>
|
||||
class basic_raw_socket
|
||||
: public basic_socket<Protocol>
|
||||
: public basic_socket<Protocol, Executor>
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// Rebinds the socket type to another executor.
|
||||
template <typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_raw_socket<Protocol, Executor1> other;
|
||||
};
|
||||
|
||||
/// The native representation of a socket.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_handle_type;
|
||||
#else
|
||||
typedef typename basic_socket<
|
||||
Protocol>::native_handle_type native_handle_type;
|
||||
typedef typename basic_socket<Protocol,
|
||||
Executor>::native_handle_type native_handle_type;
|
||||
#endif
|
||||
|
||||
/// The protocol type.
|
||||
@ -60,12 +80,29 @@ public:
|
||||
* This constructor creates a raw socket without opening it. The open()
|
||||
* function must be called before data can be sent or received on the socket.
|
||||
*
|
||||
* @param io_context The io_context object that the raw socket will use
|
||||
* to dispatch handlers for any asynchronous operations performed on the
|
||||
* socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*/
|
||||
explicit basic_raw_socket(asio::io_context& io_context)
|
||||
: basic_socket<Protocol>(io_context)
|
||||
explicit basic_raw_socket(const executor_type& ex)
|
||||
: basic_socket<Protocol, Executor>(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_raw_socket without opening it.
|
||||
/**
|
||||
* This constructor creates a raw socket without opening it. The open()
|
||||
* function must be called before data can be sent or received on the socket.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_raw_socket(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -73,17 +110,36 @@ public:
|
||||
/**
|
||||
* This constructor creates and opens a raw socket.
|
||||
*
|
||||
* @param io_context The io_context object that the raw socket will use
|
||||
* to dispatch handlers for any asynchronous operations performed on the
|
||||
* socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_raw_socket(asio::io_context& io_context,
|
||||
const protocol_type& protocol)
|
||||
: basic_socket<Protocol>(io_context, protocol)
|
||||
basic_raw_socket(const executor_type& ex, const protocol_type& protocol)
|
||||
: basic_socket<Protocol, Executor>(ex, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct and open a basic_raw_socket.
|
||||
/**
|
||||
* This constructor creates and opens a raw socket.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_raw_socket(ExecutionContext& context, const protocol_type& protocol,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
@ -94,18 +150,41 @@ public:
|
||||
* to the specified endpoint on the local machine. The protocol used is the
|
||||
* protocol associated with the given endpoint.
|
||||
*
|
||||
* @param io_context The io_context object that the raw socket will use
|
||||
* to dispatch handlers for any asynchronous operations performed on the
|
||||
* socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the raw
|
||||
* socket will be bound.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_raw_socket(asio::io_context& io_context,
|
||||
const endpoint_type& endpoint)
|
||||
: basic_socket<Protocol>(io_context, endpoint)
|
||||
basic_raw_socket(const executor_type& ex, const endpoint_type& endpoint)
|
||||
: basic_socket<Protocol, Executor>(ex, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_raw_socket, opening it and binding it to the given
|
||||
/// local endpoint.
|
||||
/**
|
||||
* This constructor creates a raw socket and automatically opens it bound
|
||||
* to the specified endpoint on the local machine. The protocol used is the
|
||||
* protocol associated with the given endpoint.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the raw
|
||||
* socket will be bound.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
@ -114,9 +193,8 @@ public:
|
||||
* This constructor creates a raw socket object to hold an existing
|
||||
* native socket.
|
||||
*
|
||||
* @param io_context The io_context object that the raw socket will use
|
||||
* to dispatch handlers for any asynchronous operations performed on the
|
||||
* socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
@ -124,9 +202,34 @@ public:
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_raw_socket(asio::io_context& io_context,
|
||||
basic_raw_socket(const executor_type& ex,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket)
|
||||
: basic_socket<Protocol>(io_context, protocol, native_socket)
|
||||
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_raw_socket on an existing native socket.
|
||||
/**
|
||||
* This constructor creates a raw socket object to hold an existing
|
||||
* native socket.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @param native_socket The new underlying socket implementation.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_raw_socket(ExecutionContext& context,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
@ -139,10 +242,11 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_raw_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_raw_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_raw_socket(basic_raw_socket&& other)
|
||||
: basic_socket<Protocol>(std::move(other))
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
@ -154,28 +258,34 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_raw_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_raw_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_raw_socket& operator=(basic_raw_socket&& other)
|
||||
{
|
||||
basic_socket<Protocol>::operator=(std::move(other));
|
||||
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Move-construct a basic_raw_socket from a socket of another protocol type.
|
||||
/// Move-construct a basic_raw_socket from a socket of another protocol
|
||||
/// type.
|
||||
/**
|
||||
* This constructor moves a raw socket from one object to another.
|
||||
*
|
||||
* @param other The other basic_raw_socket object from which the move will
|
||||
* occur.
|
||||
* @param other The other basic_raw_socket object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_raw_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_raw_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1>
|
||||
basic_raw_socket(basic_raw_socket<Protocol1>&& other,
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
|
||||
: basic_socket<Protocol>(std::move(other))
|
||||
template <typename Protocol1, typename Executor1>
|
||||
basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other,
|
||||
typename enable_if<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
@ -187,14 +297,17 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_raw_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_raw_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1>
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value,
|
||||
basic_raw_socket>::type& operator=(
|
||||
basic_raw_socket<Protocol1>&& other)
|
||||
template <typename Protocol1, typename Executor1>
|
||||
typename enable_if<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value,
|
||||
basic_raw_socket&
|
||||
>::type operator=(basic_raw_socket<Protocol1, Executor1>&& other)
|
||||
{
|
||||
basic_socket<Protocol>::operator=(std::move(other));
|
||||
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
@ -308,9 +421,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The async_send operation can only be used with a connected socket.
|
||||
* Use the async_send_to function to send data on an unconnected raw
|
||||
@ -339,7 +452,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send(this->impl_.get_implementation(),
|
||||
buffers, 0, init.completion_handler);
|
||||
buffers, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -364,9 +478,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The async_send operation can only be used with a connected socket.
|
||||
* Use the async_send_to function to send data on an unconnected raw
|
||||
@ -387,7 +501,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send(this->impl_.get_implementation(),
|
||||
buffers, flags, init.completion_handler);
|
||||
buffers, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -501,9 +616,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* To send a single data buffer use the @ref buffer function as follows:
|
||||
@ -532,7 +647,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send_to(this->impl_.get_implementation(),
|
||||
buffers, destination, 0, init.completion_handler);
|
||||
buffers, destination, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -560,9 +676,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*/
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
||||
@ -580,7 +696,7 @@ public:
|
||||
|
||||
this->impl_.get_service().async_send_to(
|
||||
this->impl_.get_implementation(), buffers, destination, flags,
|
||||
init.completion_handler);
|
||||
init.completion_handler, this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -692,9 +808,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The async_receive operation can only be used with a connected socket.
|
||||
* Use the async_receive_from function to receive data on an unconnected
|
||||
@ -724,7 +840,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_receive(this->impl_.get_implementation(),
|
||||
buffers, 0, init.completion_handler);
|
||||
buffers, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -749,9 +866,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The async_receive operation can only be used with a connected socket.
|
||||
* Use the async_receive_from function to receive data on an unconnected
|
||||
@ -772,7 +889,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_receive(this->impl_.get_implementation(),
|
||||
buffers, flags, init.completion_handler);
|
||||
buffers, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -889,9 +1007,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* To receive into a single data buffer use the @ref buffer function as
|
||||
@ -918,7 +1036,8 @@ public:
|
||||
|
||||
this->impl_.get_service().async_receive_from(
|
||||
this->impl_.get_implementation(), buffers,
|
||||
sender_endpoint, 0, init.completion_handler);
|
||||
sender_endpoint, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -948,9 +1067,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
||||
@ -968,7 +1087,8 @@ public:
|
||||
|
||||
this->impl_.get_service().async_receive_from(
|
||||
this->impl_.get_implementation(), buffers,
|
||||
sender_endpoint, flags, init.completion_handler);
|
||||
sender_endpoint, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
@ -26,6 +26,15 @@
|
||||
|
||||
namespace asio {
|
||||
|
||||
#if !defined(ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
|
||||
#define ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename Protocol, typename Executor = executor>
|
||||
class basic_seq_packet_socket;
|
||||
|
||||
#endif // !defined(ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
|
||||
|
||||
/// Provides sequenced packet socket functionality.
|
||||
/**
|
||||
* The basic_seq_packet_socket class template provides asynchronous and blocking
|
||||
@ -35,17 +44,28 @@ namespace asio {
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename Protocol>
|
||||
template <typename Protocol, typename Executor>
|
||||
class basic_seq_packet_socket
|
||||
: public basic_socket<Protocol>
|
||||
: public basic_socket<Protocol, Executor>
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// Rebinds the socket type to another executor.
|
||||
template <typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_seq_packet_socket<Protocol, Executor1> other;
|
||||
};
|
||||
|
||||
/// The native representation of a socket.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_handle_type;
|
||||
#else
|
||||
typedef typename basic_socket<
|
||||
Protocol>::native_handle_type native_handle_type;
|
||||
typedef typename basic_socket<Protocol,
|
||||
Executor>::native_handle_type native_handle_type;
|
||||
#endif
|
||||
|
||||
/// The protocol type.
|
||||
@ -60,12 +80,30 @@ public:
|
||||
* socket needs to be opened and then connected or accepted before data can
|
||||
* be sent or received on it.
|
||||
*
|
||||
* @param io_context The io_context object that the sequenced packet socket
|
||||
* will use to dispatch handlers for any asynchronous operations performed on
|
||||
* the socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*/
|
||||
explicit basic_seq_packet_socket(asio::io_context& io_context)
|
||||
: basic_socket<Protocol>(io_context)
|
||||
explicit basic_seq_packet_socket(const executor_type& ex)
|
||||
: basic_socket<Protocol, Executor>(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_seq_packet_socket without opening it.
|
||||
/**
|
||||
* This constructor creates a sequenced packet socket without opening it. The
|
||||
* socket needs to be opened and then connected or accepted before data can
|
||||
* be sent or received on it.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_seq_packet_socket(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -75,17 +113,40 @@ public:
|
||||
* needs to be connected or accepted before data can be sent or received on
|
||||
* it.
|
||||
*
|
||||
* @param io_context The io_context object that the sequenced packet socket
|
||||
* will use to dispatch handlers for any asynchronous operations performed on
|
||||
* the socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_seq_packet_socket(asio::io_context& io_context,
|
||||
basic_seq_packet_socket(const executor_type& ex,
|
||||
const protocol_type& protocol)
|
||||
: basic_socket<Protocol>(io_context, protocol)
|
||||
: basic_socket<Protocol, Executor>(ex, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct and open a basic_seq_packet_socket.
|
||||
/**
|
||||
* This constructor creates and opens a sequenced_packet socket. The socket
|
||||
* needs to be connected or accepted before data can be sent or received on
|
||||
* it.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_seq_packet_socket(ExecutionContext& context,
|
||||
const protocol_type& protocol,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
@ -96,18 +157,43 @@ public:
|
||||
* it bound to the specified endpoint on the local machine. The protocol used
|
||||
* is the protocol associated with the given endpoint.
|
||||
*
|
||||
* @param io_context The io_context object that the sequenced packet socket
|
||||
* will use to dispatch handlers for any asynchronous operations performed on
|
||||
* the socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the sequenced
|
||||
* packet socket will be bound.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_seq_packet_socket(asio::io_context& io_context,
|
||||
basic_seq_packet_socket(const executor_type& ex,
|
||||
const endpoint_type& endpoint)
|
||||
: basic_socket<Protocol>(io_context, endpoint)
|
||||
: basic_socket<Protocol, Executor>(ex, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_seq_packet_socket, opening it and binding it to the
|
||||
/// given local endpoint.
|
||||
/**
|
||||
* This constructor creates a sequenced packet socket and automatically opens
|
||||
* it bound to the specified endpoint on the local machine. The protocol used
|
||||
* is the protocol associated with the given endpoint.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the sequenced
|
||||
* packet socket will be bound.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_seq_packet_socket(ExecutionContext& context,
|
||||
const endpoint_type& endpoint,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
@ -116,9 +202,8 @@ public:
|
||||
* This constructor creates a sequenced packet socket object to hold an
|
||||
* existing native socket.
|
||||
*
|
||||
* @param io_context The io_context object that the sequenced packet socket
|
||||
* will use to dispatch handlers for any asynchronous operations performed on
|
||||
* the socket.
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
@ -126,9 +211,34 @@ public:
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_seq_packet_socket(asio::io_context& io_context,
|
||||
basic_seq_packet_socket(const executor_type& ex,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket)
|
||||
: basic_socket<Protocol>(io_context, protocol, native_socket)
|
||||
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_seq_packet_socket on an existing native socket.
|
||||
/**
|
||||
* This constructor creates a sequenced packet socket object to hold an
|
||||
* existing native socket.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @param native_socket The new underlying socket implementation.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_seq_packet_socket(ExecutionContext& context,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
@ -142,10 +252,11 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_seq_packet_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_seq_packet_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_seq_packet_socket(basic_seq_packet_socket&& other)
|
||||
: basic_socket<Protocol>(std::move(other))
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
@ -158,11 +269,12 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_seq_packet_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_seq_packet_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
|
||||
{
|
||||
basic_socket<Protocol>::operator=(std::move(other));
|
||||
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -176,13 +288,16 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_seq_packet_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_seq_packet_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1>
|
||||
basic_seq_packet_socket(
|
||||
basic_seq_packet_socket<Protocol1>&& other,
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
|
||||
: basic_socket<Protocol>(std::move(other))
|
||||
template <typename Protocol1, typename Executor1>
|
||||
basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,
|
||||
typename enable_if<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
@ -196,14 +311,17 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_seq_packet_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_seq_packet_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1>
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value,
|
||||
basic_seq_packet_socket>::type& operator=(
|
||||
basic_seq_packet_socket<Protocol1>&& other)
|
||||
template <typename Protocol1, typename Executor1>
|
||||
typename enable_if<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value,
|
||||
basic_seq_packet_socket&
|
||||
>::type operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other)
|
||||
{
|
||||
basic_socket<Protocol>::operator=(std::move(other));
|
||||
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
@ -297,9 +415,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* To send a single data buffer use the @ref buffer function as follows:
|
||||
@ -325,7 +443,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send(this->impl_.get_implementation(),
|
||||
buffers, flags, init.completion_handler);
|
||||
buffers, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -473,9 +592,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* To receive into a single data buffer use the @ref buffer function as
|
||||
@ -503,7 +622,8 @@ public:
|
||||
|
||||
this->impl_.get_service().async_receive_with_flags(
|
||||
this->impl_.get_implementation(), buffers,
|
||||
0, out_flags, init.completion_handler);
|
||||
0, out_flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -534,9 +654,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* To receive into a single data buffer use the @ref buffer function as
|
||||
@ -567,7 +687,8 @@ public:
|
||||
|
||||
this->impl_.get_service().async_receive_with_flags(
|
||||
this->impl_.get_implementation(), buffers,
|
||||
in_flags, out_flags, init.completion_handler);
|
||||
in_flags, out_flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
839
asio/include/asio/basic_serial_port.hpp
Normal file
839
asio/include/asio/basic_serial_port.hpp
Normal file
@ -0,0 +1,839 @@
|
||||
//
|
||||
// basic_serial_port.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_BASIC_SERIAL_PORT_HPP
|
||||
#define ASIO_BASIC_SERIAL_PORT_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_SERIAL_PORT) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#include <string>
|
||||
#include "asio/async_result.hpp"
|
||||
#include "asio/detail/handler_type_requirements.hpp"
|
||||
#include "asio/detail/io_object_impl.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/type_traits.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/executor.hpp"
|
||||
#include "asio/serial_port_base.hpp"
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_serial_port_service.hpp"
|
||||
#else
|
||||
# include "asio/detail/reactive_serial_port_service.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
# include <utility>
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// Provides serial port functionality.
|
||||
/**
|
||||
* The basic_serial_port class provides a wrapper over serial port
|
||||
* functionality.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename Executor = executor>
|
||||
class basic_serial_port
|
||||
: public serial_port_base
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// The native representation of a serial port.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_handle_type;
|
||||
#elif defined(ASIO_HAS_IOCP)
|
||||
typedef detail::win_iocp_serial_port_service::native_handle_type
|
||||
native_handle_type;
|
||||
#else
|
||||
typedef detail::reactive_serial_port_service::native_handle_type
|
||||
native_handle_type;
|
||||
#endif
|
||||
|
||||
/// A basic_basic_serial_port is always the lowest layer.
|
||||
typedef basic_serial_port lowest_layer_type;
|
||||
|
||||
/// Construct a basic_serial_port without opening it.
|
||||
/**
|
||||
* This constructor creates a serial port without opening it.
|
||||
*
|
||||
* @param ex The I/O executor that the serial port will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* serial port.
|
||||
*/
|
||||
explicit basic_serial_port(const executor_type& ex)
|
||||
: impl_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_serial_port without opening it.
|
||||
/**
|
||||
* This constructor creates a serial port without opening it.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the serial port will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the serial port.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_serial_port(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct and open a basic_serial_port.
|
||||
/**
|
||||
* This constructor creates and opens a serial port for the specified device
|
||||
* name.
|
||||
*
|
||||
* @param ex The I/O executor that the serial port will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* serial port.
|
||||
*
|
||||
* @param device The platform-specific device name for this serial
|
||||
* port.
|
||||
*/
|
||||
basic_serial_port(const executor_type& ex, const char* device)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||
asio::detail::throw_error(ec, "open");
|
||||
}
|
||||
|
||||
/// Construct and open a basic_serial_port.
|
||||
/**
|
||||
* This constructor creates and opens a serial port for the specified device
|
||||
* name.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the serial port will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the serial port.
|
||||
*
|
||||
* @param device The platform-specific device name for this serial
|
||||
* port.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_serial_port(ExecutionContext& context, const char* device,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||
asio::detail::throw_error(ec, "open");
|
||||
}
|
||||
|
||||
/// Construct and open a basic_serial_port.
|
||||
/**
|
||||
* This constructor creates and opens a serial port for the specified device
|
||||
* name.
|
||||
*
|
||||
* @param ex The I/O executor that the serial port will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* serial port.
|
||||
*
|
||||
* @param device The platform-specific device name for this serial
|
||||
* port.
|
||||
*/
|
||||
basic_serial_port(const executor_type& ex, const std::string& device)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||
asio::detail::throw_error(ec, "open");
|
||||
}
|
||||
|
||||
/// Construct and open a basic_serial_port.
|
||||
/**
|
||||
* This constructor creates and opens a serial port for the specified device
|
||||
* name.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the serial port will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the serial port.
|
||||
*
|
||||
* @param device The platform-specific device name for this serial
|
||||
* port.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_serial_port(ExecutionContext& context, const std::string& device,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||
asio::detail::throw_error(ec, "open");
|
||||
}
|
||||
|
||||
/// Construct a basic_serial_port on an existing native serial port.
|
||||
/**
|
||||
* This constructor creates a serial port object to hold an existing native
|
||||
* serial port.
|
||||
*
|
||||
* @param ex The I/O executor that the serial port will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* serial port.
|
||||
*
|
||||
* @param native_serial_port A native serial port.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_serial_port(const executor_type& ex,
|
||||
const native_handle_type& native_serial_port)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_serial_port, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
/// Construct a basic_serial_port on an existing native serial port.
|
||||
/**
|
||||
* This constructor creates a serial port object to hold an existing native
|
||||
* serial port.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the serial port will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the serial port.
|
||||
*
|
||||
* @param native_serial_port A native serial port.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_serial_port(ExecutionContext& context,
|
||||
const native_handle_type& native_serial_port,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_serial_port, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a basic_serial_port from another.
|
||||
/**
|
||||
* This constructor moves a serial port from one object to another.
|
||||
*
|
||||
* @param other The other basic_serial_port object from which the move will
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_serial_port(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_serial_port(basic_serial_port&& other)
|
||||
: impl_(std::move(other.impl_))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a basic_serial_port from another.
|
||||
/**
|
||||
* This assignment operator moves a serial port from one object to another.
|
||||
*
|
||||
* @param other The other basic_serial_port object from which the move will
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_serial_port(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_serial_port& operator=(basic_serial_port&& other)
|
||||
{
|
||||
impl_ = std::move(other.impl_);
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Destroys the serial port.
|
||||
/**
|
||||
* This function destroys the serial port, cancelling any outstanding
|
||||
* asynchronous wait operations associated with the serial port as if by
|
||||
* calling @c cancel.
|
||||
*/
|
||||
~basic_serial_port()
|
||||
{
|
||||
}
|
||||
|
||||
/// Get the executor associated with the object.
|
||||
executor_type get_executor() ASIO_NOEXCEPT
|
||||
{
|
||||
return impl_.get_executor();
|
||||
}
|
||||
|
||||
/// Get a reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a reference to the lowest layer in a stack of
|
||||
* layers. Since a basic_serial_port cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A reference to the lowest layer in the stack of layers. Ownership
|
||||
* is not transferred to the caller.
|
||||
*/
|
||||
lowest_layer_type& lowest_layer()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const reference to the lowest layer in a stack of
|
||||
* layers. Since a basic_serial_port cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A const reference to the lowest layer in the stack of layers.
|
||||
* Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Open the serial port using the specified device name.
|
||||
/**
|
||||
* This function opens the serial port for the specified device name.
|
||||
*
|
||||
* @param device The platform-specific device name.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void open(const std::string& device)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||
asio::detail::throw_error(ec, "open");
|
||||
}
|
||||
|
||||
/// Open the serial port using the specified device name.
|
||||
/**
|
||||
* This function opens the serial port using the given platform-specific
|
||||
* device name.
|
||||
*
|
||||
* @param device The platform-specific device name.
|
||||
*
|
||||
* @param ec Set the indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID open(const std::string& device,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().open(impl_.get_implementation(), device, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Assign an existing native serial port to the serial port.
|
||||
/*
|
||||
* This function opens the serial port to hold an existing native serial port.
|
||||
*
|
||||
* @param native_serial_port A native serial port.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void assign(const native_handle_type& native_serial_port)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_serial_port, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
/// Assign an existing native serial port to the serial port.
|
||||
/*
|
||||
* This function opens the serial port to hold an existing native serial port.
|
||||
*
|
||||
* @param native_serial_port A native serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_serial_port, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Determine whether the serial port is open.
|
||||
bool is_open() const
|
||||
{
|
||||
return impl_.get_service().is_open(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Close the serial port.
|
||||
/**
|
||||
* This function is used to close the serial port. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "close");
|
||||
}
|
||||
|
||||
/// Close the serial port.
|
||||
/**
|
||||
* This function is used to close the serial port. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Get the native serial port representation.
|
||||
/**
|
||||
* This function may be used to obtain the underlying representation of the
|
||||
* serial port. This is intended to allow access to native serial port
|
||||
* functionality that is not otherwise provided.
|
||||
*/
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
return impl_.get_service().native_handle(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the serial port.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void cancel()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "cancel");
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the serial port.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Send a break sequence to the serial port.
|
||||
/**
|
||||
* This function causes a break sequence of platform-specific duration to be
|
||||
* sent out the serial port.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void send_break()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().send_break(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "send_break");
|
||||
}
|
||||
|
||||
/// Send a break sequence to the serial port.
|
||||
/**
|
||||
* This function causes a break sequence of platform-specific duration to be
|
||||
* sent out the serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID send_break(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().send_break(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Set an option on the serial port.
|
||||
/**
|
||||
* This function is used to set an option on the serial port.
|
||||
*
|
||||
* @param option The option value to be set on the serial port.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @sa SettableSerialPortOption @n
|
||||
* asio::serial_port_base::baud_rate @n
|
||||
* asio::serial_port_base::flow_control @n
|
||||
* asio::serial_port_base::parity @n
|
||||
* asio::serial_port_base::stop_bits @n
|
||||
* asio::serial_port_base::character_size
|
||||
*/
|
||||
template <typename SettableSerialPortOption>
|
||||
void set_option(const SettableSerialPortOption& option)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().set_option(impl_.get_implementation(), option, ec);
|
||||
asio::detail::throw_error(ec, "set_option");
|
||||
}
|
||||
|
||||
/// Set an option on the serial port.
|
||||
/**
|
||||
* This function is used to set an option on the serial port.
|
||||
*
|
||||
* @param option The option value to be set on the serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @sa SettableSerialPortOption @n
|
||||
* asio::serial_port_base::baud_rate @n
|
||||
* asio::serial_port_base::flow_control @n
|
||||
* asio::serial_port_base::parity @n
|
||||
* asio::serial_port_base::stop_bits @n
|
||||
* asio::serial_port_base::character_size
|
||||
*/
|
||||
template <typename SettableSerialPortOption>
|
||||
ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().set_option(impl_.get_implementation(), option, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Get an option from the serial port.
|
||||
/**
|
||||
* This function is used to get the current value of an option on the serial
|
||||
* port.
|
||||
*
|
||||
* @param option The option value to be obtained from the serial port.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @sa GettableSerialPortOption @n
|
||||
* asio::serial_port_base::baud_rate @n
|
||||
* asio::serial_port_base::flow_control @n
|
||||
* asio::serial_port_base::parity @n
|
||||
* asio::serial_port_base::stop_bits @n
|
||||
* asio::serial_port_base::character_size
|
||||
*/
|
||||
template <typename GettableSerialPortOption>
|
||||
void get_option(GettableSerialPortOption& option)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().get_option(impl_.get_implementation(), option, ec);
|
||||
asio::detail::throw_error(ec, "get_option");
|
||||
}
|
||||
|
||||
/// Get an option from the serial port.
|
||||
/**
|
||||
* This function is used to get the current value of an option on the serial
|
||||
* port.
|
||||
*
|
||||
* @param option The option value to be obtained from the serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @sa GettableSerialPortOption @n
|
||||
* asio::serial_port_base::baud_rate @n
|
||||
* asio::serial_port_base::flow_control @n
|
||||
* asio::serial_port_base::parity @n
|
||||
* asio::serial_port_base::stop_bits @n
|
||||
* asio::serial_port_base::character_size
|
||||
*/
|
||||
template <typename GettableSerialPortOption>
|
||||
ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().get_option(impl_.get_implementation(), option, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Write some data to the serial port.
|
||||
/**
|
||||
* This function is used to write data to the serial port. The function call
|
||||
* will block until one or more bytes of the data has been written
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the serial port.
|
||||
*
|
||||
* @returns The number of bytes written.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. An error code of
|
||||
* asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* basic_serial_port.write_some(asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = impl_.get_service().write_some(
|
||||
impl_.get_implementation(), buffers, ec);
|
||||
asio::detail::throw_error(ec, "write_some");
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Write some data to the serial port.
|
||||
/**
|
||||
* This function is used to write data to the serial port. The function call
|
||||
* will block until one or more bytes of the data has been written
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the serial port.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return impl_.get_service().write_some(
|
||||
impl_.get_implementation(), buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write.
|
||||
/**
|
||||
* This function is used to asynchronously write data to the serial port.
|
||||
* The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the serial port.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the write operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes written.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The write operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref async_write function if you need to ensure that all
|
||||
* data is written before the asynchronous operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* basic_serial_port.async_write_some(
|
||||
* asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
||||
void (asio::error_code, std::size_t))
|
||||
async_write_some(const ConstBufferSequence& buffers,
|
||||
ASIO_MOVE_ARG(WriteHandler) handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a WriteHandler.
|
||||
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||
|
||||
async_completion<WriteHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
impl_.get_service().async_write_some(impl_.get_implementation(), buffers,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
/// Read some data from the serial port.
|
||||
/**
|
||||
* This function is used to read data from the serial port. The function
|
||||
* call will block until one or more bytes of data has been read successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. An error code of
|
||||
* asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* basic_serial_port.read_some(asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = impl_.get_service().read_some(
|
||||
impl_.get_implementation(), buffers, ec);
|
||||
asio::detail::throw_error(ec, "read_some");
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Read some data from the serial port.
|
||||
/**
|
||||
* This function is used to read data from the serial port. The function
|
||||
* call will block until one or more bytes of data has been read successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return impl_.get_service().read_some(
|
||||
impl_.get_implementation(), buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read.
|
||||
/**
|
||||
* This function is used to asynchronously read data from the serial port.
|
||||
* The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the read operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes read.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The read operation may not read all of the requested number of bytes.
|
||||
* Consider using the @ref async_read function if you need to ensure that the
|
||||
* requested amount of data is read before the asynchronous operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* basic_serial_port.async_read_some(
|
||||
* asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
||||
void (asio::error_code, std::size_t))
|
||||
async_read_some(const MutableBufferSequence& buffers,
|
||||
ASIO_MOVE_ARG(ReadHandler) handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a ReadHandler.
|
||||
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||
|
||||
async_completion<ReadHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
impl_.get_service().async_read_some(impl_.get_implementation(), buffers,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
basic_serial_port(const basic_serial_port&) ASIO_DELETED;
|
||||
basic_serial_port& operator=(const basic_serial_port&) ASIO_DELETED;
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_;
|
||||
#else
|
||||
detail::io_object_impl<detail::reactive_serial_port_service, Executor> impl_;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_SERIAL_PORT)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#endif // ASIO_BASIC_SERIAL_PORT_HPP
|
532
asio/include/asio/basic_signal_set.hpp
Normal file
532
asio/include/asio/basic_signal_set.hpp
Normal file
@ -0,0 +1,532 @@
|
||||
//
|
||||
// basic_signal_set.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_BASIC_SIGNAL_SET_HPP
|
||||
#define ASIO_BASIC_SIGNAL_SET_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#include "asio/async_result.hpp"
|
||||
#include "asio/detail/handler_type_requirements.hpp"
|
||||
#include "asio/detail/io_object_impl.hpp"
|
||||
#include "asio/detail/signal_set_service.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/type_traits.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/executor.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// Provides signal functionality.
|
||||
/**
|
||||
* The basic_signal_set class provides the ability to perform an asynchronous
|
||||
* wait for one or more signals to occur.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*
|
||||
* @par Example
|
||||
* Performing an asynchronous wait:
|
||||
* @code
|
||||
* void handler(
|
||||
* const asio::error_code& error,
|
||||
* int signal_number)
|
||||
* {
|
||||
* if (!error)
|
||||
* {
|
||||
* // A signal occurred.
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* // Construct a signal set registered for process termination.
|
||||
* asio::signal_set signals(my_context, SIGINT, SIGTERM);
|
||||
*
|
||||
* // Start an asynchronous wait for one of the signals to occur.
|
||||
* signals.async_wait(handler);
|
||||
* @endcode
|
||||
*
|
||||
* @par Queueing of signal notifications
|
||||
*
|
||||
* If a signal is registered with a signal_set, and the signal occurs when
|
||||
* there are no waiting handlers, then the signal notification is queued. The
|
||||
* next async_wait operation on that signal_set will dequeue the notification.
|
||||
* If multiple notifications are queued, subsequent async_wait operations
|
||||
* dequeue them one at a time. Signal notifications are dequeued in order of
|
||||
* ascending signal number.
|
||||
*
|
||||
* If a signal number is removed from a signal_set (using the @c remove or @c
|
||||
* erase member functions) then any queued notifications for that signal are
|
||||
* discarded.
|
||||
*
|
||||
* @par Multiple registration of signals
|
||||
*
|
||||
* The same signal number may be registered with different signal_set objects.
|
||||
* When the signal occurs, one handler is called for each signal_set object.
|
||||
*
|
||||
* Note that multiple registration only works for signals that are registered
|
||||
* using Asio. The application must not also register a signal handler using
|
||||
* functions such as @c signal() or @c sigaction().
|
||||
*
|
||||
* @par Signal masking on POSIX platforms
|
||||
*
|
||||
* POSIX allows signals to be blocked using functions such as @c sigprocmask()
|
||||
* and @c pthread_sigmask(). For signals to be delivered, programs must ensure
|
||||
* that any signals registered using signal_set objects are unblocked in at
|
||||
* least one thread.
|
||||
*/
|
||||
template <typename Executor = executor>
|
||||
class basic_signal_set
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// Construct a signal set without adding any signals.
|
||||
/**
|
||||
* This constructor creates a signal set without registering for any signals.
|
||||
*
|
||||
* @param ex The I/O executor that the signal set will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* signal set.
|
||||
*/
|
||||
explicit basic_signal_set(const executor_type& ex)
|
||||
: impl_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a signal set without adding any signals.
|
||||
/**
|
||||
* This constructor creates a signal set without registering for any signals.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the signal set will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the signal set.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_signal_set(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a signal set and add one signal.
|
||||
/**
|
||||
* This constructor creates a signal set and registers for one signal.
|
||||
*
|
||||
* @param ex The I/O executor that the signal set will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* signal set.
|
||||
*
|
||||
* @param signal_number_1 The signal number to be added.
|
||||
*
|
||||
* @note This constructor is equivalent to performing:
|
||||
* @code asio::signal_set signals(ex);
|
||||
* signals.add(signal_number_1); @endcode
|
||||
*/
|
||||
basic_signal_set(const executor_type& ex, int signal_number_1)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
}
|
||||
|
||||
/// Construct a signal set and add one signal.
|
||||
/**
|
||||
* This constructor creates a signal set and registers for one signal.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the signal set will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the signal set.
|
||||
*
|
||||
* @param signal_number_1 The signal number to be added.
|
||||
*
|
||||
* @note This constructor is equivalent to performing:
|
||||
* @code asio::signal_set signals(context);
|
||||
* signals.add(signal_number_1); @endcode
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_signal_set(ExecutionContext& context, int signal_number_1,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
}
|
||||
|
||||
/// Construct a signal set and add two signals.
|
||||
/**
|
||||
* This constructor creates a signal set and registers for two signals.
|
||||
*
|
||||
* @param ex The I/O executor that the signal set will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* signal set.
|
||||
*
|
||||
* @param signal_number_1 The first signal number to be added.
|
||||
*
|
||||
* @param signal_number_2 The second signal number to be added.
|
||||
*
|
||||
* @note This constructor is equivalent to performing:
|
||||
* @code asio::signal_set signals(ex);
|
||||
* signals.add(signal_number_1);
|
||||
* signals.add(signal_number_2); @endcode
|
||||
*/
|
||||
basic_signal_set(const executor_type& ex, int signal_number_1,
|
||||
int signal_number_2)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
}
|
||||
|
||||
/// Construct a signal set and add two signals.
|
||||
/**
|
||||
* This constructor creates a signal set and registers for two signals.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the signal set will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the signal set.
|
||||
*
|
||||
* @param signal_number_1 The first signal number to be added.
|
||||
*
|
||||
* @param signal_number_2 The second signal number to be added.
|
||||
*
|
||||
* @note This constructor is equivalent to performing:
|
||||
* @code asio::signal_set signals(context);
|
||||
* signals.add(signal_number_1);
|
||||
* signals.add(signal_number_2); @endcode
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_signal_set(ExecutionContext& context, int signal_number_1,
|
||||
int signal_number_2,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
}
|
||||
|
||||
/// Construct a signal set and add three signals.
|
||||
/**
|
||||
* This constructor creates a signal set and registers for three signals.
|
||||
*
|
||||
* @param ex The I/O executor that the signal set will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* signal set.
|
||||
*
|
||||
* @param signal_number_1 The first signal number to be added.
|
||||
*
|
||||
* @param signal_number_2 The second signal number to be added.
|
||||
*
|
||||
* @param signal_number_3 The third signal number to be added.
|
||||
*
|
||||
* @note This constructor is equivalent to performing:
|
||||
* @code asio::signal_set signals(ex);
|
||||
* signals.add(signal_number_1);
|
||||
* signals.add(signal_number_2);
|
||||
* signals.add(signal_number_3); @endcode
|
||||
*/
|
||||
basic_signal_set(const executor_type& ex, int signal_number_1,
|
||||
int signal_number_2, int signal_number_3)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_3, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
}
|
||||
|
||||
/// Construct a signal set and add three signals.
|
||||
/**
|
||||
* This constructor creates a signal set and registers for three signals.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the signal set will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the signal set.
|
||||
*
|
||||
* @param signal_number_1 The first signal number to be added.
|
||||
*
|
||||
* @param signal_number_2 The second signal number to be added.
|
||||
*
|
||||
* @param signal_number_3 The third signal number to be added.
|
||||
*
|
||||
* @note This constructor is equivalent to performing:
|
||||
* @code asio::signal_set signals(context);
|
||||
* signals.add(signal_number_1);
|
||||
* signals.add(signal_number_2);
|
||||
* signals.add(signal_number_3); @endcode
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_signal_set(ExecutionContext& context, int signal_number_1,
|
||||
int signal_number_2, int signal_number_3,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_2, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number_3, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
}
|
||||
|
||||
/// Destroys the signal set.
|
||||
/**
|
||||
* This function destroys the signal set, cancelling any outstanding
|
||||
* asynchronous wait operations associated with the signal set as if by
|
||||
* calling @c cancel.
|
||||
*/
|
||||
~basic_signal_set()
|
||||
{
|
||||
}
|
||||
|
||||
/// Get the executor associated with the object.
|
||||
executor_type get_executor() ASIO_NOEXCEPT
|
||||
{
|
||||
return impl_.get_executor();
|
||||
}
|
||||
|
||||
/// Add a signal to a signal_set.
|
||||
/**
|
||||
* This function adds the specified signal to the set. It has no effect if the
|
||||
* signal is already in the set.
|
||||
*
|
||||
* @param signal_number The signal to be added to the set.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void add(int signal_number)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number, ec);
|
||||
asio::detail::throw_error(ec, "add");
|
||||
}
|
||||
|
||||
/// Add a signal to a signal_set.
|
||||
/**
|
||||
* This function adds the specified signal to the set. It has no effect if the
|
||||
* signal is already in the set.
|
||||
*
|
||||
* @param signal_number The signal to be added to the set.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID add(int signal_number,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().add(impl_.get_implementation(), signal_number, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Remove a signal from a signal_set.
|
||||
/**
|
||||
* This function removes the specified signal from the set. It has no effect
|
||||
* if the signal is not in the set.
|
||||
*
|
||||
* @param signal_number The signal to be removed from the set.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @note Removes any notifications that have been queued for the specified
|
||||
* signal number.
|
||||
*/
|
||||
void remove(int signal_number)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().remove(impl_.get_implementation(), signal_number, ec);
|
||||
asio::detail::throw_error(ec, "remove");
|
||||
}
|
||||
|
||||
/// Remove a signal from a signal_set.
|
||||
/**
|
||||
* This function removes the specified signal from the set. It has no effect
|
||||
* if the signal is not in the set.
|
||||
*
|
||||
* @param signal_number The signal to be removed from the set.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @note Removes any notifications that have been queued for the specified
|
||||
* signal number.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID remove(int signal_number,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().remove(impl_.get_implementation(), signal_number, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Remove all signals from a signal_set.
|
||||
/**
|
||||
* This function removes all signals from the set. It has no effect if the set
|
||||
* is already empty.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @note Removes all queued notifications.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().clear(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "clear");
|
||||
}
|
||||
|
||||
/// Remove all signals from a signal_set.
|
||||
/**
|
||||
* This function removes all signals from the set. It has no effect if the set
|
||||
* is already empty.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @note Removes all queued notifications.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID clear(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().clear(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Cancel all operations associated with the signal set.
|
||||
/**
|
||||
* This function forces the completion of any pending asynchronous wait
|
||||
* operations against the signal set. The handler for each cancelled
|
||||
* operation will be invoked with the asio::error::operation_aborted
|
||||
* error code.
|
||||
*
|
||||
* Cancellation does not alter the set of registered signals.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @note If a registered signal occurred before cancel() is called, then the
|
||||
* handlers for asynchronous wait operations will:
|
||||
*
|
||||
* @li have already been invoked; or
|
||||
*
|
||||
* @li have been queued for invocation in the near future.
|
||||
*
|
||||
* These handlers can no longer be cancelled, and therefore are passed an
|
||||
* error code that indicates the successful completion of the wait operation.
|
||||
*/
|
||||
void cancel()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "cancel");
|
||||
}
|
||||
|
||||
/// Cancel all operations associated with the signal set.
|
||||
/**
|
||||
* This function forces the completion of any pending asynchronous wait
|
||||
* operations against the signal set. The handler for each cancelled
|
||||
* operation will be invoked with the asio::error::operation_aborted
|
||||
* error code.
|
||||
*
|
||||
* Cancellation does not alter the set of registered signals.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @note If a registered signal occurred before cancel() is called, then the
|
||||
* handlers for asynchronous wait operations will:
|
||||
*
|
||||
* @li have already been invoked; or
|
||||
*
|
||||
* @li have been queued for invocation in the near future.
|
||||
*
|
||||
* These handlers can no longer be cancelled, and therefore are passed an
|
||||
* error code that indicates the successful completion of the wait operation.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous operation to wait for a signal to be delivered.
|
||||
/**
|
||||
* This function may be used to initiate an asynchronous wait against the
|
||||
* signal set. It always returns immediately.
|
||||
*
|
||||
* For each call to async_wait(), the supplied handler will be called exactly
|
||||
* once. The handler will be called when:
|
||||
*
|
||||
* @li One of the registered signals in the signal set occurs; or
|
||||
*
|
||||
* @li The signal set was cancelled, in which case the handler is passed the
|
||||
* error code asio::error::operation_aborted.
|
||||
*
|
||||
* @param handler The handler to be called when the signal occurs. Copies
|
||||
* will be made of the handler as required. The function signature of the
|
||||
* handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* int signal_number // Indicates which signal occurred.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*/
|
||||
template <typename SignalHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(SignalHandler,
|
||||
void (asio::error_code, int))
|
||||
async_wait(ASIO_MOVE_ARG(SignalHandler) handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a SignalHandler.
|
||||
ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check;
|
||||
|
||||
async_completion<SignalHandler,
|
||||
void (asio::error_code, int)> init(handler);
|
||||
|
||||
impl_.get_service().async_wait(impl_.get_implementation(),
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
basic_signal_set(const basic_signal_set&) ASIO_DELETED;
|
||||
basic_signal_set& operator=(const basic_signal_set&) ASIO_DELETED;
|
||||
|
||||
detail::io_object_impl<detail::signal_set_service, Executor> impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#endif // ASIO_BASIC_SIGNAL_SET_HPP
|
@ -22,8 +22,11 @@
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/type_traits.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/executor.hpp"
|
||||
#include "asio/post.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
|
||||
#if defined(ASIO_WINDOWS_RUNTIME)
|
||||
# include "asio/detail/null_socket_service.hpp"
|
||||
#elif defined(ASIO_HAS_IOCP)
|
||||
@ -40,6 +43,15 @@
|
||||
|
||||
namespace asio {
|
||||
|
||||
#if !defined(ASIO_BASIC_SOCKET_FWD_DECL)
|
||||
#define ASIO_BASIC_SOCKET_FWD_DECL
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename Protocol, typename Executor = executor>
|
||||
class basic_socket;
|
||||
|
||||
#endif // !defined(ASIO_BASIC_SOCKET_FWD_DECL)
|
||||
|
||||
/// Provides socket functionality.
|
||||
/**
|
||||
* The basic_socket class template provides functionality that is common to both
|
||||
@ -49,13 +61,21 @@ namespace asio {
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename Protocol>
|
||||
template <typename Protocol, typename Executor>
|
||||
class basic_socket
|
||||
: 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)
|
||||
@ -79,18 +99,35 @@ public:
|
||||
|
||||
#if !defined(ASIO_NO_EXTENSIONS)
|
||||
/// A basic_socket is always the lowest layer.
|
||||
typedef basic_socket<Protocol> lowest_layer_type;
|
||||
typedef basic_socket<Protocol, Executor> lowest_layer_type;
|
||||
#endif // !defined(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(asio::io_context& io_context)
|
||||
: impl_(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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -98,16 +135,39 @@ 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 asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_socket(asio::io_context& io_context,
|
||||
const protocol_type& protocol)
|
||||
: impl_(io_context)
|
||||
basic_socket(const executor_type& ex, const protocol_type& protocol)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), protocol, ec);
|
||||
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 asio::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)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().open(impl_.get_implementation(), protocol, ec);
|
||||
@ -121,7 +181,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
|
||||
@ -129,9 +189,39 @@ public:
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_socket(asio::io_context& io_context,
|
||||
const endpoint_type& endpoint)
|
||||
: impl_(io_context)
|
||||
basic_socket(const executor_type& ex, const endpoint_type& endpoint)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
const protocol_type protocol = endpoint.protocol();
|
||||
impl_.get_service().open(impl_.get_implementation(), protocol, ec);
|
||||
asio::detail::throw_error(ec, "open");
|
||||
impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
|
||||
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 asio::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)
|
||||
{
|
||||
asio::error_code ec;
|
||||
const protocol_type protocol = endpoint.protocol();
|
||||
@ -145,7 +235,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.
|
||||
@ -154,9 +244,37 @@ public:
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_socket(asio::io_context& io_context,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket)
|
||||
: impl_(io_context)
|
||||
basic_socket(const executor_type& ex, const protocol_type& protocol,
|
||||
const native_handle_type& native_socket)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
protocol, native_socket, ec);
|
||||
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 asio::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)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
@ -173,7 +291,7 @@ 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)
|
||||
: impl_(std::move(other.impl_))
|
||||
@ -188,7 +306,7 @@ 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)
|
||||
{
|
||||
@ -197,7 +315,7 @@ public:
|
||||
}
|
||||
|
||||
// All sockets have access to each other's implementations.
|
||||
template <typename Protocol1>
|
||||
template <typename Protocol1, typename Executor1>
|
||||
friend class basic_socket;
|
||||
|
||||
/// Move-construct a basic_socket from a socket of another protocol type.
|
||||
@ -208,11 +326,14 @@ 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>
|
||||
basic_socket(basic_socket<Protocol1>&& other,
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
|
||||
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_))
|
||||
{
|
||||
}
|
||||
@ -225,11 +346,14 @@ 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>
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value,
|
||||
basic_socket>::type& operator=(basic_socket<Protocol1>&& 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));
|
||||
impl_ = std::move(tmp.impl_);
|
||||
@ -283,7 +407,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* socket.open(asio::ip::tcp::v4());
|
||||
* @endcode
|
||||
*/
|
||||
@ -304,7 +428,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* asio::error_code ec;
|
||||
* socket.open(asio::ip::tcp::v4(), ec);
|
||||
* if (ec)
|
||||
@ -393,7 +517,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::error_code ec;
|
||||
* socket.close(ec);
|
||||
@ -649,7 +773,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* socket.open(asio::ip::tcp::v4());
|
||||
* socket.bind(asio::ip::tcp::endpoint(
|
||||
* asio::ip::tcp::v4(), 12345));
|
||||
@ -674,7 +798,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* socket.open(asio::ip::tcp::v4());
|
||||
* asio::error_code ec;
|
||||
* socket.bind(asio::ip::tcp::endpoint(
|
||||
@ -709,7 +833,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* asio::ip::tcp::endpoint endpoint(
|
||||
* asio::ip::address::from_string("1.2.3.4"), 12345);
|
||||
* socket.connect(endpoint);
|
||||
@ -745,7 +869,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* asio::ip::tcp::endpoint endpoint(
|
||||
* asio::ip::address::from_string("1.2.3.4"), 12345);
|
||||
* asio::error_code ec;
|
||||
@ -792,9 +916,9 @@ public:
|
||||
* const asio::error_code& error // Result of operation
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
@ -808,7 +932,7 @@ public:
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* asio::ip::tcp::endpoint endpoint(
|
||||
* asio::ip::address::from_string("1.2.3.4"), 12345);
|
||||
* socket.async_connect(endpoint, connect_handler);
|
||||
@ -847,8 +971,8 @@ public:
|
||||
async_completion<ConnectHandler,
|
||||
void (asio::error_code)> init(handler);
|
||||
|
||||
impl_.get_service().async_connect(
|
||||
impl_.get_implementation(), peer_endpoint, init.completion_handler);
|
||||
impl_.get_service().async_connect(impl_.get_implementation(), peer_endpoint,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -881,7 +1005,7 @@ public:
|
||||
* @par Example
|
||||
* Setting the IPPROTO_TCP/TCP_NODELAY option:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::no_delay option(true);
|
||||
* socket.set_option(option);
|
||||
@ -923,7 +1047,7 @@ public:
|
||||
* @par Example
|
||||
* Setting the IPPROTO_TCP/TCP_NODELAY option:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::no_delay option(true);
|
||||
* asio::error_code ec;
|
||||
@ -970,7 +1094,7 @@ public:
|
||||
* @par Example
|
||||
* Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::socket::keep_alive option;
|
||||
* socket.get_option(option);
|
||||
@ -1013,7 +1137,7 @@ public:
|
||||
* @par Example
|
||||
* Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::socket::keep_alive option;
|
||||
* asio::error_code ec;
|
||||
@ -1048,7 +1172,7 @@ public:
|
||||
* @par Example
|
||||
* Getting the number of bytes ready to read:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::socket::bytes_readable command;
|
||||
* socket.io_control(command);
|
||||
@ -1078,7 +1202,7 @@ public:
|
||||
* @par Example
|
||||
* Getting the number of bytes ready to read:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::socket::bytes_readable command;
|
||||
* asio::error_code ec;
|
||||
@ -1439,7 +1563,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
|
||||
* @endcode
|
||||
@ -1464,7 +1588,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::error_code ec;
|
||||
* asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
|
||||
@ -1489,7 +1613,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
|
||||
* @endcode
|
||||
@ -1514,7 +1638,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::error_code ec;
|
||||
* asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
|
||||
@ -1541,7 +1665,7 @@ public:
|
||||
* @par Example
|
||||
* Shutting down the send side of the socket:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* socket.shutdown(asio::ip::tcp::socket::shutdown_send);
|
||||
* @endcode
|
||||
@ -1565,7 +1689,7 @@ public:
|
||||
* @par Example
|
||||
* Shutting down the send side of the socket:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::error_code ec;
|
||||
* socket.shutdown(asio::ip::tcp::socket::shutdown_send, ec);
|
||||
@ -1593,7 +1717,7 @@ public:
|
||||
* @par Example
|
||||
* Waiting for a socket to become readable.
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* socket.wait(asio::ip::tcp::socket::wait_read);
|
||||
* @endcode
|
||||
@ -1618,7 +1742,7 @@ public:
|
||||
* @par Example
|
||||
* Waiting for a socket to become readable.
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::error_code ec;
|
||||
* socket.wait(asio::ip::tcp::socket::wait_read, ec);
|
||||
@ -1645,9 +1769,9 @@ public:
|
||||
* const asio::error_code& error // Result of operation
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
@ -1661,7 +1785,7 @@ public:
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* socket.async_wait(asio::ip::tcp::socket::wait_read, wait_handler);
|
||||
* @endcode
|
||||
@ -1678,8 +1802,8 @@ public:
|
||||
async_completion<WaitHandler,
|
||||
void (asio::error_code)> init(handler);
|
||||
|
||||
impl_.get_service().async_wait(impl_.get_implementation(),
|
||||
w, init.completion_handler);
|
||||
impl_.get_service().async_wait(impl_.get_implementation(), w,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -1695,11 +1819,14 @@ protected:
|
||||
}
|
||||
|
||||
#if defined(ASIO_WINDOWS_RUNTIME)
|
||||
detail::io_object_impl<detail::null_socket_service<Protocol> > impl_;
|
||||
detail::io_object_impl<
|
||||
detail::null_socket_service<Protocol>, Executor> impl_;
|
||||
#elif defined(ASIO_HAS_IOCP)
|
||||
detail::io_object_impl<detail::win_iocp_socket_service<Protocol> > impl_;
|
||||
detail::io_object_impl<
|
||||
detail::win_iocp_socket_service<Protocol>, Executor> impl_;
|
||||
#else
|
||||
detail::io_object_impl<detail::reactive_socket_service<Protocol> > impl_;
|
||||
detail::io_object_impl<
|
||||
detail::reactive_socket_service<Protocol>, Executor> impl_;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -47,7 +47,7 @@
|
||||
// {
|
||||
// init_buffers();
|
||||
// typedef typename Protocol::resolver resolver_type;
|
||||
// resolver_type resolver(socket().get_executor().context());
|
||||
// resolver_type resolver(socket().get_executor());
|
||||
// connect_to_endpoints(
|
||||
// resolver.resolve(x1, ..., xn, ec_));
|
||||
// return !ec_ ? this : 0;
|
||||
@ -60,7 +60,7 @@
|
||||
{ \
|
||||
init_buffers(); \
|
||||
typedef typename Protocol::resolver resolver_type; \
|
||||
resolver_type resolver(socket().get_executor().context()); \
|
||||
resolver_type resolver(socket().get_executor()); \
|
||||
connect_to_endpoints( \
|
||||
resolver.resolve(ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \
|
||||
return !ec_ ? this : 0; \
|
||||
@ -283,7 +283,7 @@ public:
|
||||
{
|
||||
init_buffers();
|
||||
typedef typename Protocol::resolver resolver_type;
|
||||
resolver_type resolver(socket().get_executor().context());
|
||||
resolver_type resolver(socket().get_executor());
|
||||
connect_to_endpoints(resolver.resolve(x..., ec_));
|
||||
return !ec_ ? this : 0;
|
||||
}
|
||||
|
@ -27,6 +27,15 @@
|
||||
|
||||
namespace asio {
|
||||
|
||||
#if !defined(ASIO_BASIC_STREAM_SOCKET_FWD_DECL)
|
||||
#define ASIO_BASIC_STREAM_SOCKET_FWD_DECL
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename Protocol, typename Executor = executor>
|
||||
class basic_stream_socket;
|
||||
|
||||
#endif // !defined(ASIO_BASIC_STREAM_SOCKET_FWD_DECL)
|
||||
|
||||
/// Provides stream-oriented socket functionality.
|
||||
/**
|
||||
* The basic_stream_socket class template provides asynchronous and blocking
|
||||
@ -39,17 +48,28 @@ namespace asio {
|
||||
* @par Concepts:
|
||||
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
||||
*/
|
||||
template <typename Protocol>
|
||||
template <typename Protocol, typename Executor>
|
||||
class basic_stream_socket
|
||||
: public basic_socket<Protocol>
|
||||
: public basic_socket<Protocol, Executor>
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// Rebinds the socket type to another executor.
|
||||
template <typename Executor1>
|
||||
struct rebind_executor
|
||||
{
|
||||
/// The socket type when rebound to the specified executor.
|
||||
typedef basic_stream_socket<Protocol, Executor1> other;
|
||||
};
|
||||
|
||||
/// The native representation of a socket.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_handle_type;
|
||||
#else
|
||||
typedef typename basic_socket<
|
||||
Protocol>::native_handle_type native_handle_type;
|
||||
typedef typename basic_socket<Protocol,
|
||||
Executor>::native_handle_type native_handle_type;
|
||||
#endif
|
||||
|
||||
/// The protocol type.
|
||||
@ -64,11 +84,30 @@ public:
|
||||
* needs to be opened and then connected or accepted before data can be sent
|
||||
* or received on it.
|
||||
*
|
||||
* @param io_context The io_context object that the stream socket will use to
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*/
|
||||
explicit basic_stream_socket(asio::io_context& io_context)
|
||||
: basic_socket<Protocol>(io_context)
|
||||
explicit basic_stream_socket(const executor_type& ex)
|
||||
: basic_socket<Protocol, Executor>(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_stream_socket without opening it.
|
||||
/**
|
||||
* This constructor creates a stream socket without opening it. The socket
|
||||
* needs to be opened and then connected or accepted before data can be sent
|
||||
* or received on it.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_stream_socket(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -77,16 +116,37 @@ public:
|
||||
* This constructor creates and opens a stream socket. The socket needs to be
|
||||
* connected or accepted before data can be sent or received on it.
|
||||
*
|
||||
* @param io_context The io_context object that the stream socket will use to
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_stream_socket(asio::io_context& io_context,
|
||||
const protocol_type& protocol)
|
||||
: basic_socket<Protocol>(io_context, protocol)
|
||||
basic_stream_socket(const executor_type& ex, const protocol_type& protocol)
|
||||
: basic_socket<Protocol, Executor>(ex, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct and open a basic_stream_socket.
|
||||
/**
|
||||
* This constructor creates and opens a stream socket. The socket needs to be
|
||||
* connected or accepted before data can be sent or received on it.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_stream_socket(ExecutionContext& context, const protocol_type& protocol,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol)
|
||||
{
|
||||
}
|
||||
|
||||
@ -97,7 +157,7 @@ public:
|
||||
* to the specified endpoint on the local machine. The protocol used is the
|
||||
* protocol associated with the given endpoint.
|
||||
*
|
||||
* @param io_context The io_context object that the stream socket will use to
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the stream
|
||||
@ -105,9 +165,33 @@ public:
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_stream_socket(asio::io_context& io_context,
|
||||
const endpoint_type& endpoint)
|
||||
: basic_socket<Protocol>(io_context, endpoint)
|
||||
basic_stream_socket(const executor_type& ex, const endpoint_type& endpoint)
|
||||
: basic_socket<Protocol, Executor>(ex, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_stream_socket, opening it and binding it to the given
|
||||
/// local endpoint.
|
||||
/**
|
||||
* This constructor creates a stream socket and automatically opens it bound
|
||||
* to the specified endpoint on the local machine. The protocol used is the
|
||||
* protocol associated with the given endpoint.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param endpoint An endpoint on the local machine to which the stream
|
||||
* socket will be bound.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
@ -116,7 +200,7 @@ public:
|
||||
* This constructor creates a stream socket object to hold an existing native
|
||||
* socket.
|
||||
*
|
||||
* @param io_context The io_context object that the stream socket will use to
|
||||
* @param ex The I/O executor that the socket will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
@ -125,9 +209,34 @@ public:
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_stream_socket(asio::io_context& io_context,
|
||||
basic_stream_socket(const executor_type& ex,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket)
|
||||
: basic_socket<Protocol>(io_context, protocol, native_socket)
|
||||
: basic_socket<Protocol, Executor>(ex, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a basic_stream_socket on an existing native socket.
|
||||
/**
|
||||
* This constructor creates a stream socket object to hold an existing native
|
||||
* socket.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the socket will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the socket.
|
||||
*
|
||||
* @param protocol An object specifying protocol parameters to be used.
|
||||
*
|
||||
* @param native_socket The new underlying socket implementation.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_stream_socket(ExecutionContext& context,
|
||||
const protocol_type& protocol, const native_handle_type& native_socket,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(context, protocol, native_socket)
|
||||
{
|
||||
}
|
||||
|
||||
@ -140,10 +249,11 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_stream_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_stream_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_stream_socket(basic_stream_socket&& other)
|
||||
: basic_socket<Protocol>(std::move(other))
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
@ -155,11 +265,12 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_stream_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_stream_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_stream_socket& operator=(basic_stream_socket&& other)
|
||||
{
|
||||
basic_socket<Protocol>::operator=(std::move(other));
|
||||
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -172,12 +283,16 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_stream_socket(io_context&) constructor.
|
||||
* constructed using the @c ,asic_stream_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1>
|
||||
basic_stream_socket(basic_stream_socket<Protocol1>&& other,
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
|
||||
: basic_socket<Protocol>(std::move(other))
|
||||
template <typename Protocol1, typename Executor1>
|
||||
basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other,
|
||||
typename enable_if<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value
|
||||
>::type* = 0)
|
||||
: basic_socket<Protocol, Executor>(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
@ -189,14 +304,17 @@ public:
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_stream_socket(io_context&) constructor.
|
||||
* constructed using the @c basic_stream_socket(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
template <typename Protocol1>
|
||||
typename enable_if<is_convertible<Protocol1, Protocol>::value,
|
||||
basic_stream_socket>::type& operator=(
|
||||
basic_stream_socket<Protocol1>&& other)
|
||||
template <typename Protocol1, typename Executor1>
|
||||
typename enable_if<
|
||||
is_convertible<Protocol1, Protocol>::value
|
||||
&& is_convertible<Executor1, Executor>::value,
|
||||
basic_stream_socket&
|
||||
>::type operator=(basic_stream_socket<Protocol1, Executor1>&& other)
|
||||
{
|
||||
basic_socket<Protocol>::operator=(std::move(other));
|
||||
basic_socket<Protocol, Executor>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
@ -327,9 +445,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The send operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref async_write function if you need to ensure that all
|
||||
@ -357,9 +475,9 @@ public:
|
||||
async_completion<WriteHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send(
|
||||
this->impl_.get_implementation(), buffers, 0,
|
||||
init.completion_handler);
|
||||
this->impl_.get_service().async_send(this->impl_.get_implementation(),
|
||||
buffers, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -384,9 +502,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes sent.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The send operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref async_write function if you need to ensure that all
|
||||
@ -415,9 +533,9 @@ public:
|
||||
async_completion<WriteHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send(
|
||||
this->impl_.get_implementation(), buffers, flags,
|
||||
init.completion_handler);
|
||||
this->impl_.get_service().async_send(this->impl_.get_implementation(),
|
||||
buffers, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -545,9 +663,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The receive operation may not receive all of the requested number of
|
||||
* bytes. Consider using the @ref async_read function if you need to ensure
|
||||
@ -578,7 +696,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_receive(this->impl_.get_implementation(),
|
||||
buffers, 0, init.completion_handler);
|
||||
buffers, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -603,9 +722,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes received.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The receive operation may not receive all of the requested number of
|
||||
* bytes. Consider using the @ref async_read function if you need to ensure
|
||||
@ -637,7 +756,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_receive(this->impl_.get_implementation(),
|
||||
buffers, flags, init.completion_handler);
|
||||
buffers, flags, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -721,9 +841,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes written.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The write operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref async_write function if you need to ensure that all
|
||||
@ -752,7 +872,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_send(this->impl_.get_implementation(),
|
||||
buffers, 0, init.completion_handler);
|
||||
buffers, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -838,9 +959,9 @@ public:
|
||||
* std::size_t bytes_transferred // Number of bytes read.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The read operation may not read all of the requested number of bytes.
|
||||
* Consider using the @ref async_read function if you need to ensure that the
|
||||
@ -870,7 +991,8 @@ public:
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_receive(this->impl_.get_implementation(),
|
||||
buffers, 0, init.completion_handler);
|
||||
buffers, 0, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "asio/detail/io_object_impl.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/executor.hpp"
|
||||
#include "asio/wait_traits.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
@ -38,7 +39,8 @@ namespace asio {
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename Clock,
|
||||
typename WaitTraits = asio::wait_traits<Clock> >
|
||||
typename WaitTraits = asio::wait_traits<Clock>,
|
||||
typename Executor = executor>
|
||||
class basic_waitable_timer;
|
||||
|
||||
#endif // !defined(ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
|
||||
@ -66,7 +68,7 @@ class basic_waitable_timer;
|
||||
* Performing a blocking wait (C++11):
|
||||
* @code
|
||||
* // Construct a timer without setting an expiry time.
|
||||
* asio::steady_timer timer(io_context);
|
||||
* asio::steady_timer timer(my_context);
|
||||
*
|
||||
* // Set an expiry time relative to now.
|
||||
* timer.expires_after(std::chrono::seconds(5));
|
||||
@ -89,7 +91,7 @@ class basic_waitable_timer;
|
||||
* ...
|
||||
*
|
||||
* // Construct a timer with an absolute expiry time.
|
||||
* asio::steady_timer timer(io_context,
|
||||
* asio::steady_timer timer(my_context,
|
||||
* std::chrono::steady_clock::now() + std::chrono::seconds(60));
|
||||
*
|
||||
* // Start an asynchronous wait.
|
||||
@ -135,12 +137,12 @@ class basic_waitable_timer;
|
||||
* @li If a wait handler is cancelled, the asio::error_code passed to
|
||||
* it contains the value asio::error::operation_aborted.
|
||||
*/
|
||||
template <typename Clock, typename WaitTraits>
|
||||
template <typename Clock, typename WaitTraits, typename Executor>
|
||||
class basic_waitable_timer
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef io_context::executor_type executor_type;
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// The clock type.
|
||||
typedef Clock clock_type;
|
||||
@ -160,11 +162,30 @@ public:
|
||||
* expires_at() or expires_after() functions must be called to set an expiry
|
||||
* time before the timer can be waited on.
|
||||
*
|
||||
* @param io_context The io_context object that the timer will use to dispatch
|
||||
* handlers for any asynchronous operations performed on the timer.
|
||||
* @param ex The I/O executor that the timer will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||
*/
|
||||
explicit basic_waitable_timer(asio::io_context& io_context)
|
||||
: impl_(io_context)
|
||||
explicit basic_waitable_timer(const executor_type& ex)
|
||||
: impl_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
/**
|
||||
* This constructor creates a timer without setting an expiry time. The
|
||||
* expires_at() or expires_after() functions must be called to set an expiry
|
||||
* time before the timer can be waited on.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the timer.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_waitable_timer(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -172,15 +193,38 @@ public:
|
||||
/**
|
||||
* This constructor creates a timer and sets the expiry time.
|
||||
*
|
||||
* @param io_context The io_context object that the timer will use to dispatch
|
||||
* handlers for any asynchronous operations performed on the timer.
|
||||
* @param ex The I/O executor object that the timer will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer, expressed
|
||||
* as an absolute time.
|
||||
*/
|
||||
basic_waitable_timer(asio::io_context& io_context,
|
||||
const time_point& expiry_time)
|
||||
: impl_(io_context)
|
||||
basic_waitable_timer(const executor_type& ex, const time_point& expiry_time)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
|
||||
asio::detail::throw_error(ec, "expires_at");
|
||||
}
|
||||
|
||||
/// Constructor to set a particular expiry time as an absolute time.
|
||||
/**
|
||||
* This constructor creates a timer and sets the expiry time.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the timer.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer, expressed
|
||||
* as an absolute time.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_waitable_timer(ExecutionContext& context,
|
||||
const time_point& expiry_time,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);
|
||||
@ -191,15 +235,39 @@ public:
|
||||
/**
|
||||
* This constructor creates a timer and sets the expiry time.
|
||||
*
|
||||
* @param io_context The io_context object that the timer will use to dispatch
|
||||
* handlers for any asynchronous operations performed on the timer.
|
||||
* @param ex The I/O executor that the timer will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the timer.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer, relative to
|
||||
* now.
|
||||
*/
|
||||
basic_waitable_timer(asio::io_context& io_context,
|
||||
const duration& expiry_time)
|
||||
: impl_(io_context)
|
||||
basic_waitable_timer(const executor_type& ex, const duration& expiry_time)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().expires_after(
|
||||
impl_.get_implementation(), expiry_time, ec);
|
||||
asio::detail::throw_error(ec, "expires_after");
|
||||
}
|
||||
|
||||
/// Constructor to set a particular expiry time relative to now.
|
||||
/**
|
||||
* This constructor creates a timer and sets the expiry time.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the timer will use, by default, to dispatch handlers for any asynchronous
|
||||
* operations performed on the timer.
|
||||
*
|
||||
* @param expiry_time The expiry time to be used for the timer, relative to
|
||||
* now.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_waitable_timer(ExecutionContext& context,
|
||||
const duration& expiry_time,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().expires_after(
|
||||
@ -216,7 +284,8 @@ public:
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_waitable_timer(io_context&) constructor.
|
||||
* constructed using the @c basic_waitable_timer(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_waitable_timer(basic_waitable_timer&& other)
|
||||
: impl_(std::move(other.impl_))
|
||||
@ -232,7 +301,8 @@ public:
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_waitable_timer(io_context&) constructor.
|
||||
* constructed using the @c basic_waitable_timer(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_waitable_timer& operator=(basic_waitable_timer&& other)
|
||||
{
|
||||
@ -616,9 +686,9 @@ public:
|
||||
* const asio::error_code& error // Result of operation.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*/
|
||||
template <typename WaitHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WaitHandler,
|
||||
@ -633,7 +703,7 @@ public:
|
||||
void (asio::error_code)> init(handler);
|
||||
|
||||
impl_.get_service().async_wait(impl_.get_implementation(),
|
||||
init.completion_handler);
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -646,7 +716,8 @@ private:
|
||||
|
||||
detail::io_object_impl<
|
||||
detail::deadline_timer_service<
|
||||
detail::chrono_time_traits<Clock, WaitTraits> > > impl_;
|
||||
detail::chrono_time_traits<Clock, WaitTraits> >,
|
||||
executor_type > impl_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
@ -82,13 +82,13 @@ struct is_endpoint_sequence
|
||||
* Otherwise, contains the error from the last connection attempt.
|
||||
*
|
||||
* @par Example
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* asio::connect(s, r.resolve(q)); @endcode
|
||||
*/
|
||||
template <typename Protocol, typename EndpointSequence>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type* = 0);
|
||||
@ -113,9 +113,9 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
* default-constructed endpoint.
|
||||
*
|
||||
* @par Example
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* asio::error_code ec;
|
||||
* asio::connect(s, r.resolve(q), ec);
|
||||
* if (ec)
|
||||
@ -123,8 +123,8 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
* // An error occurred.
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Protocol, typename EndpointSequence>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints, asio::error_code& ec,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type* = 0);
|
||||
@ -154,8 +154,8 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
* Iterator represents the end of the sequence. This is a valid assumption for
|
||||
* iterator types such as @c asio::ip::tcp::resolver::iterator.
|
||||
*/
|
||||
template <typename Protocol, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
template <typename Protocol, typename Executor, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
|
||||
|
||||
/// (Deprecated: Use range overload.) Establishes a socket connection by trying
|
||||
@ -182,8 +182,8 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* Iterator represents the end of the sequence. This is a valid assumption for
|
||||
* iterator types such as @c asio::ip::tcp::resolver::iterator.
|
||||
*/
|
||||
template <typename Protocol, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, asio::error_code& ec,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
@ -209,14 +209,15 @@ Iterator connect(basic_socket<Protocol>& s,
|
||||
* Otherwise, contains the error from the last connection attempt.
|
||||
*
|
||||
* @par Example
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::resolver::results_type e = r.resolve(q);
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* asio::connect(s, e.begin(), e.end()); @endcode
|
||||
*/
|
||||
template <typename Protocol, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end);
|
||||
template <typename Protocol, typename Executor, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, Iterator end);
|
||||
|
||||
/// Establishes a socket connection by trying each endpoint in a sequence.
|
||||
/**
|
||||
@ -240,10 +241,10 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end);
|
||||
* endpoint. Otherwise, the end iterator.
|
||||
*
|
||||
* @par Example
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::resolver::results_type e = r.resolve(q);
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* asio::error_code ec;
|
||||
* asio::connect(s, e.begin(), e.end(), ec);
|
||||
* if (ec)
|
||||
@ -251,8 +252,8 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end);
|
||||
* // An error occurred.
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Protocol, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, Iterator end, asio::error_code& ec);
|
||||
|
||||
/// Establishes a socket connection by trying each endpoint in a sequence.
|
||||
@ -299,16 +300,16 @@ Iterator connect(basic_socket<Protocol>& s,
|
||||
* }
|
||||
* }; @endcode
|
||||
* It would be used with the asio::connect function as follows:
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* tcp::endpoint e = asio::connect(s,
|
||||
* r.resolve(q), my_connect_condition());
|
||||
* std::cout << "Connected to: " << e << std::endl; @endcode
|
||||
*/
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
typename ConnectCondition>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename EndpointSequence, typename ConnectCondition>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints, ConnectCondition connect_condition,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type* = 0);
|
||||
@ -358,9 +359,9 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
* }
|
||||
* }; @endcode
|
||||
* It would be used with the asio::connect function as follows:
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* asio::error_code ec;
|
||||
* tcp::endpoint e = asio::connect(s,
|
||||
* r.resolve(q), my_connect_condition(), ec);
|
||||
@ -373,9 +374,9 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
* std::cout << "Connected to: " << e << std::endl;
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
typename ConnectCondition>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename EndpointSequence, typename ConnectCondition>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints, ConnectCondition connect_condition,
|
||||
asio::error_code& ec,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
@ -417,8 +418,9 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
* Iterator represents the end of the sequence. This is a valid assumption for
|
||||
* iterator types such as @c asio::ip::tcp::resolver::iterator.
|
||||
*/
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, ConnectCondition connect_condition,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
|
||||
|
||||
@ -457,8 +459,9 @@ Iterator connect(basic_socket<Protocol>& s,
|
||||
* Iterator represents the end of the sequence. This is a valid assumption for
|
||||
* iterator types such as @c asio::ip::tcp::resolver::iterator.
|
||||
*/
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
ConnectCondition connect_condition, asio::error_code& ec,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
@ -509,16 +512,17 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* }
|
||||
* }; @endcode
|
||||
* It would be used with the asio::connect function as follows:
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::resolver::results_type e = r.resolve(q);
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* tcp::resolver::results_type::iterator i = asio::connect(
|
||||
* s, e.begin(), e.end(), my_connect_condition());
|
||||
* std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode
|
||||
*/
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
Iterator end, ConnectCondition connect_condition);
|
||||
|
||||
/// Establishes a socket connection by trying each endpoint in a sequence.
|
||||
@ -568,10 +572,10 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* }
|
||||
* }; @endcode
|
||||
* It would be used with the asio::connect function as follows:
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::resolver::results_type e = r.resolve(q);
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* asio::error_code ec;
|
||||
* tcp::resolver::results_type::iterator i = asio::connect(
|
||||
* s, e.begin(), e.end(), my_connect_condition());
|
||||
@ -584,9 +588,11 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* std::cout << "Connected to: " << i->endpoint() << std::endl;
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
ConnectCondition connect_condition, asio::error_code& ec);
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, Iterator end, ConnectCondition connect_condition,
|
||||
asio::error_code& ec);
|
||||
|
||||
/*@}*/
|
||||
|
||||
@ -625,14 +631,14 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
* const typename Protocol::endpoint& endpoint
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
@ -659,11 +665,12 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
* // ...
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
typename RangeConnectHandler>
|
||||
template <typename Protocol, typename Executor,
|
||||
typename EndpointSequence, typename RangeConnectHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
||||
void (asio::error_code, typename Protocol::endpoint))
|
||||
async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
async_connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints,
|
||||
ASIO_MOVE_ARG(RangeConnectHandler) handler,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type* = 0);
|
||||
@ -696,18 +703,19 @@ async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
* Iterator iterator
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note This overload assumes that a default constructed object of type @c
|
||||
* Iterator represents the end of the sequence. This is a valid assumption for
|
||||
* iterator types such as @c asio::ip::tcp::resolver::iterator.
|
||||
*/
|
||||
template <typename Protocol, typename Iterator, typename IteratorConnectHandler>
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename IteratorConnectHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator))
|
||||
async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
ASIO_MOVE_ARG(IteratorConnectHandler) handler,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
@ -741,13 +749,13 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* Iterator iterator
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* @code std::vector<tcp::endpoint> endpoints = ...;
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
* asio::async_connect(s,
|
||||
* endpoints.begin(), endpoints.end(),
|
||||
* connect_handler);
|
||||
@ -761,10 +769,11 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* // ...
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Protocol, typename Iterator, typename IteratorConnectHandler>
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename IteratorConnectHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator))
|
||||
async_connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
|
||||
ASIO_MOVE_ARG(IteratorConnectHandler) handler);
|
||||
|
||||
/// Asynchronously establishes a socket connection by trying each endpoint in a
|
||||
@ -805,9 +814,9 @@ async_connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
* Iterator iterator
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* The following connect condition function object can be used to output
|
||||
@ -824,9 +833,9 @@ async_connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
* }
|
||||
* }; @endcode
|
||||
* It would be used with the asio::connect function as follows:
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
@ -862,12 +871,12 @@ async_connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
* }
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
||||
void (asio::error_code, typename Protocol::endpoint))
|
||||
async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
ConnectCondition connect_condition,
|
||||
async_connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints, ConnectCondition connect_condition,
|
||||
ASIO_MOVE_ARG(RangeConnectHandler) handler,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type* = 0);
|
||||
@ -911,19 +920,19 @@ async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
* Iterator iterator
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note This overload assumes that a default constructed object of type @c
|
||||
* Iterator represents the end of the sequence. This is a valid assumption for
|
||||
* iterator types such as @c asio::ip::tcp::resolver::iterator.
|
||||
*/
|
||||
template <typename Protocol, typename Iterator,
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator))
|
||||
async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
ConnectCondition connect_condition,
|
||||
ASIO_MOVE_ARG(IteratorConnectHandler) handler,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
|
||||
@ -969,9 +978,9 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* Iterator iterator
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* The following connect condition function object can be used to output
|
||||
@ -988,9 +997,9 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* }
|
||||
* }; @endcode
|
||||
* It would be used with the asio::connect function as follows:
|
||||
* @code tcp::resolver r(io_context);
|
||||
* @code tcp::resolver r(my_context);
|
||||
* tcp::resolver::query q("host", "service");
|
||||
* tcp::socket s(io_context);
|
||||
* tcp::socket s(my_context);
|
||||
*
|
||||
* // ...
|
||||
*
|
||||
@ -1027,11 +1036,11 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
* }
|
||||
* } @endcode
|
||||
*/
|
||||
template <typename Protocol, typename Iterator,
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator))
|
||||
async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
Iterator end, ConnectCondition connect_condition,
|
||||
ASIO_MOVE_ARG(IteratorConnectHandler) handler);
|
||||
|
||||
|
@ -205,7 +205,7 @@ class coroutine_ref;
|
||||
* {
|
||||
* do
|
||||
* {
|
||||
* socket_.reset(new tcp::socket(io_context_));
|
||||
* socket_.reset(new tcp::socket(my_context_));
|
||||
* yield acceptor->async_accept(*socket_, *this);
|
||||
* fork server(*this)();
|
||||
* } while (is_parent());
|
||||
@ -227,7 +227,7 @@ class coroutine_ref;
|
||||
* Note that @c fork doesn't do the actual forking by itself. It is the
|
||||
* application's responsibility to create a clone of the coroutine and call it.
|
||||
* The clone can be called immediately, as above, or scheduled for delayed
|
||||
* execution using something like io_context::post().
|
||||
* execution using something like asio::post().
|
||||
*
|
||||
* @par Alternate macro names
|
||||
*
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <cstddef>
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
@ -43,7 +43,7 @@ namespace detail {
|
||||
|
||||
template <typename Time_Traits>
|
||||
class deadline_timer_service
|
||||
: public service_base<deadline_timer_service<Time_Traits> >
|
||||
: public execution_context_service_base<deadline_timer_service<Time_Traits> >
|
||||
{
|
||||
public:
|
||||
// The time type.
|
||||
@ -63,9 +63,10 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
deadline_timer_service(asio::io_context& io_context)
|
||||
: service_base<deadline_timer_service<Time_Traits> >(io_context),
|
||||
scheduler_(asio::use_service<timer_scheduler>(io_context))
|
||||
deadline_timer_service(execution_context& context)
|
||||
: execution_context_service_base<
|
||||
deadline_timer_service<Time_Traits> >(context),
|
||||
scheduler_(asio::use_service<timer_scheduler>(context))
|
||||
{
|
||||
scheduler_.init_task();
|
||||
scheduler_.add_timer_queue(timer_queue_);
|
||||
@ -225,14 +226,15 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous wait on the timer.
|
||||
template <typename Handler>
|
||||
void async_wait(implementation_type& impl, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_wait(implementation_type& impl,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef wait_handler<Handler> op;
|
||||
typedef wait_handler<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
impl.might_have_pending_waits = true;
|
||||
|
||||
|
@ -66,20 +66,21 @@ private:
|
||||
MutableBufferSequence buffers_;
|
||||
};
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
|
||||
class descriptor_read_op
|
||||
: public descriptor_read_op_base<MutableBufferSequence>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(descriptor_read_op);
|
||||
|
||||
descriptor_read_op(int descriptor,
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
descriptor_read_op(int descriptor, const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: descriptor_read_op_base<MutableBufferSequence>(
|
||||
descriptor, buffers, &descriptor_read_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -89,7 +90,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -116,6 +117,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -66,20 +66,21 @@ private:
|
||||
ConstBufferSequence buffers_;
|
||||
};
|
||||
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
class descriptor_write_op
|
||||
: public descriptor_write_op_base<ConstBufferSequence>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(descriptor_write_op);
|
||||
|
||||
descriptor_write_op(int descriptor,
|
||||
const ConstBufferSequence& buffers, Handler& handler)
|
||||
descriptor_write_op(int descriptor, const ConstBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: descriptor_write_op_base<ConstBufferSequence>(
|
||||
descriptor, buffers, &descriptor_write_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -89,7 +90,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
descriptor_write_op* o(static_cast<descriptor_write_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -116,6 +117,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -27,24 +27,41 @@ namespace detail {
|
||||
// A helper class template to allow completion handlers to be dispatched
|
||||
// through either the new executors framework or the old invocaton hook. The
|
||||
// primary template uses the new executors framework.
|
||||
template <typename Handler, typename Executor
|
||||
= typename associated_executor<Handler>::type>
|
||||
template <typename Handler,
|
||||
typename IoExecutor = system_executor, typename HandlerExecutor
|
||||
= typename associated_executor<Handler, IoExecutor>::type>
|
||||
class handler_work
|
||||
{
|
||||
public:
|
||||
explicit handler_work(Handler& handler) ASIO_NOEXCEPT
|
||||
: executor_(associated_executor<Handler>::get(handler))
|
||||
: io_executor_(),
|
||||
executor_(asio::get_associated_executor(handler, io_executor_))
|
||||
{
|
||||
}
|
||||
|
||||
handler_work(Handler& handler, const IoExecutor& io_ex) ASIO_NOEXCEPT
|
||||
: io_executor_(io_ex),
|
||||
executor_(asio::get_associated_executor(handler, io_executor_))
|
||||
{
|
||||
}
|
||||
|
||||
static void start(Handler& handler) ASIO_NOEXCEPT
|
||||
{
|
||||
Executor ex(associated_executor<Handler>::get(handler));
|
||||
HandlerExecutor ex(asio::get_associated_executor(handler));
|
||||
ex.on_work_started();
|
||||
}
|
||||
|
||||
static void start(Handler& handler,
|
||||
const IoExecutor& io_ex) ASIO_NOEXCEPT
|
||||
{
|
||||
HandlerExecutor ex(asio::get_associated_executor(handler, io_ex));
|
||||
ex.on_work_started();
|
||||
io_ex.on_work_started();
|
||||
}
|
||||
|
||||
~handler_work()
|
||||
{
|
||||
io_executor_.on_work_finished();
|
||||
executor_.on_work_finished();
|
||||
}
|
||||
|
||||
@ -52,7 +69,7 @@ public:
|
||||
void complete(Function& function, Handler& handler)
|
||||
{
|
||||
executor_.dispatch(ASIO_MOVE_CAST(Function)(function),
|
||||
associated_allocator<Handler>::get(handler));
|
||||
asio::get_associated_allocator(handler));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -60,7 +77,8 @@ private:
|
||||
handler_work(const handler_work&);
|
||||
handler_work& operator=(const handler_work&);
|
||||
|
||||
typename associated_executor<Handler>::type executor_;
|
||||
IoExecutor io_executor_;
|
||||
HandlerExecutor executor_;
|
||||
};
|
||||
|
||||
// This specialisation dispatches a handler through the old invocation hook.
|
||||
@ -68,7 +86,7 @@ private:
|
||||
// system_executor will dispatch through the hook anyway. However, by doing
|
||||
// this we avoid an extra copy of the handler.
|
||||
template <typename Handler>
|
||||
class handler_work<Handler, system_executor>
|
||||
class handler_work<Handler, system_executor, system_executor>
|
||||
{
|
||||
public:
|
||||
explicit handler_work(Handler&) ASIO_NOEXCEPT {}
|
||||
|
@ -30,9 +30,9 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
reactive_descriptor_service::reactive_descriptor_service(
|
||||
asio::io_context& io_context)
|
||||
: service_base<reactive_descriptor_service>(io_context),
|
||||
reactor_(asio::use_service<reactor>(io_context))
|
||||
execution_context& context)
|
||||
: execution_context_service_base<reactive_descriptor_service>(context),
|
||||
reactor_(asio::use_service<reactor>(context))
|
||||
{
|
||||
reactor_.init_task();
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
reactive_serial_port_service::reactive_serial_port_service(
|
||||
asio::io_context& io_context)
|
||||
: service_base<reactive_serial_port_service>(io_context),
|
||||
descriptor_service_(io_context)
|
||||
execution_context& context)
|
||||
: execution_context_service_base<reactive_serial_port_service>(context),
|
||||
descriptor_service_(context)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -28,9 +28,8 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
reactive_socket_service_base::reactive_socket_service_base(
|
||||
asio::io_context& io_context)
|
||||
: io_context_(io_context),
|
||||
reactor_(use_service<reactor>(io_context))
|
||||
execution_context& context)
|
||||
: reactor_(use_service<reactor>(context))
|
||||
{
|
||||
reactor_.init_task();
|
||||
}
|
||||
|
@ -23,25 +23,30 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class resolver_service_base::work_io_context_runner
|
||||
class resolver_service_base::work_scheduler_runner
|
||||
{
|
||||
public:
|
||||
work_io_context_runner(asio::io_context& io_context)
|
||||
: io_context_(io_context) {}
|
||||
void operator()() { io_context_.run(); }
|
||||
work_scheduler_runner(scheduler_impl& work_scheduler)
|
||||
: work_scheduler_(work_scheduler)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
asio::error_code ec;
|
||||
work_scheduler_.run(ec);
|
||||
}
|
||||
|
||||
private:
|
||||
asio::io_context& io_context_;
|
||||
scheduler_impl& work_scheduler_;
|
||||
};
|
||||
|
||||
resolver_service_base::resolver_service_base(
|
||||
asio::io_context& io_context)
|
||||
: io_context_impl_(asio::use_service<io_context_impl>(io_context)),
|
||||
work_io_context_(new asio::io_context(-1)),
|
||||
work_io_context_impl_(asio::use_service<
|
||||
io_context_impl>(*work_io_context_)),
|
||||
work_(asio::make_work_guard(*work_io_context_)),
|
||||
resolver_service_base::resolver_service_base(execution_context& context)
|
||||
: scheduler_(asio::use_service<scheduler_impl>(context)),
|
||||
work_scheduler_(new scheduler_impl(context, -1, false)),
|
||||
work_thread_(0)
|
||||
{
|
||||
work_scheduler_->work_started();
|
||||
}
|
||||
|
||||
resolver_service_base::~resolver_service_base()
|
||||
@ -51,34 +56,35 @@ resolver_service_base::~resolver_service_base()
|
||||
|
||||
void resolver_service_base::base_shutdown()
|
||||
{
|
||||
work_.reset();
|
||||
if (work_io_context_.get())
|
||||
if (work_scheduler_.get())
|
||||
{
|
||||
work_io_context_->stop();
|
||||
work_scheduler_->work_finished();
|
||||
work_scheduler_->stop();
|
||||
if (work_thread_.get())
|
||||
{
|
||||
work_thread_->join();
|
||||
work_thread_.reset();
|
||||
}
|
||||
work_io_context_.reset();
|
||||
work_scheduler_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void resolver_service_base::base_notify_fork(
|
||||
asio::io_context::fork_event fork_ev)
|
||||
execution_context::fork_event fork_ev)
|
||||
{
|
||||
if (work_thread_.get())
|
||||
{
|
||||
if (fork_ev == asio::io_context::fork_prepare)
|
||||
if (fork_ev == execution_context::fork_prepare)
|
||||
{
|
||||
work_io_context_->stop();
|
||||
work_scheduler_->stop();
|
||||
work_thread_->join();
|
||||
work_thread_.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
work_io_context_->restart();
|
||||
work_scheduler_->restart();
|
||||
work_thread_.reset(new asio::detail::thread(
|
||||
work_io_context_runner(*work_io_context_)));
|
||||
work_scheduler_runner(*work_scheduler_)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,7 +98,7 @@ void resolver_service_base::construct(
|
||||
void resolver_service_base::destroy(
|
||||
resolver_service_base::implementation_type& impl)
|
||||
{
|
||||
ASIO_HANDLER_OPERATION((io_context_impl_.context(),
|
||||
ASIO_HANDLER_OPERATION((scheduler_.context(),
|
||||
"resolver", &impl, 0, "cancel"));
|
||||
|
||||
impl.reset();
|
||||
@ -114,7 +120,7 @@ void resolver_service_base::move_assign(implementation_type& impl,
|
||||
void resolver_service_base::cancel(
|
||||
resolver_service_base::implementation_type& impl)
|
||||
{
|
||||
ASIO_HANDLER_OPERATION((io_context_impl_.context(),
|
||||
ASIO_HANDLER_OPERATION((scheduler_.context(),
|
||||
"resolver", &impl, 0, "cancel"));
|
||||
|
||||
impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
|
||||
@ -123,16 +129,16 @@ void resolver_service_base::cancel(
|
||||
void resolver_service_base::start_resolve_op(resolve_op* op)
|
||||
{
|
||||
if (ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
|
||||
io_context_impl_.concurrency_hint()))
|
||||
scheduler_.concurrency_hint()))
|
||||
{
|
||||
start_work_thread();
|
||||
io_context_impl_.work_started();
|
||||
work_io_context_impl_.post_immediate_completion(op, false);
|
||||
scheduler_.work_started();
|
||||
work_scheduler_->post_immediate_completion(op, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
op->ec_ = asio::error::operation_not_supported;
|
||||
io_context_impl_.post_immediate_completion(op, false);
|
||||
scheduler_.post_immediate_completion(op, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +148,7 @@ void resolver_service_base::start_work_thread()
|
||||
if (!work_thread_.get())
|
||||
{
|
||||
work_thread_.reset(new asio::detail::thread(
|
||||
work_io_context_runner(*work_io_context_)));
|
||||
work_scheduler_runner(*work_scheduler_)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,12 +23,31 @@
|
||||
#include "asio/detail/reactor.hpp"
|
||||
#include "asio/detail/scheduler.hpp"
|
||||
#include "asio/detail/scheduler_thread_info.hpp"
|
||||
#include "asio/detail/signal_blocker.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class scheduler::thread_function
|
||||
{
|
||||
public:
|
||||
explicit thread_function(scheduler* s)
|
||||
: this_(s)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
asio::error_code ec;
|
||||
this_->run(ec);
|
||||
}
|
||||
|
||||
private:
|
||||
scheduler* this_;
|
||||
};
|
||||
|
||||
struct scheduler::task_cleanup
|
||||
{
|
||||
~task_cleanup()
|
||||
@ -84,8 +103,8 @@ struct scheduler::work_cleanup
|
||||
thread_info* this_thread_;
|
||||
};
|
||||
|
||||
scheduler::scheduler(
|
||||
asio::execution_context& ctx, int concurrency_hint)
|
||||
scheduler::scheduler(asio::execution_context& ctx,
|
||||
int concurrency_hint, bool own_thread)
|
||||
: asio::detail::execution_context_service_base<scheduler>(ctx),
|
||||
one_thread_(concurrency_hint == 1
|
||||
|| !ASIO_CONCURRENCY_HINT_IS_LOCKING(
|
||||
@ -99,17 +118,44 @@ scheduler::scheduler(
|
||||
outstanding_work_(0),
|
||||
stopped_(false),
|
||||
shutdown_(false),
|
||||
concurrency_hint_(concurrency_hint)
|
||||
concurrency_hint_(concurrency_hint),
|
||||
thread_(0)
|
||||
{
|
||||
ASIO_HANDLER_TRACKING_INIT;
|
||||
|
||||
if (own_thread)
|
||||
{
|
||||
++outstanding_work_;
|
||||
asio::detail::signal_blocker sb;
|
||||
thread_ = new asio::detail::thread(thread_function(this));
|
||||
}
|
||||
}
|
||||
|
||||
scheduler::~scheduler()
|
||||
{
|
||||
if (thread_)
|
||||
{
|
||||
thread_->join();
|
||||
delete thread_;
|
||||
}
|
||||
}
|
||||
|
||||
void scheduler::shutdown()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
if (thread_)
|
||||
stop_all_threads(lock);
|
||||
lock.unlock();
|
||||
|
||||
// Join thread to ensure task operation is returned to queue.
|
||||
if (thread_)
|
||||
{
|
||||
thread_->join();
|
||||
delete thread_;
|
||||
thread_ = 0;
|
||||
}
|
||||
|
||||
// Destroy handler objects.
|
||||
while (!op_queue_.empty())
|
||||
{
|
||||
|
@ -118,14 +118,13 @@ public:
|
||||
// && !defined(ASIO_WINDOWS_RUNTIME)
|
||||
// && !defined(__CYGWIN__)
|
||||
|
||||
signal_set_service::signal_set_service(
|
||||
asio::io_context& io_context)
|
||||
: service_base<signal_set_service>(io_context),
|
||||
io_context_(asio::use_service<io_context_impl>(io_context)),
|
||||
signal_set_service::signal_set_service(execution_context& context)
|
||||
: execution_context_service_base<signal_set_service>(context),
|
||||
scheduler_(asio::use_service<scheduler_impl>(context)),
|
||||
#if !defined(ASIO_WINDOWS) \
|
||||
&& !defined(ASIO_WINDOWS_RUNTIME) \
|
||||
&& !defined(__CYGWIN__)
|
||||
reactor_(asio::use_service<reactor>(io_context)),
|
||||
reactor_(asio::use_service<reactor>(context)),
|
||||
#endif // !defined(ASIO_WINDOWS)
|
||||
// && !defined(ASIO_WINDOWS_RUNTIME)
|
||||
// && !defined(__CYGWIN__)
|
||||
@ -169,11 +168,10 @@ void signal_set_service::shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
io_context_.abandon_operations(ops);
|
||||
scheduler_.abandon_operations(ops);
|
||||
}
|
||||
|
||||
void signal_set_service::notify_fork(
|
||||
asio::io_context::fork_event fork_ev)
|
||||
void signal_set_service::notify_fork(execution_context::fork_event fork_ev)
|
||||
{
|
||||
#if !defined(ASIO_WINDOWS) \
|
||||
&& !defined(ASIO_WINDOWS_RUNTIME) \
|
||||
@ -183,7 +181,7 @@ void signal_set_service::notify_fork(
|
||||
|
||||
switch (fork_ev)
|
||||
{
|
||||
case asio::io_context::fork_prepare:
|
||||
case execution_context::fork_prepare:
|
||||
{
|
||||
int read_descriptor = state->read_descriptor_;
|
||||
state->fork_prepared_ = true;
|
||||
@ -192,7 +190,7 @@ void signal_set_service::notify_fork(
|
||||
reactor_.cleanup_descriptor_data(reactor_data_);
|
||||
}
|
||||
break;
|
||||
case asio::io_context::fork_parent:
|
||||
case execution_context::fork_parent:
|
||||
if (state->fork_prepared_)
|
||||
{
|
||||
int read_descriptor = state->read_descriptor_;
|
||||
@ -202,7 +200,7 @@ void signal_set_service::notify_fork(
|
||||
read_descriptor, reactor_data_, new pipe_read_op);
|
||||
}
|
||||
break;
|
||||
case asio::io_context::fork_child:
|
||||
case execution_context::fork_child:
|
||||
if (state->fork_prepared_)
|
||||
{
|
||||
asio::detail::signal_blocker blocker;
|
||||
@ -441,7 +439,7 @@ asio::error_code signal_set_service::cancel(
|
||||
signal_set_service::implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
ASIO_HANDLER_OPERATION((io_context_.context(),
|
||||
ASIO_HANDLER_OPERATION((scheduler_.context(),
|
||||
"signal_set", &impl, 0, "cancel"));
|
||||
|
||||
op_queue<operation> ops;
|
||||
@ -457,7 +455,7 @@ asio::error_code signal_set_service::cancel(
|
||||
}
|
||||
}
|
||||
|
||||
io_context_.post_deferred_completions(ops);
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
@ -493,7 +491,7 @@ void signal_set_service::deliver_signal(int signal_number)
|
||||
reg = reg->next_in_table_;
|
||||
}
|
||||
|
||||
service->io_context_.post_deferred_completions(ops);
|
||||
service->scheduler_.post_deferred_completions(ops);
|
||||
|
||||
service = service->next_;
|
||||
}
|
||||
@ -510,17 +508,17 @@ void signal_set_service::add_service(signal_set_service* service)
|
||||
open_descriptors();
|
||||
#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
// If an io_context object is thread-unsafe then it must be the only
|
||||
// io_context used to create signal_set objects.
|
||||
// If a scheduler_ object is thread-unsafe then it must be the only
|
||||
// scheduler used to create signal_set objects.
|
||||
if (state->service_list_ != 0)
|
||||
{
|
||||
if (!ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
|
||||
service->io_context_.concurrency_hint())
|
||||
service->scheduler_.concurrency_hint())
|
||||
|| !ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
|
||||
state->service_list_->io_context_.concurrency_hint()))
|
||||
state->service_list_->scheduler_.concurrency_hint()))
|
||||
{
|
||||
std::logic_error ex(
|
||||
"Thread-unsafe io_context objects require "
|
||||
"Thread-unsafe execution context objects require "
|
||||
"exclusive access to signal handling.");
|
||||
asio::detail::throw_exception(ex);
|
||||
}
|
||||
@ -639,7 +637,7 @@ void signal_set_service::close_descriptors()
|
||||
void signal_set_service::start_wait_op(
|
||||
signal_set_service::implementation_type& impl, signal_op* op)
|
||||
{
|
||||
io_context_.work_started();
|
||||
scheduler_.work_started();
|
||||
|
||||
signal_state* state = get_signal_state();
|
||||
static_mutex::scoped_lock lock(state->mutex_);
|
||||
@ -651,7 +649,7 @@ void signal_set_service::start_wait_op(
|
||||
{
|
||||
--reg->undelivered_;
|
||||
op->signal_number_ = reg->signal_number_;
|
||||
io_context_.post_deferred_completion(op);
|
||||
scheduler_.post_deferred_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -65,10 +65,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
win_iocp_handle_service::win_iocp_handle_service(
|
||||
asio::io_context& io_context)
|
||||
: service_base<win_iocp_handle_service>(io_context),
|
||||
iocp_service_(asio::use_service<win_iocp_io_context>(io_context)),
|
||||
win_iocp_handle_service::win_iocp_handle_service(execution_context& context)
|
||||
: execution_context_service_base<win_iocp_handle_service>(context),
|
||||
iocp_service_(asio::use_service<win_iocp_io_context>(context)),
|
||||
mutex_(),
|
||||
impl_list_(0)
|
||||
{
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/limits.hpp"
|
||||
#include "asio/detail/thread.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/win_iocp_io_context.hpp"
|
||||
|
||||
@ -32,6 +33,22 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
struct win_iocp_io_context::thread_function
|
||||
{
|
||||
explicit thread_function(win_iocp_io_context* s)
|
||||
: this_(s)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
asio::error_code ec;
|
||||
this_->run(ec);
|
||||
}
|
||||
|
||||
win_iocp_io_context* this_;
|
||||
};
|
||||
|
||||
struct win_iocp_io_context::work_finished_on_block_exit
|
||||
{
|
||||
~work_finished_on_block_exit()
|
||||
@ -62,7 +79,7 @@ struct win_iocp_io_context::timer_thread_function
|
||||
};
|
||||
|
||||
win_iocp_io_context::win_iocp_io_context(
|
||||
asio::execution_context& ctx, int concurrency_hint)
|
||||
asio::execution_context& ctx, int concurrency_hint, bool own_thread)
|
||||
: execution_context_service_base<win_iocp_io_context>(ctx),
|
||||
iocp_(),
|
||||
outstanding_work_(0),
|
||||
@ -84,6 +101,21 @@ win_iocp_io_context::win_iocp_io_context(
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "iocp");
|
||||
}
|
||||
|
||||
if (own_thread)
|
||||
{
|
||||
::InterlockedIncrement(&outstanding_work_);
|
||||
thread_.reset(new asio::detail::thread(thread_function(this)));
|
||||
}
|
||||
}
|
||||
|
||||
win_iocp_io_context::~win_iocp_io_context()
|
||||
{
|
||||
if (thread_.get())
|
||||
{
|
||||
thread_->join();
|
||||
thread_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_context::shutdown()
|
||||
@ -97,6 +129,13 @@ void win_iocp_io_context::shutdown()
|
||||
::SetWaitableTimer(waitable_timer_.handle, &timeout, 1, 0, 0, FALSE);
|
||||
}
|
||||
|
||||
if (thread_.get())
|
||||
{
|
||||
thread_->join();
|
||||
thread_.reset();
|
||||
::InterlockedDecrement(&outstanding_work_);
|
||||
}
|
||||
|
||||
while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)
|
||||
{
|
||||
op_queue<win_iocp_operation> ops;
|
||||
|
@ -29,9 +29,9 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_iocp_serial_port_service::win_iocp_serial_port_service(
|
||||
asio::io_context& io_context)
|
||||
: service_base<win_iocp_serial_port_service>(io_context),
|
||||
handle_service_(io_context)
|
||||
execution_context& context)
|
||||
: execution_context_service_base<win_iocp_serial_port_service>(context),
|
||||
handle_service_(context)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -27,9 +27,9 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_iocp_socket_service_base::win_iocp_socket_service_base(
|
||||
asio::io_context& io_context)
|
||||
: io_context_(io_context),
|
||||
iocp_service_(use_service<win_iocp_io_context>(io_context)),
|
||||
execution_context& context)
|
||||
: context_(context),
|
||||
iocp_service_(use_service<win_iocp_io_context>(context)),
|
||||
reactor_(0),
|
||||
connect_ex_(0),
|
||||
nt_set_info_(0),
|
||||
@ -707,7 +707,7 @@ select_reactor& win_iocp_socket_service_base::get_reactor()
|
||||
reinterpret_cast<void**>(&reactor_), 0, 0));
|
||||
if (!r)
|
||||
{
|
||||
r = &(use_service<select_reactor>(io_context_));
|
||||
r = &(use_service<select_reactor>(context_));
|
||||
interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);
|
||||
}
|
||||
return *r;
|
||||
|
@ -27,10 +27,9 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_object_handle_service::win_object_handle_service(
|
||||
asio::io_context& io_context)
|
||||
: service_base<win_object_handle_service>(io_context),
|
||||
io_context_(asio::use_service<io_context_impl>(io_context)),
|
||||
win_object_handle_service::win_object_handle_service(execution_context& context)
|
||||
: execution_context_service_base<win_object_handle_service>(context),
|
||||
scheduler_(asio::use_service<scheduler_impl>(context)),
|
||||
mutex_(),
|
||||
impl_list_(0),
|
||||
shutdown_(false)
|
||||
@ -52,7 +51,7 @@ void win_object_handle_service::shutdown()
|
||||
|
||||
lock.unlock();
|
||||
|
||||
io_context_.abandon_operations(ops);
|
||||
scheduler_.abandon_operations(ops);
|
||||
}
|
||||
|
||||
void win_object_handle_service::construct(
|
||||
@ -178,7 +177,7 @@ void win_object_handle_service::destroy(
|
||||
|
||||
if (is_open(impl))
|
||||
{
|
||||
ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle",
|
||||
ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle",
|
||||
&impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "close"));
|
||||
|
||||
HANDLE wait_handle = impl.wait_handle_;
|
||||
@ -203,7 +202,7 @@ void win_object_handle_service::destroy(
|
||||
::CloseHandle(impl.handle_);
|
||||
impl.handle_ = INVALID_HANDLE_VALUE;
|
||||
|
||||
io_context_.post_deferred_completions(ops);
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,7 +227,7 @@ asio::error_code win_object_handle_service::close(
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle",
|
||||
ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle",
|
||||
&impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "close"));
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
@ -264,7 +263,7 @@ asio::error_code win_object_handle_service::close(
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
|
||||
io_context_.post_deferred_completions(completed_ops);
|
||||
scheduler_.post_deferred_completions(completed_ops);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -280,7 +279,7 @@ asio::error_code win_object_handle_service::cancel(
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle",
|
||||
ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle",
|
||||
&impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "cancel"));
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
@ -306,7 +305,7 @@ asio::error_code win_object_handle_service::cancel(
|
||||
|
||||
ec = asio::error_code();
|
||||
|
||||
io_context_.post_deferred_completions(completed_ops);
|
||||
scheduler_.post_deferred_completions(completed_ops);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -340,7 +339,7 @@ void win_object_handle_service::wait(
|
||||
void win_object_handle_service::start_wait_op(
|
||||
win_object_handle_service::implementation_type& impl, wait_op* op)
|
||||
{
|
||||
io_context_.work_started();
|
||||
scheduler_.work_started();
|
||||
|
||||
if (is_open(impl))
|
||||
{
|
||||
@ -358,13 +357,13 @@ void win_object_handle_service::start_wait_op(
|
||||
else
|
||||
{
|
||||
lock.unlock();
|
||||
io_context_.post_deferred_completion(op);
|
||||
scheduler_.post_deferred_completion(op);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op->ec_ = asio::error::bad_descriptor;
|
||||
io_context_.post_deferred_completion(op);
|
||||
scheduler_.post_deferred_completion(op);
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,7 +390,7 @@ void win_object_handle_service::register_wait_callback(
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
io_context_.post_deferred_completions(completed_ops);
|
||||
scheduler_.post_deferred_completions(completed_ops);
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,9 +432,9 @@ void win_object_handle_service::wait_callback(PVOID param, BOOLEAN)
|
||||
}
|
||||
}
|
||||
|
||||
io_context_impl& ioc = impl->owner_->io_context_;
|
||||
scheduler_impl& sched = impl->owner_->scheduler_;
|
||||
lock.unlock();
|
||||
ioc.post_deferred_completions(completed_ops);
|
||||
sched.post_deferred_completions(completed_ops);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,9 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
winrt_ssocket_service_base::winrt_ssocket_service_base(
|
||||
asio::io_context& io_context)
|
||||
: io_context_(use_service<io_context_impl>(io_context)),
|
||||
async_manager_(use_service<winrt_async_manager>(io_context)),
|
||||
execution_context& context)
|
||||
: scheduler_(use_service<scheduler_impl>(context)),
|
||||
async_manager_(use_service<winrt_async_manager>(context)),
|
||||
mutex_(),
|
||||
impl_list_(0)
|
||||
{
|
||||
@ -398,7 +398,7 @@ void winrt_ssocket_service_base::start_connect_op(
|
||||
if (!is_open(impl))
|
||||
{
|
||||
op->ec_ = asio::error::bad_descriptor;
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -427,7 +427,7 @@ void winrt_ssocket_service_base::start_connect_op(
|
||||
|
||||
if (op->ec_)
|
||||
{
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -442,7 +442,7 @@ void winrt_ssocket_service_base::start_connect_op(
|
||||
{
|
||||
op->ec_ = asio::error_code(
|
||||
e->HResult, asio::system_category());
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,14 +493,14 @@ void winrt_ssocket_service_base::start_send_op(
|
||||
if (flags)
|
||||
{
|
||||
op->ec_ = asio::error::operation_not_supported;
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_open(impl))
|
||||
{
|
||||
op->ec_ = asio::error::bad_descriptor;
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -511,7 +511,7 @@ void winrt_ssocket_service_base::start_send_op(
|
||||
|
||||
if (bufs.all_empty())
|
||||
{
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -522,7 +522,7 @@ void winrt_ssocket_service_base::start_send_op(
|
||||
{
|
||||
op->ec_ = asio::error_code(e->HResult,
|
||||
asio::system_category());
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -584,14 +584,14 @@ void winrt_ssocket_service_base::start_receive_op(
|
||||
if (flags)
|
||||
{
|
||||
op->ec_ = asio::error::operation_not_supported;
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_open(impl))
|
||||
{
|
||||
op->ec_ = asio::error::bad_descriptor;
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -602,7 +602,7 @@ void winrt_ssocket_service_base::start_receive_op(
|
||||
|
||||
if (bufs.all_empty())
|
||||
{
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -615,7 +615,7 @@ void winrt_ssocket_service_base::start_receive_op(
|
||||
{
|
||||
op->ec_ = asio::error_code(e->HResult,
|
||||
asio::system_category());
|
||||
io_context_.post_immediate_completion(op, is_continuation);
|
||||
scheduler_.post_immediate_completion(op, is_continuation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,12 +46,12 @@ void winrt_timer_scheduler::schedule_timer(timer_queue<Time_Traits>& queue,
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
io_context_.post_immediate_completion(op, false);
|
||||
scheduler_.post_immediate_completion(op, false);
|
||||
return;
|
||||
}
|
||||
|
||||
bool earliest = queue.enqueue_timer(time, timer, op);
|
||||
io_context_.work_started();
|
||||
scheduler_.work_started();
|
||||
if (earliest)
|
||||
event_.signal(lock);
|
||||
}
|
||||
@ -65,7 +65,7 @@ std::size_t winrt_timer_scheduler::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
op_queue<operation> ops;
|
||||
std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
|
||||
lock.unlock();
|
||||
io_context_.post_deferred_completions(ops);
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,9 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
winrt_timer_scheduler::winrt_timer_scheduler(
|
||||
asio::io_context& io_context)
|
||||
: asio::detail::service_base<winrt_timer_scheduler>(io_context),
|
||||
io_context_(use_service<io_context_impl>(io_context)),
|
||||
winrt_timer_scheduler::winrt_timer_scheduler(execution_context& context)
|
||||
: execution_context_service_base<winrt_timer_scheduler>(context),
|
||||
scheduler_(use_service<scheduler_impl>(context)),
|
||||
mutex_(),
|
||||
event_(),
|
||||
timer_queues_(),
|
||||
@ -64,10 +63,10 @@ void winrt_timer_scheduler::shutdown()
|
||||
|
||||
op_queue<operation> ops;
|
||||
timer_queues_.get_all_timers(ops);
|
||||
io_context_.abandon_operations(ops);
|
||||
scheduler_.abandon_operations(ops);
|
||||
}
|
||||
|
||||
void winrt_timer_scheduler::notify_fork(asio::io_context::fork_event)
|
||||
void winrt_timer_scheduler::notify_fork(execution_context::fork_event)
|
||||
{
|
||||
}
|
||||
|
||||
@ -89,7 +88,7 @@ void winrt_timer_scheduler::run_thread()
|
||||
if (!ops.empty())
|
||||
{
|
||||
lock.unlock();
|
||||
io_context_.post_deferred_completions(ops);
|
||||
scheduler_.post_deferred_completions(ops);
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
|
127
asio/include/asio/detail/io_object_executor.hpp
Normal file
127
asio/include/asio/detail/io_object_executor.hpp
Normal file
@ -0,0 +1,127 @@
|
||||
//
|
||||
// io_object_executor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP
|
||||
#define ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/type_traits.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
// Wrap the (potentially polymorphic) executor so that we can bypass it when
|
||||
// dispatching on a target executor that has a native I/O implementation.
|
||||
template <typename Executor>
|
||||
class io_object_executor
|
||||
{
|
||||
public:
|
||||
io_object_executor(const Executor& ex, bool native_implementation)
|
||||
: executor_(ex),
|
||||
has_native_impl_(native_implementation)
|
||||
{
|
||||
}
|
||||
|
||||
execution_context& context() const ASIO_NOEXCEPT
|
||||
{
|
||||
return executor_.context();
|
||||
}
|
||||
|
||||
void on_work_started() const ASIO_NOEXCEPT
|
||||
{
|
||||
if (is_same<Executor, io_context::executor_type>::value
|
||||
|| has_native_impl_)
|
||||
{
|
||||
// When using a native implementation, work is already counted by the
|
||||
// execution context.
|
||||
}
|
||||
else
|
||||
{
|
||||
executor_.on_work_started();
|
||||
}
|
||||
}
|
||||
|
||||
void on_work_finished() const ASIO_NOEXCEPT
|
||||
{
|
||||
if (is_same<Executor, io_context::executor_type>::value
|
||||
|| has_native_impl_)
|
||||
{
|
||||
// When using a native implementation, work is already counted by the
|
||||
// execution context.
|
||||
}
|
||||
else
|
||||
{
|
||||
executor_.on_work_finished();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F, typename A>
|
||||
void dispatch(ASIO_MOVE_ARG(F) f, const A& a) const
|
||||
{
|
||||
if (is_same<Executor, io_context::executor_type>::value
|
||||
|| has_native_impl_)
|
||||
{
|
||||
// When using a native implementation, I/O completion handlers are
|
||||
// already dispatched according to the execution context's executor's
|
||||
// rules. We can call the function directly.
|
||||
typename decay<F>::type function(ASIO_MOVE_CAST(F)(f));
|
||||
asio_handler_invoke_helpers::invoke(function, function);
|
||||
}
|
||||
else
|
||||
{
|
||||
executor_.dispatch(ASIO_MOVE_CAST(F)(f), a);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F, typename A>
|
||||
void post(ASIO_MOVE_ARG(F) f, const A& a) const
|
||||
{
|
||||
executor_.post(ASIO_MOVE_CAST(F)(f), a);
|
||||
}
|
||||
|
||||
template <typename F, typename A>
|
||||
void defer(ASIO_MOVE_ARG(F) f, const A& a) const
|
||||
{
|
||||
executor_.defer(ASIO_MOVE_CAST(F)(f), a);
|
||||
}
|
||||
|
||||
friend bool operator==(const io_object_executor& a,
|
||||
const io_object_executor& b) ASIO_NOEXCEPT
|
||||
{
|
||||
return a.executor_ == b.executor_
|
||||
&& a.has_native_impl_ == b.has_native_impl_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const io_object_executor& a,
|
||||
const io_object_executor& b) ASIO_NOEXCEPT
|
||||
{
|
||||
return a.executor_ != b.executor_
|
||||
|| a.has_native_impl_ != b.has_native_impl_;
|
||||
}
|
||||
|
||||
private:
|
||||
Executor executor_;
|
||||
const bool has_native_impl_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP
|
@ -15,7 +15,10 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <new>
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/detail/io_object_executor.hpp"
|
||||
#include "asio/detail/type_traits.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
@ -23,7 +26,8 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename IoObjectService>
|
||||
template <typename IoObjectService,
|
||||
typename Executor = io_context::executor_type>
|
||||
class io_object_impl
|
||||
{
|
||||
public:
|
||||
@ -34,11 +38,28 @@ public:
|
||||
typedef typename service_type::implementation_type implementation_type;
|
||||
|
||||
// The type of the executor associated with the object.
|
||||
typedef asio::io_context::executor_type executor_type;
|
||||
typedef Executor executor_type;
|
||||
|
||||
// Construct an I/O object.
|
||||
explicit io_object_impl(asio::io_context& io_context)
|
||||
: service_(&asio::use_service<IoObjectService>(io_context))
|
||||
// The type of executor to be used when implementing asynchronous operations.
|
||||
typedef io_object_executor<Executor> implementation_executor_type;
|
||||
|
||||
// Construct an I/O object using an executor.
|
||||
explicit io_object_impl(const executor_type& ex)
|
||||
: executor_(ex),
|
||||
service_(&asio::use_service<IoObjectService>(ex.context())),
|
||||
has_native_impl_(is_same<Executor, io_context::executor_type>::value)
|
||||
{
|
||||
service_->construct(implementation_);
|
||||
}
|
||||
|
||||
// Construct an I/O object using an execution context.
|
||||
template <typename ExecutionContext>
|
||||
explicit io_object_impl(ExecutionContext& context,
|
||||
typename enable_if<is_convertible<
|
||||
ExecutionContext&, execution_context&>::value>::type* = 0)
|
||||
: executor_(context.get_executor()),
|
||||
service_(&asio::use_service<IoObjectService>(context)),
|
||||
has_native_impl_(is_same<ExecutionContext, io_context>::value)
|
||||
{
|
||||
service_->construct(implementation_);
|
||||
}
|
||||
@ -46,16 +67,19 @@ public:
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
// Move-construct an I/O object.
|
||||
io_object_impl(io_object_impl&& other)
|
||||
: service_(&other.get_service())
|
||||
: executor_(other.get_executor()),
|
||||
service_(&other.get_service()),
|
||||
has_native_impl_(other.has_native_impl_)
|
||||
{
|
||||
service_->move_construct(implementation_, other.implementation_);
|
||||
}
|
||||
|
||||
// Perform a converting move-construction of an I/O object.
|
||||
template <typename IoObjectService1>
|
||||
io_object_impl(io_object_impl<IoObjectService1>&& other)
|
||||
: service_(&asio::use_service<IoObjectService>(
|
||||
other.get_service().get_io_context()))
|
||||
template <typename IoObjectService1, typename Executor1>
|
||||
io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other)
|
||||
: executor_(other.get_executor()),
|
||||
service_(&asio::use_service<IoObjectService>(executor_.context())),
|
||||
has_native_impl_(is_same<Executor1, io_context::executor_type>::value)
|
||||
{
|
||||
service_->converting_move_construct(implementation_,
|
||||
other.get_service(), other.get_implementation());
|
||||
@ -72,31 +96,29 @@ public:
|
||||
// Move-assign an I/O object.
|
||||
io_object_impl& operator=(io_object_impl&& other)
|
||||
{
|
||||
service_->move_assign(implementation_,
|
||||
*other.service_, other.implementation_);
|
||||
service_ = other.service_;
|
||||
if (this != &other)
|
||||
{
|
||||
service_->move_assign(implementation_,
|
||||
*other.service_, other.implementation_);
|
||||
executor_.~executor_type();
|
||||
new (&executor_) executor_type(std::move(other.executor_));
|
||||
service_ = other.service_;
|
||||
has_native_impl_ = other.has_native_impl_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
#if !defined(ASIO_NO_DEPRECATED)
|
||||
// Deprecated access to underlying I/O context.
|
||||
asio::io_context& get_io_context()
|
||||
{
|
||||
return service_->get_io_context();
|
||||
}
|
||||
|
||||
// Deprecated access to underlying I/O context.
|
||||
asio::io_context& get_io_service()
|
||||
{
|
||||
return service_->get_io_context();
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
// Get the executor associated with the object.
|
||||
executor_type get_executor() ASIO_NOEXCEPT
|
||||
{
|
||||
return service_->get_io_context().get_executor();
|
||||
return executor_;
|
||||
}
|
||||
|
||||
// Get the executor to be used when implementing asynchronous operations.
|
||||
implementation_executor_type get_implementation_executor() ASIO_NOEXCEPT
|
||||
{
|
||||
return io_object_executor<Executor>(executor_, has_native_impl_);
|
||||
}
|
||||
|
||||
// Get the service associated with the I/O object.
|
||||
@ -128,11 +150,17 @@ private:
|
||||
io_object_impl(const io_object_impl&);
|
||||
io_object_impl& operator=(const io_object_impl&);
|
||||
|
||||
// The associated executor.
|
||||
executor_type executor_;
|
||||
|
||||
// The service associated with the I/O object.
|
||||
service_type* service_;
|
||||
|
||||
// The underlying implementation of the I/O object.
|
||||
implementation_type implementation_;
|
||||
|
||||
// Whether the executor has a native I/O implementation.
|
||||
bool has_native_impl_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/post.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
|
||||
@ -32,7 +33,7 @@ namespace detail {
|
||||
|
||||
template <typename Protocol>
|
||||
class null_socket_service :
|
||||
public service_base<null_socket_service<Protocol> >
|
||||
public execution_context_service_base<null_socket_service<Protocol> >
|
||||
{
|
||||
public:
|
||||
// The protocol type.
|
||||
@ -50,9 +51,8 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
null_socket_service(asio::io_context& io_context)
|
||||
: service_base<null_socket_service<Protocol> >(io_context),
|
||||
io_context_(io_context)
|
||||
null_socket_service(execution_context& context)
|
||||
: execution_context_service_base<null_socket_service<Protocol> >(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -272,23 +272,25 @@ public:
|
||||
|
||||
// Start an asynchronous send. The data being sent must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_send(implementation_type&, const ConstBufferSequence&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Start an asynchronous wait until data can be sent without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_send(implementation_type&, const null_buffers&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Receive some data from the peer. Returns the number of bytes received.
|
||||
@ -310,23 +312,26 @@ public:
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive(implementation_type&, const MutableBufferSequence&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive(implementation_type&, const null_buffers&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Receive some data with associated flags. Returns the number of bytes
|
||||
@ -351,25 +356,28 @@ public:
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive_with_flags(implementation_type&,
|
||||
const MutableBufferSequence&, socket_base::message_flags,
|
||||
socket_base::message_flags&, Handler& handler)
|
||||
socket_base::message_flags&, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
void async_receive_with_flags(implementation_type&,
|
||||
const null_buffers&, socket_base::message_flags,
|
||||
socket_base::message_flags&, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive_with_flags(implementation_type&, const null_buffers&,
|
||||
socket_base::message_flags, socket_base::message_flags&,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Send a datagram to the specified endpoint. Returns the number of bytes
|
||||
@ -394,24 +402,27 @@ public:
|
||||
|
||||
// Start an asynchronous send. The data being sent must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_send_to(implementation_type&, const ConstBufferSequence&,
|
||||
const endpoint_type&, socket_base::message_flags,
|
||||
Handler& handler)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Start an asynchronous wait until data can be sent without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_send_to(implementation_type&, const null_buffers&,
|
||||
const endpoint_type&, socket_base::message_flags, Handler& handler)
|
||||
const endpoint_type&, socket_base::message_flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Receive a datagram with the endpoint of the sender. Returns the number of
|
||||
@ -437,25 +448,28 @@ public:
|
||||
// Start an asynchronous receive. The buffer for the data being received and
|
||||
// the sender_endpoint object must both be valid for the lifetime of the
|
||||
// asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
void async_receive_from(implementation_type&,
|
||||
const MutableBufferSequence&, endpoint_type&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive_from(implementation_type&, const MutableBufferSequence&,
|
||||
endpoint_type&, socket_base::message_flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
void async_receive_from(implementation_type&,
|
||||
const null_buffers&, endpoint_type&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive_from(implementation_type&, const null_buffers&,
|
||||
endpoint_type&, socket_base::message_flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
|
||||
asio::post(io_ex, detail::bind_handler(
|
||||
handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
// Accept a new connection.
|
||||
@ -469,12 +483,12 @@ public:
|
||||
|
||||
// Start an asynchronous accept. The peer and peer_endpoint objects
|
||||
// must be valid until the accept's handler is invoked.
|
||||
template <typename Socket, typename Handler>
|
||||
void async_accept(implementation_type&, Socket&,
|
||||
endpoint_type*, Handler& handler)
|
||||
template <typename Socket, typename Handler, typename IoExecutor>
|
||||
void async_accept(implementation_type&, Socket&, endpoint_type*,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
io_context_.post(detail::bind_handler(handler, ec));
|
||||
asio::post(io_ex, detail::bind_handler(handler, ec));
|
||||
}
|
||||
|
||||
// Connect the socket to the specified endpoint.
|
||||
@ -486,16 +500,13 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous connect.
|
||||
template <typename Handler>
|
||||
void async_connect(implementation_type&,
|
||||
const endpoint_type&, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_connect(implementation_type&, const endpoint_type&,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
io_context_.post(detail::bind_handler(handler, ec));
|
||||
asio::post(io_ex, detail::bind_handler(handler, ec));
|
||||
}
|
||||
|
||||
private:
|
||||
asio::io_context& io_context_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -22,7 +22,7 @@
|
||||
&& !defined(__CYGWIN__)
|
||||
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/descriptor_ops.hpp"
|
||||
@ -42,7 +42,7 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class reactive_descriptor_service :
|
||||
public service_base<reactive_descriptor_service>
|
||||
public execution_context_service_base<reactive_descriptor_service>
|
||||
{
|
||||
public:
|
||||
// The native type of a descriptor.
|
||||
@ -75,8 +75,7 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
ASIO_DECL reactive_descriptor_service(
|
||||
asio::io_context& io_context);
|
||||
ASIO_DECL reactive_descriptor_service(execution_context& context);
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void shutdown();
|
||||
@ -190,18 +189,19 @@ public:
|
||||
|
||||
// Asynchronously wait for the descriptor to become ready to read, ready to
|
||||
// write, or to have pending error conditions.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_wait(implementation_type& impl,
|
||||
posix::descriptor_base::wait_type w, Handler& handler)
|
||||
posix::descriptor_base::wait_type w,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_wait_op<Handler> op;
|
||||
typedef reactive_wait_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",
|
||||
&impl, impl.descriptor_, "async_wait"));
|
||||
@ -253,18 +253,19 @@ public:
|
||||
|
||||
// Start an asynchronous write. The data being sent must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, Handler& handler)
|
||||
const ConstBufferSequence& buffers, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef descriptor_write_op<ConstBufferSequence, Handler> op;
|
||||
typedef descriptor_write_op<ConstBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.descriptor_, buffers, handler);
|
||||
p.p = new (p.v) op(impl.descriptor_, buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",
|
||||
&impl, impl.descriptor_, "async_write_some"));
|
||||
@ -276,18 +277,18 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous wait until data can be written without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const null_buffers&, Handler& handler)
|
||||
const null_buffers&, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_null_buffers_op<Handler> op;
|
||||
typedef reactive_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",
|
||||
&impl, impl.descriptor_, "async_write_some(null_buffers)"));
|
||||
@ -320,18 +321,20 @@ public:
|
||||
|
||||
// Start an asynchronous read. The buffer for the data being read must be
|
||||
// valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef descriptor_read_op<MutableBufferSequence, Handler> op;
|
||||
typedef descriptor_read_op<MutableBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.descriptor_, buffers, handler);
|
||||
p.p = new (p.v) op(impl.descriptor_, buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",
|
||||
&impl, impl.descriptor_, "async_read_some"));
|
||||
@ -343,18 +346,18 @@ public:
|
||||
}
|
||||
|
||||
// Wait until data can be read without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const null_buffers&, Handler& handler)
|
||||
const null_buffers&, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_null_buffers_op<Handler> op;
|
||||
typedef reactive_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",
|
||||
&impl, impl.descriptor_, "async_read_some(null_buffers)"));
|
||||
|
@ -27,18 +27,19 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class reactive_null_buffers_op : public reactor_op
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op);
|
||||
|
||||
reactive_null_buffers_op(Handler& handler)
|
||||
reactive_null_buffers_op(Handler& handler, const IoExecutor& io_ex)
|
||||
: reactor_op(&reactive_null_buffers_op::do_perform,
|
||||
&reactive_null_buffers_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static status do_perform(reactor_op*)
|
||||
@ -53,7 +54,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -80,6 +81,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include <string>
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/serial_port_base.hpp"
|
||||
#include "asio/detail/descriptor_ops.hpp"
|
||||
#include "asio/detail/reactive_descriptor_service.hpp"
|
||||
@ -35,7 +35,7 @@ namespace detail {
|
||||
|
||||
// Extend reactive_descriptor_service to provide serial port support.
|
||||
class reactive_serial_port_service :
|
||||
public service_base<reactive_serial_port_service>
|
||||
public execution_context_service_base<reactive_serial_port_service>
|
||||
{
|
||||
public:
|
||||
// The native type of a serial port.
|
||||
@ -44,8 +44,7 @@ public:
|
||||
// The implementation type of the serial port.
|
||||
typedef reactive_descriptor_service::implementation_type implementation_type;
|
||||
|
||||
ASIO_DECL reactive_serial_port_service(
|
||||
asio::io_context& io_context);
|
||||
ASIO_DECL reactive_serial_port_service(execution_context& context);
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void shutdown();
|
||||
@ -156,11 +155,12 @@ public:
|
||||
|
||||
// Start an asynchronous write. The data being written must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, Handler& handler)
|
||||
const ConstBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
descriptor_service_.async_write_some(impl, buffers, handler);
|
||||
descriptor_service_.async_write_some(impl, buffers, handler, io_ex);
|
||||
}
|
||||
|
||||
// Read some data. Returns the number of bytes received.
|
||||
@ -173,11 +173,13 @@ public:
|
||||
|
||||
// Start an asynchronous read. The buffer for the data being received must be
|
||||
// valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
descriptor_service_.async_read_some(impl, buffers, handler);
|
||||
descriptor_service_.async_read_some(impl, buffers, handler, io_ex);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -85,7 +85,8 @@ private:
|
||||
std::size_t addrlen_;
|
||||
};
|
||||
|
||||
template <typename Socket, typename Protocol, typename Handler>
|
||||
template <typename Socket, typename Protocol,
|
||||
typename Handler, typename IoExecutor>
|
||||
class reactive_socket_accept_op :
|
||||
public reactive_socket_accept_op_base<Socket, Protocol>
|
||||
{
|
||||
@ -94,12 +95,14 @@ public:
|
||||
|
||||
reactive_socket_accept_op(socket_type socket,
|
||||
socket_ops::state_type state, Socket& peer, const Protocol& protocol,
|
||||
typename Protocol::endpoint* peer_endpoint, Handler& handler)
|
||||
typename Protocol::endpoint* peer_endpoint, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
: reactive_socket_accept_op_base<Socket, Protocol>(socket, state, peer,
|
||||
protocol, peer_endpoint, &reactive_socket_accept_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -109,7 +112,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
// On success, assign new connection to peer socket object.
|
||||
if (owner)
|
||||
@ -140,11 +143,13 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
|
||||
template <typename Protocol, typename Handler>
|
||||
template <typename Protocol, typename PeerIoExecutor,
|
||||
typename Handler, typename IoExecutor>
|
||||
class reactive_socket_move_accept_op :
|
||||
private Protocol::socket,
|
||||
public reactive_socket_accept_op_base<typename Protocol::socket, Protocol>
|
||||
@ -152,16 +157,18 @@ class reactive_socket_move_accept_op :
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op);
|
||||
|
||||
reactive_socket_move_accept_op(io_context& ioc, socket_type socket,
|
||||
socket_ops::state_type state, const Protocol& protocol,
|
||||
typename Protocol::endpoint* peer_endpoint, Handler& handler)
|
||||
: Protocol::socket(ioc),
|
||||
reactive_socket_move_accept_op(const PeerIoExecutor& peer_io_ex,
|
||||
socket_type socket, socket_ops::state_type state,
|
||||
const Protocol& protocol, typename Protocol::endpoint* peer_endpoint,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: Protocol::socket(peer_io_ex),
|
||||
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_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -172,7 +179,7 @@ public:
|
||||
reactive_socket_move_accept_op* o(
|
||||
static_cast<reactive_socket_move_accept_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
// On success, assign new connection to peer socket object.
|
||||
if (owner)
|
||||
@ -205,6 +212,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
@ -54,18 +54,20 @@ private:
|
||||
socket_type socket_;
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class reactive_socket_connect_op : public reactive_socket_connect_op_base
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op);
|
||||
|
||||
reactive_socket_connect_op(socket_type socket, Handler& handler)
|
||||
reactive_socket_connect_op(socket_type socket,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: reactive_socket_connect_op_base(socket,
|
||||
&reactive_socket_connect_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -76,7 +78,7 @@ public:
|
||||
reactive_socket_connect_op* o
|
||||
(static_cast<reactive_socket_connect_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -103,6 +105,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -74,21 +74,22 @@ private:
|
||||
socket_base::message_flags flags_;
|
||||
};
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
|
||||
class reactive_socket_recv_op :
|
||||
public reactive_socket_recv_op_base<MutableBufferSequence>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op);
|
||||
|
||||
reactive_socket_recv_op(socket_type socket,
|
||||
socket_ops::state_type state, const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
reactive_socket_recv_op(socket_type socket, socket_ops::state_type state,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: reactive_socket_recv_op_base<MutableBufferSequence>(socket, state,
|
||||
buffers, flags, &reactive_socket_recv_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -98,7 +99,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -125,6 +126,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -75,7 +75,8 @@ private:
|
||||
socket_base::message_flags flags_;
|
||||
};
|
||||
|
||||
template <typename MutableBufferSequence, typename Endpoint, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Endpoint,
|
||||
typename Handler, typename IoExecutor>
|
||||
class reactive_socket_recvfrom_op :
|
||||
public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>
|
||||
{
|
||||
@ -84,13 +85,15 @@ public:
|
||||
|
||||
reactive_socket_recvfrom_op(socket_type socket, int protocol_type,
|
||||
const MutableBufferSequence& buffers, Endpoint& endpoint,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
socket_base::message_flags flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
: reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>(
|
||||
socket, protocol_type, buffers, endpoint, flags,
|
||||
&reactive_socket_recvfrom_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -101,7 +104,7 @@ public:
|
||||
reactive_socket_recvfrom_op* o(
|
||||
static_cast<reactive_socket_recvfrom_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -128,6 +131,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -70,7 +70,7 @@ private:
|
||||
socket_base::message_flags& out_flags_;
|
||||
};
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
|
||||
class reactive_socket_recvmsg_op :
|
||||
public reactive_socket_recvmsg_op_base<MutableBufferSequence>
|
||||
{
|
||||
@ -79,12 +79,14 @@ public:
|
||||
|
||||
reactive_socket_recvmsg_op(socket_type socket,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
socket_base::message_flags& out_flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
: reactive_socket_recvmsg_op_base<MutableBufferSequence>(socket, buffers,
|
||||
in_flags, out_flags, &reactive_socket_recvmsg_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -95,7 +97,7 @@ public:
|
||||
reactive_socket_recvmsg_op* o(
|
||||
static_cast<reactive_socket_recvmsg_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -122,6 +124,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -73,21 +73,22 @@ private:
|
||||
socket_base::message_flags flags_;
|
||||
};
|
||||
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
class reactive_socket_send_op :
|
||||
public reactive_socket_send_op_base<ConstBufferSequence>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op);
|
||||
|
||||
reactive_socket_send_op(socket_type socket,
|
||||
socket_ops::state_type state, const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
reactive_socket_send_op(socket_type socket, socket_ops::state_type state,
|
||||
const ConstBufferSequence& buffers, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: reactive_socket_send_op_base<ConstBufferSequence>(socket,
|
||||
state, buffers, flags, &reactive_socket_send_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -97,7 +98,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -124,6 +125,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -69,7 +69,8 @@ private:
|
||||
socket_base::message_flags flags_;
|
||||
};
|
||||
|
||||
template <typename ConstBufferSequence, typename Endpoint, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Endpoint,
|
||||
typename Handler, typename IoExecutor>
|
||||
class reactive_socket_sendto_op :
|
||||
public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>
|
||||
{
|
||||
@ -78,12 +79,14 @@ public:
|
||||
|
||||
reactive_socket_sendto_op(socket_type socket,
|
||||
const ConstBufferSequence& buffers, const Endpoint& endpoint,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
socket_base::message_flags flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
: reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>(socket,
|
||||
buffers, endpoint, flags, &reactive_socket_sendto_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -93,7 +96,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -120,6 +123,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
@ -45,7 +45,7 @@ namespace detail {
|
||||
|
||||
template <typename Protocol>
|
||||
class reactive_socket_service :
|
||||
public service_base<reactive_socket_service<Protocol> >,
|
||||
public execution_context_service_base<reactive_socket_service<Protocol> >,
|
||||
public reactive_socket_service_base
|
||||
{
|
||||
public:
|
||||
@ -73,9 +73,10 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
reactive_socket_service(asio::io_context& io_context)
|
||||
: service_base<reactive_socket_service<Protocol> >(io_context),
|
||||
reactive_socket_service_base(io_context)
|
||||
reactive_socket_service(execution_context& context)
|
||||
: execution_context_service_base<
|
||||
reactive_socket_service<Protocol> >(context),
|
||||
reactive_socket_service_base(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -239,21 +240,22 @@ public:
|
||||
|
||||
// Start an asynchronous send. The data being sent must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_send_to(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers,
|
||||
const endpoint_type& destination, socket_base::message_flags flags,
|
||||
Handler& handler)
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_sendto_op<ConstBufferSequence,
|
||||
endpoint_type, Handler> op;
|
||||
endpoint_type, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
|
||||
p.p = new (p.v) op(impl.socket_, buffers,
|
||||
destination, flags, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_send_to"));
|
||||
@ -263,18 +265,19 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous wait until data can be sent without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_send_to(implementation_type& impl, const null_buffers&,
|
||||
const endpoint_type&, socket_base::message_flags, Handler& handler)
|
||||
const endpoint_type&, socket_base::message_flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_null_buffers_op<Handler> op;
|
||||
typedef reactive_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_send_to(null_buffers)"));
|
||||
@ -322,22 +325,24 @@ public:
|
||||
// Start an asynchronous receive. The buffer for the data being received and
|
||||
// the sender_endpoint object must both be valid for the lifetime of the
|
||||
// asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive_from(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
socket_base::message_flags flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_recvfrom_op<MutableBufferSequence,
|
||||
endpoint_type, Handler> op;
|
||||
endpoint_type, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
int protocol = impl.protocol_.type();
|
||||
p.p = new (p.v) op(impl.socket_, protocol,
|
||||
buffers, sender_endpoint, flags, handler);
|
||||
p.p = new (p.v) op(impl.socket_, protocol, buffers,
|
||||
sender_endpoint, flags, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive_from"));
|
||||
@ -350,19 +355,19 @@ public:
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
void async_receive_from(implementation_type& impl,
|
||||
const null_buffers&, endpoint_type& sender_endpoint,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive_from(implementation_type& impl, const null_buffers&,
|
||||
endpoint_type& sender_endpoint, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_null_buffers_op<Handler> op;
|
||||
typedef reactive_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive_from(null_buffers)"));
|
||||
@ -407,49 +412,21 @@ public:
|
||||
return ec;
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
// Accept a new connection.
|
||||
typename Protocol::socket accept(implementation_type& impl,
|
||||
io_context* peer_io_context, endpoint_type* peer_endpoint,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
typename Protocol::socket peer(
|
||||
peer_io_context ? *peer_io_context : io_context_);
|
||||
|
||||
std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
|
||||
socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
|
||||
impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
|
||||
peer_endpoint ? &addr_len : 0, ec));
|
||||
|
||||
// On success, assign new connection to peer socket object.
|
||||
if (new_socket.get() != invalid_socket)
|
||||
{
|
||||
if (peer_endpoint)
|
||||
peer_endpoint->resize(addr_len);
|
||||
peer.assign(impl.protocol_, new_socket.get(), ec);
|
||||
if (!ec)
|
||||
new_socket.release();
|
||||
}
|
||||
|
||||
return peer;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
// Start an asynchronous accept. The peer and peer_endpoint objects must be
|
||||
// valid until the accept's handler is invoked.
|
||||
template <typename Socket, typename Handler>
|
||||
template <typename Socket, typename Handler, typename IoExecutor>
|
||||
void async_accept(implementation_type& impl, Socket& peer,
|
||||
endpoint_type* peer_endpoint, Handler& handler)
|
||||
endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
|
||||
typedef reactive_socket_accept_op<Socket, Protocol, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.socket_, impl.state_, peer,
|
||||
impl.protocol_, peer_endpoint, handler);
|
||||
impl.protocol_, peer_endpoint, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_accept"));
|
||||
@ -461,20 +438,21 @@ public:
|
||||
#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,
|
||||
asio::io_context* peer_io_context,
|
||||
endpoint_type* peer_endpoint, Handler& handler)
|
||||
template <typename PeerIoExecutor, typename Handler, typename IoExecutor>
|
||||
void async_move_accept(implementation_type& impl,
|
||||
const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_move_accept_op<Protocol, Handler> op;
|
||||
typedef reactive_socket_move_accept_op<Protocol,
|
||||
PeerIoExecutor, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(peer_io_context ? *peer_io_context : io_context_,
|
||||
impl.socket_, impl.state_, impl.protocol_, peer_endpoint, handler);
|
||||
p.p = new (p.v) op(peer_io_ex, impl.socket_, impl.state_,
|
||||
impl.protocol_, peer_endpoint, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_accept"));
|
||||
@ -494,18 +472,19 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous connect.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_connect(implementation_type& impl,
|
||||
const endpoint_type& peer_endpoint, Handler& handler)
|
||||
const endpoint_type& peer_endpoint,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_connect_op<Handler> op;
|
||||
typedef reactive_socket_connect_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.socket_, handler);
|
||||
p.p = new (p.v) op(impl.socket_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_connect"));
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
@ -62,8 +62,7 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
ASIO_DECL reactive_socket_service_base(
|
||||
asio::io_context& io_context);
|
||||
ASIO_DECL reactive_socket_service_base(execution_context& context);
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void base_shutdown();
|
||||
@ -193,18 +192,18 @@ public:
|
||||
|
||||
// Asynchronously wait for the socket to become ready to read, ready to
|
||||
// write, or to have pending error conditions.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_wait(base_implementation_type& impl,
|
||||
socket_base::wait_type w, Handler& handler)
|
||||
socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_wait_op<Handler> op;
|
||||
typedef reactive_wait_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_wait"));
|
||||
@ -257,19 +256,21 @@ public:
|
||||
|
||||
// Start an asynchronous send. The data being sent must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_send(base_implementation_type& impl,
|
||||
const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
const ConstBufferSequence& buffers, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
|
||||
typedef reactive_socket_send_op<
|
||||
ConstBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
|
||||
p.p = new (p.v) op(impl.socket_, impl.state_,
|
||||
buffers, flags, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_send"));
|
||||
@ -282,18 +283,18 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous wait until data can be sent without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_send(base_implementation_type& impl, const null_buffers&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_null_buffers_op<Handler> op;
|
||||
typedef reactive_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_send(null_buffers)"));
|
||||
@ -327,19 +328,22 @@ public:
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_recv_op<MutableBufferSequence, Handler> op;
|
||||
typedef reactive_socket_recv_op<
|
||||
MutableBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
|
||||
p.p = new (p.v) op(impl.socket_, impl.state_,
|
||||
buffers, flags, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive"));
|
||||
@ -356,18 +360,19 @@ public:
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
void async_receive(base_implementation_type& impl, const null_buffers&,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive(base_implementation_type& impl,
|
||||
const null_buffers&, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_null_buffers_op<Handler> op;
|
||||
typedef reactive_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive(null_buffers)"));
|
||||
@ -411,19 +416,23 @@ public:
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive_with_flags(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
socket_base::message_flags& out_flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_socket_recvmsg_op<MutableBufferSequence, Handler> op;
|
||||
typedef reactive_socket_recvmsg_op<
|
||||
MutableBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
|
||||
p.p = new (p.v) op(impl.socket_, buffers,
|
||||
in_flags, out_flags, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive_with_flags"));
|
||||
@ -437,19 +446,20 @@ public:
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive_with_flags(base_implementation_type& impl,
|
||||
const null_buffers&, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
socket_base::message_flags& out_flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef reactive_null_buffers_op<Handler> op;
|
||||
typedef reactive_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
|
||||
@ -489,9 +499,6 @@ protected:
|
||||
reactor_op* op, bool is_continuation,
|
||||
const socket_addr_type* addr, size_t addrlen);
|
||||
|
||||
// The io_context that owns this socket service.
|
||||
io_context& io_context_;
|
||||
|
||||
// The selector that performs event demultiplexing for the service.
|
||||
reactor& reactor_;
|
||||
};
|
||||
|
@ -27,18 +27,19 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class reactive_wait_op : public reactor_op
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(reactive_wait_op);
|
||||
|
||||
reactive_wait_op(Handler& handler)
|
||||
reactive_wait_op(Handler& handler, const IoExecutor& io_ex)
|
||||
: reactor_op(&reactive_wait_op::do_perform,
|
||||
&reactive_wait_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static status do_perform(reactor_op*)
|
||||
@ -53,7 +54,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
reactive_wait_op* o(static_cast<reactive_wait_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -80,6 +81,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/ip/basic_resolver_results.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
@ -27,12 +26,18 @@
|
||||
#include "asio/detail/resolve_op.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Protocol, typename Handler>
|
||||
template <typename Protocol, typename Handler, typename IoExecutor>
|
||||
class resolve_endpoint_op : public resolve_op
|
||||
{
|
||||
public:
|
||||
@ -41,15 +46,23 @@ public:
|
||||
typedef typename Protocol::endpoint endpoint_type;
|
||||
typedef asio::ip::basic_resolver_results<Protocol> results_type;
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
|
||||
resolve_endpoint_op(socket_ops::weak_cancel_token_type cancel_token,
|
||||
const endpoint_type& endpoint, io_context_impl& ioc, Handler& handler)
|
||||
const endpoint_type& endpoint, scheduler_impl& sched,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: resolve_op(&resolve_endpoint_op::do_complete),
|
||||
cancel_token_(cancel_token),
|
||||
endpoint_(endpoint),
|
||||
io_context_impl_(ioc),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
scheduler_(sched),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -59,9 +72,9 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
if (owner && owner != &o->io_context_impl_)
|
||||
if (owner && owner != &o->scheduler_)
|
||||
{
|
||||
// The operation is being run on the worker io_context. Time to perform
|
||||
// the resolver operation.
|
||||
@ -75,7 +88,7 @@ public:
|
||||
o->results_ = results_type::create(o->endpoint_, host_name, service_name);
|
||||
|
||||
// Pass operation back to main io_context for completion.
|
||||
o->io_context_impl_.post_deferred_completion(o);
|
||||
o->scheduler_.post_deferred_completion(o);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
else
|
||||
@ -109,8 +122,9 @@ public:
|
||||
private:
|
||||
socket_ops::weak_cancel_token_type cancel_token_;
|
||||
endpoint_type endpoint_;
|
||||
io_context_impl& io_context_impl_;
|
||||
scheduler_impl& scheduler_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
results_type results_;
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/ip/basic_resolver_query.hpp"
|
||||
#include "asio/ip/basic_resolver_results.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
@ -28,12 +27,18 @@
|
||||
#include "asio/detail/resolve_op.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Protocol, typename Handler>
|
||||
template <typename Protocol, typename Handler, typename IoExecutor>
|
||||
class resolve_query_op : public resolve_op
|
||||
{
|
||||
public:
|
||||
@ -42,16 +47,24 @@ public:
|
||||
typedef asio::ip::basic_resolver_query<Protocol> query_type;
|
||||
typedef asio::ip::basic_resolver_results<Protocol> results_type;
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
|
||||
resolve_query_op(socket_ops::weak_cancel_token_type cancel_token,
|
||||
const query_type& query, io_context_impl& ioc, Handler& handler)
|
||||
const query_type& query, scheduler_impl& sched,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: resolve_op(&resolve_query_op::do_complete),
|
||||
cancel_token_(cancel_token),
|
||||
query_(query),
|
||||
io_context_impl_(ioc),
|
||||
scheduler_(sched),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex),
|
||||
addrinfo_(0)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
~resolve_query_op()
|
||||
@ -68,7 +81,7 @@ public:
|
||||
resolve_query_op* o(static_cast<resolve_query_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
|
||||
if (owner && owner != &o->io_context_impl_)
|
||||
if (owner && owner != &o->scheduler_)
|
||||
{
|
||||
// The operation is being run on the worker io_context. Time to perform
|
||||
// the resolver operation.
|
||||
@ -79,7 +92,7 @@ public:
|
||||
o->query_.hints(), &o->addrinfo_, o->ec_);
|
||||
|
||||
// Pass operation back to main io_context for completion.
|
||||
o->io_context_impl_.post_deferred_completion(o);
|
||||
o->scheduler_.post_deferred_completion(o);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
else
|
||||
@ -88,7 +101,7 @@ public:
|
||||
// handler is ready to be delivered.
|
||||
|
||||
// Take ownership of the operation's outstanding work.
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -121,8 +134,9 @@ public:
|
||||
private:
|
||||
socket_ops::weak_cancel_token_type cancel_token_;
|
||||
query_type query_;
|
||||
io_context_impl& io_context_impl_;
|
||||
scheduler_impl& scheduler_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
asio::detail::addrinfo_type* addrinfo_;
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,7 @@ namespace detail {
|
||||
|
||||
template <typename Protocol>
|
||||
class resolver_service :
|
||||
public service_base<resolver_service<Protocol> >,
|
||||
public execution_context_service_base<resolver_service<Protocol> >,
|
||||
public resolver_service_base
|
||||
{
|
||||
public:
|
||||
@ -52,9 +52,9 @@ public:
|
||||
typedef asio::ip::basic_resolver_results<Protocol> results_type;
|
||||
|
||||
// Constructor.
|
||||
resolver_service(asio::io_context& io_context)
|
||||
: service_base<resolver_service<Protocol> >(io_context),
|
||||
resolver_service_base(io_context)
|
||||
resolver_service(execution_context& context)
|
||||
: execution_context_service_base<resolver_service<Protocol> >(context),
|
||||
resolver_service_base(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ public:
|
||||
}
|
||||
|
||||
// Perform any fork-related housekeeping.
|
||||
void notify_fork(asio::io_context::fork_event fork_ev)
|
||||
void notify_fork(execution_context::fork_event fork_ev)
|
||||
{
|
||||
this->base_notify_fork(fork_ev);
|
||||
}
|
||||
@ -85,17 +85,17 @@ public:
|
||||
}
|
||||
|
||||
// Asynchronously resolve a query to a list of entries.
|
||||
template <typename Handler>
|
||||
void async_resolve(implementation_type& impl,
|
||||
const query_type& query, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_resolve(implementation_type& impl, const query_type& query,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef resolve_query_op<Protocol, Handler> op;
|
||||
typedef resolve_query_op<Protocol, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl, query, io_context_impl_, handler);
|
||||
p.p = new (p.v) op(impl, query, scheduler_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_impl_.context(),
|
||||
ASIO_HANDLER_CREATION((scheduler_.context(),
|
||||
*p.p, "resolver", &impl, 0, "async_resolve"));
|
||||
|
||||
start_resolve_op(p.p);
|
||||
@ -117,17 +117,17 @@ public:
|
||||
}
|
||||
|
||||
// Asynchronously resolve an endpoint to a list of entries.
|
||||
template <typename Handler>
|
||||
void async_resolve(implementation_type& impl,
|
||||
const endpoint_type& endpoint, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_resolve(implementation_type& impl, const endpoint_type& endpoint,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef resolve_endpoint_op<Protocol, Handler> op;
|
||||
typedef resolve_endpoint_op<Protocol, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl, endpoint, io_context_impl_, handler);
|
||||
p.p = new (p.v) op(impl, endpoint, scheduler_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_impl_.context(),
|
||||
ASIO_HANDLER_CREATION((scheduler_.context(),
|
||||
*p.p, "resolver", &impl, 0, "async_resolve"));
|
||||
|
||||
start_resolve_op(p.p);
|
||||
|
@ -17,8 +17,7 @@
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/executor_work_guard.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/detail/mutex.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
#include "asio/detail/resolve_op.hpp"
|
||||
@ -27,6 +26,12 @@
|
||||
#include "asio/detail/scoped_ptr.hpp"
|
||||
#include "asio/detail/thread.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
@ -40,7 +45,7 @@ public:
|
||||
typedef socket_ops::shared_cancel_token_type implementation_type;
|
||||
|
||||
// Constructor.
|
||||
ASIO_DECL resolver_service_base(asio::io_context& io_context);
|
||||
ASIO_DECL resolver_service_base(execution_context& context);
|
||||
|
||||
// Destructor.
|
||||
ASIO_DECL ~resolver_service_base();
|
||||
@ -50,7 +55,7 @@ public:
|
||||
|
||||
// Perform any fork-related housekeeping.
|
||||
ASIO_DECL void base_notify_fork(
|
||||
asio::io_context::fork_event fork_ev);
|
||||
execution_context::fork_event fork_ev);
|
||||
|
||||
// Construct a new resolver implementation.
|
||||
ASIO_DECL void construct(implementation_type& impl);
|
||||
@ -101,28 +106,26 @@ protected:
|
||||
};
|
||||
#endif // !defined(ASIO_WINDOWS_RUNTIME)
|
||||
|
||||
// Helper class to run the work io_context in a thread.
|
||||
class work_io_context_runner;
|
||||
// Helper class to run the work scheduler in a thread.
|
||||
class work_scheduler_runner;
|
||||
|
||||
// Start the work thread if it's not already running.
|
||||
// Start the work scheduler if it's not already running.
|
||||
ASIO_DECL void start_work_thread();
|
||||
|
||||
// The io_context implementation used to post completions.
|
||||
io_context_impl& io_context_impl_;
|
||||
// The scheduler implementation used to post completions.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
scheduler_impl& scheduler_;
|
||||
|
||||
private:
|
||||
// Mutex to protect access to internal data.
|
||||
asio::detail::mutex mutex_;
|
||||
|
||||
// Private io_context used for performing asynchronous host resolution.
|
||||
asio::detail::scoped_ptr<asio::io_context> work_io_context_;
|
||||
|
||||
// The work io_context implementation used to post completions.
|
||||
io_context_impl& work_io_context_impl_;
|
||||
|
||||
// Work for the private io_context to perform.
|
||||
asio::executor_work_guard<
|
||||
asio::io_context::executor_type> work_;
|
||||
// Private scheduler used for performing asynchronous host resolution.
|
||||
asio::detail::scoped_ptr<scheduler_impl> work_scheduler_;
|
||||
|
||||
// Thread used for running the work io_context's run loop.
|
||||
asio::detail::scoped_ptr<asio::detail::thread> work_thread_;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "asio/detail/op_queue.hpp"
|
||||
#include "asio/detail/reactor_fwd.hpp"
|
||||
#include "asio/detail/scheduler_operation.hpp"
|
||||
#include "asio/detail/thread.hpp"
|
||||
#include "asio/detail/thread_context.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
@ -44,7 +45,10 @@ public:
|
||||
// Constructor. Specifies the number of concurrent threads that are likely to
|
||||
// run the scheduler. If set to 1 certain optimisation are performed.
|
||||
ASIO_DECL scheduler(asio::execution_context& ctx,
|
||||
int concurrency_hint = 0);
|
||||
int concurrency_hint = 0, bool own_thread = true);
|
||||
|
||||
// Destructor.
|
||||
ASIO_DECL ~scheduler();
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void shutdown();
|
||||
@ -156,6 +160,10 @@ private:
|
||||
ASIO_DECL void wake_one_thread_and_unlock(
|
||||
mutex::scoped_lock& lock);
|
||||
|
||||
// Helper class to run the scheduler in its own thread.
|
||||
class thread_function;
|
||||
friend class thread_function;
|
||||
|
||||
// Helper class to perform task-related operations on block exit.
|
||||
struct task_cleanup;
|
||||
friend struct task_cleanup;
|
||||
@ -199,6 +207,9 @@ private:
|
||||
|
||||
// The concurrency hint used to initialise the scheduler.
|
||||
const int concurrency_hint_;
|
||||
|
||||
// The thread that is running the scheduler.
|
||||
asio::detail::thread* thread_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -29,17 +29,18 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class signal_handler : public signal_op
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(signal_handler);
|
||||
|
||||
signal_handler(Handler& h)
|
||||
signal_handler(Handler& h, const IoExecutor& io_ex)
|
||||
: signal_op(&signal_handler::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(h))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(h)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -49,7 +50,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
signal_handler* h(static_cast<signal_handler*>(base));
|
||||
ptr p = { asio::detail::addressof(h->handler_), h, h };
|
||||
handler_work<Handler> w(h->handler_);
|
||||
handler_work<Handler, IoExecutor> w(h->handler_, h->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*h));
|
||||
|
||||
@ -76,6 +77,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <cstddef>
|
||||
#include <signal.h>
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
#include "asio/detail/op_queue.hpp"
|
||||
@ -28,6 +28,12 @@
|
||||
#include "asio/detail/signal_op.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)
|
||||
# include "asio/detail/reactor.hpp"
|
||||
#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)
|
||||
@ -48,7 +54,7 @@ extern ASIO_DECL struct signal_state* get_signal_state();
|
||||
extern "C" ASIO_DECL void asio_signal_handler(int signal_number);
|
||||
|
||||
class signal_set_service :
|
||||
public service_base<signal_set_service>
|
||||
public execution_context_service_base<signal_set_service>
|
||||
{
|
||||
public:
|
||||
// Type used for tracking an individual signal registration.
|
||||
@ -109,7 +115,7 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
ASIO_DECL signal_set_service(asio::io_context& io_context);
|
||||
ASIO_DECL signal_set_service(execution_context& context);
|
||||
|
||||
// Destructor.
|
||||
ASIO_DECL ~signal_set_service();
|
||||
@ -119,7 +125,7 @@ public:
|
||||
|
||||
// Perform fork-related housekeeping.
|
||||
ASIO_DECL void notify_fork(
|
||||
asio::io_context::fork_event fork_ev);
|
||||
asio::execution_context::fork_event fork_ev);
|
||||
|
||||
// Construct a new signal_set implementation.
|
||||
ASIO_DECL void construct(implementation_type& impl);
|
||||
@ -144,16 +150,17 @@ public:
|
||||
asio::error_code& ec);
|
||||
|
||||
// Start an asynchronous operation to wait for a signal to be delivered.
|
||||
template <typename Handler>
|
||||
void async_wait(implementation_type& impl, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_wait(implementation_type& impl,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef signal_handler<Handler> op;
|
||||
typedef signal_handler<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_.context(),
|
||||
ASIO_HANDLER_CREATION((scheduler_.context(),
|
||||
*p.p, "signal_set", &impl, 0, "async_wait"));
|
||||
|
||||
start_wait_op(impl, p.p);
|
||||
@ -179,8 +186,13 @@ private:
|
||||
// Helper function to start a wait operation.
|
||||
ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op);
|
||||
|
||||
// The io_context instance used for dispatching handlers.
|
||||
io_context_impl& io_context_;
|
||||
// The scheduler used for dispatching handlers.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
scheduler_impl& scheduler_;
|
||||
|
||||
#if !defined(ASIO_WINDOWS) \
|
||||
&& !defined(ASIO_WINDOWS_RUNTIME) \
|
||||
|
@ -64,6 +64,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Test whether the group is empty.
|
||||
bool empty() const
|
||||
{
|
||||
return first_ == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// Structure used to track a single thread in the group.
|
||||
struct item
|
||||
|
@ -19,26 +19,27 @@
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/handler_work.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
#include "asio/detail/wait_op.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class wait_handler : public wait_op
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(wait_handler);
|
||||
|
||||
wait_handler(Handler& h)
|
||||
wait_handler(Handler& h, const IoExecutor& ex)
|
||||
: wait_op(&wait_handler::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(h))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(h)),
|
||||
io_executor_(ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -48,7 +49,7 @@ public:
|
||||
// Take ownership of the handler object.
|
||||
wait_handler* h(static_cast<wait_handler*>(base));
|
||||
ptr p = { asio::detail::addressof(h->handler_), h, h };
|
||||
handler_work<Handler> w(h->handler_);
|
||||
handler_work<Handler, IoExecutor> w(h->handler_, h->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*h));
|
||||
|
||||
@ -75,6 +76,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -34,19 +34,20 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
|
||||
class win_iocp_handle_read_op : public operation
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_read_op);
|
||||
|
||||
win_iocp_handle_read_op(
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
win_iocp_handle_read_op(const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: operation(&win_iocp_handle_read_op::do_complete),
|
||||
buffers_(buffers),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -58,7 +59,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -99,6 +100,7 @@ public:
|
||||
private:
|
||||
MutableBufferSequence buffers_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -21,7 +21,7 @@
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/cstdint.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
@ -38,7 +38,7 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class win_iocp_handle_service :
|
||||
public service_base<win_iocp_handle_service>
|
||||
public execution_context_service_base<win_iocp_handle_service>
|
||||
{
|
||||
public:
|
||||
// The native type of a stream handle.
|
||||
@ -75,7 +75,7 @@ public:
|
||||
implementation_type* prev_;
|
||||
};
|
||||
|
||||
ASIO_DECL win_iocp_handle_service(asio::io_context& io_context);
|
||||
ASIO_DECL win_iocp_handle_service(execution_context& context);
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void shutdown();
|
||||
@ -142,15 +142,17 @@ public:
|
||||
|
||||
// Start an asynchronous write. The data being written must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, Handler& handler)
|
||||
const ConstBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
|
||||
typedef win_iocp_handle_write_op<
|
||||
ConstBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(buffers, handler);
|
||||
p.p = new (p.v) op(buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
|
||||
reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some"));
|
||||
@ -163,15 +165,17 @@ public:
|
||||
|
||||
// Start an asynchronous write at a specified offset. The data being written
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
void async_write_some_at(implementation_type& impl, uint64_t offset,
|
||||
const ConstBufferSequence& buffers, Handler& handler)
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_write_some_at(implementation_type& impl,
|
||||
uint64_t offset, const ConstBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
|
||||
typedef win_iocp_handle_write_op<
|
||||
ConstBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(buffers, handler);
|
||||
p.p = new (p.v) op(buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
|
||||
reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some_at"));
|
||||
@ -204,15 +208,18 @@ public:
|
||||
|
||||
// Start an asynchronous read. The buffer for the data being received must be
|
||||
// valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
|
||||
typedef win_iocp_handle_read_op<
|
||||
MutableBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(buffers, handler);
|
||||
p.p = new (p.v) op(buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
|
||||
reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some"));
|
||||
@ -226,15 +233,18 @@ public:
|
||||
// Start an asynchronous read at a specified offset. The buffer for the data
|
||||
// being received must be valid for the lifetime of the asynchronous
|
||||
// operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
void async_read_some_at(implementation_type& impl, uint64_t offset,
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_read_some_at(implementation_type& impl,
|
||||
uint64_t offset, const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
|
||||
typedef win_iocp_handle_read_op<
|
||||
MutableBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(buffers, handler);
|
||||
p.p = new (p.v) op(buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
|
||||
reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some_at"));
|
||||
@ -251,22 +261,24 @@ private:
|
||||
const null_buffers& buffers, asio::error_code& ec);
|
||||
size_t write_some_at(implementation_type& impl, uint64_t offset,
|
||||
const null_buffers& buffers, asio::error_code& ec);
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const null_buffers& buffers, Handler& handler);
|
||||
template <typename Handler>
|
||||
const null_buffers& buffers, Handler& handler,
|
||||
const IoExecutor& io_ex);
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_write_some_at(implementation_type& impl, uint64_t offset,
|
||||
const null_buffers& buffers, Handler& handler);
|
||||
const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex);
|
||||
size_t read_some(implementation_type& impl,
|
||||
const null_buffers& buffers, asio::error_code& ec);
|
||||
size_t read_some_at(implementation_type& impl, uint64_t offset,
|
||||
const null_buffers& buffers, asio::error_code& ec);
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const null_buffers& buffers, Handler& handler);
|
||||
template <typename Handler>
|
||||
const null_buffers& buffers, Handler& handler,
|
||||
const IoExecutor& io_ex);
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_read_some_at(implementation_type& impl, uint64_t offset,
|
||||
const null_buffers& buffers, Handler& handler);
|
||||
const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex);
|
||||
|
||||
// Helper class for waiting for synchronous operations to complete.
|
||||
class overlapped_wrapper;
|
||||
|
@ -34,18 +34,20 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
class win_iocp_handle_write_op : public operation
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_write_op);
|
||||
|
||||
win_iocp_handle_write_op(const ConstBufferSequence& buffers, Handler& handler)
|
||||
win_iocp_handle_write_op(const ConstBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: operation(&win_iocp_handle_write_op::do_complete),
|
||||
buffers_(buffers),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -54,7 +56,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -91,6 +93,7 @@ public:
|
||||
private:
|
||||
ConstBufferSequence buffers_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -48,7 +48,10 @@ public:
|
||||
// Constructor. Specifies a concurrency hint that is passed through to the
|
||||
// underlying I/O completion port.
|
||||
ASIO_DECL win_iocp_io_context(asio::execution_context& ctx,
|
||||
int concurrency_hint = -1);
|
||||
int concurrency_hint = -1, bool own_thread = true);
|
||||
|
||||
// Destructor.
|
||||
ASIO_DECL ~win_iocp_io_context();
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void shutdown();
|
||||
@ -287,6 +290,10 @@ private:
|
||||
// Timeout to use with GetQueuedCompletionStatus.
|
||||
const DWORD gqcs_timeout_;
|
||||
|
||||
// Helper class to run the scheduler in its own thread.
|
||||
struct thread_function;
|
||||
friend struct thread_function;
|
||||
|
||||
// Function object for processing timeouts in a background thread.
|
||||
struct timer_thread_function;
|
||||
friend struct timer_thread_function;
|
||||
@ -311,6 +318,9 @@ private:
|
||||
|
||||
// The concurrency hint used to initialise the io_context.
|
||||
const int concurrency_hint_;
|
||||
|
||||
// The thread that is running the io_context.
|
||||
scoped_ptr<thread> thread_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -34,20 +34,21 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class win_iocp_null_buffers_op : public reactor_op
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(win_iocp_null_buffers_op);
|
||||
|
||||
win_iocp_null_buffers_op(socket_ops::weak_cancel_token_type cancel_token,
|
||||
Handler& handler)
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: reactor_op(&win_iocp_null_buffers_op::do_perform,
|
||||
&win_iocp_null_buffers_op::do_complete),
|
||||
cancel_token_(cancel_token),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static status do_perform(reactor_op*)
|
||||
@ -64,7 +65,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -109,6 +110,7 @@ public:
|
||||
private:
|
||||
socket_ops::weak_cancel_token_type cancel_token_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include <string>
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/detail/win_iocp_handle_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
@ -32,7 +32,7 @@ namespace detail {
|
||||
|
||||
// Extend win_iocp_handle_service to provide serial port support.
|
||||
class win_iocp_serial_port_service :
|
||||
public service_base<win_iocp_serial_port_service>
|
||||
public execution_context_service_base<win_iocp_serial_port_service>
|
||||
{
|
||||
public:
|
||||
// The native type of a serial port.
|
||||
@ -42,8 +42,7 @@ public:
|
||||
typedef win_iocp_handle_service::implementation_type implementation_type;
|
||||
|
||||
// Constructor.
|
||||
ASIO_DECL win_iocp_serial_port_service(
|
||||
asio::io_context& io_context);
|
||||
ASIO_DECL win_iocp_serial_port_service(execution_context& context);
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void shutdown();
|
||||
@ -151,11 +150,12 @@ public:
|
||||
|
||||
// Start an asynchronous write. The data being written must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_write_some(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, Handler& handler)
|
||||
const ConstBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
handle_service_.async_write_some(impl, buffers, handler);
|
||||
handle_service_.async_write_some(impl, buffers, handler, io_ex);
|
||||
}
|
||||
|
||||
// Read some data. Returns the number of bytes received.
|
||||
@ -168,11 +168,13 @@ public:
|
||||
|
||||
// Start an asynchronous read. The buffer for the data being received must be
|
||||
// valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_read_some(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
handle_service_.async_read_some(impl, buffers, handler);
|
||||
handle_service_.async_read_some(impl, buffers, handler, io_ex);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -35,7 +35,8 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Socket, typename Protocol, typename Handler>
|
||||
template <typename Socket, typename Protocol,
|
||||
typename Handler, typename IoExecutor>
|
||||
class win_iocp_socket_accept_op : public operation
|
||||
{
|
||||
public:
|
||||
@ -44,7 +45,7 @@ public:
|
||||
win_iocp_socket_accept_op(win_iocp_socket_service_base& socket_service,
|
||||
socket_type socket, Socket& peer, const Protocol& protocol,
|
||||
typename Protocol::endpoint* peer_endpoint,
|
||||
bool enable_connection_aborted, Handler& handler)
|
||||
bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex)
|
||||
: operation(&win_iocp_socket_accept_op::do_complete),
|
||||
socket_service_(socket_service),
|
||||
socket_(socket),
|
||||
@ -52,9 +53,10 @@ public:
|
||||
protocol_(protocol),
|
||||
peer_endpoint_(peer_endpoint),
|
||||
enable_connection_aborted_(enable_connection_aborted),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
socket_holder& new_socket()
|
||||
@ -81,7 +83,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
if (owner)
|
||||
{
|
||||
@ -155,11 +157,13 @@ private:
|
||||
unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
|
||||
bool enable_connection_aborted_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
|
||||
template <typename Protocol, typename Handler>
|
||||
template <typename Protocol, typename PeerIoExecutor,
|
||||
typename Handler, typename IoExecutor>
|
||||
class win_iocp_socket_move_accept_op : public operation
|
||||
{
|
||||
public:
|
||||
@ -167,19 +171,20 @@ public:
|
||||
|
||||
win_iocp_socket_move_accept_op(
|
||||
win_iocp_socket_service_base& socket_service, socket_type socket,
|
||||
const Protocol& protocol, asio::io_context& peer_io_context,
|
||||
const Protocol& protocol, const PeerIoExecutor& peer_io_ex,
|
||||
typename Protocol::endpoint* peer_endpoint,
|
||||
bool enable_connection_aborted, Handler& handler)
|
||||
bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex)
|
||||
: operation(&win_iocp_socket_move_accept_op::do_complete),
|
||||
socket_service_(socket_service),
|
||||
socket_(socket),
|
||||
peer_(peer_io_context),
|
||||
peer_(peer_io_ex),
|
||||
protocol_(protocol),
|
||||
peer_endpoint_(peer_endpoint),
|
||||
enable_connection_aborted_(enable_connection_aborted),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
socket_holder& new_socket()
|
||||
@ -207,7 +212,7 @@ public:
|
||||
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_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
if (owner)
|
||||
{
|
||||
@ -283,6 +288,7 @@ private:
|
||||
unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
|
||||
bool enable_connection_aborted_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
@ -56,18 +56,20 @@ public:
|
||||
bool connect_ex_;
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class win_iocp_socket_connect_op : public win_iocp_socket_connect_op_base
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_connect_op);
|
||||
|
||||
win_iocp_socket_connect_op(socket_type socket, Handler& handler)
|
||||
win_iocp_socket_connect_op(socket_type socket,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: win_iocp_socket_connect_op_base(socket,
|
||||
&win_iocp_socket_connect_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -80,7 +82,7 @@ public:
|
||||
win_iocp_socket_connect_op* o(
|
||||
static_cast<win_iocp_socket_connect_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
if (owner)
|
||||
{
|
||||
@ -115,6 +117,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -34,7 +34,7 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
|
||||
class win_iocp_socket_recv_op : public operation
|
||||
{
|
||||
public:
|
||||
@ -42,14 +42,16 @@ public:
|
||||
|
||||
win_iocp_socket_recv_op(socket_ops::state_type state,
|
||||
socket_ops::weak_cancel_token_type cancel_token,
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
const MutableBufferSequence& buffers, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
: operation(&win_iocp_socket_recv_op::do_complete),
|
||||
state_(state),
|
||||
cancel_token_(cancel_token),
|
||||
buffers_(buffers),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -61,7 +63,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -105,6 +107,7 @@ private:
|
||||
socket_ops::weak_cancel_token_type cancel_token_;
|
||||
MutableBufferSequence buffers_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -34,7 +34,8 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename MutableBufferSequence, typename Endpoint, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Endpoint,
|
||||
typename Handler, typename IoExecutor>
|
||||
class win_iocp_socket_recvfrom_op : public operation
|
||||
{
|
||||
public:
|
||||
@ -42,15 +43,17 @@ public:
|
||||
|
||||
win_iocp_socket_recvfrom_op(Endpoint& endpoint,
|
||||
socket_ops::weak_cancel_token_type cancel_token,
|
||||
const MutableBufferSequence& buffers, Handler& handler)
|
||||
const MutableBufferSequence& buffers, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
: operation(&win_iocp_socket_recvfrom_op::do_complete),
|
||||
endpoint_(endpoint),
|
||||
endpoint_size_(static_cast<int>(endpoint.capacity())),
|
||||
cancel_token_(cancel_token),
|
||||
buffers_(buffers),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
int& endpoint_size()
|
||||
@ -68,7 +71,7 @@ public:
|
||||
win_iocp_socket_recvfrom_op* o(
|
||||
static_cast<win_iocp_socket_recvfrom_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -113,6 +116,7 @@ private:
|
||||
socket_ops::weak_cancel_token_type cancel_token_;
|
||||
MutableBufferSequence buffers_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -35,7 +35,7 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
|
||||
class win_iocp_socket_recvmsg_op : public operation
|
||||
{
|
||||
public:
|
||||
@ -44,14 +44,16 @@ public:
|
||||
win_iocp_socket_recvmsg_op(
|
||||
socket_ops::weak_cancel_token_type cancel_token,
|
||||
const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
socket_base::message_flags& out_flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: operation(&win_iocp_socket_recvmsg_op::do_complete),
|
||||
cancel_token_(cancel_token),
|
||||
buffers_(buffers),
|
||||
out_flags_(out_flags),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -64,7 +66,7 @@ public:
|
||||
win_iocp_socket_recvmsg_op* o(
|
||||
static_cast<win_iocp_socket_recvmsg_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -106,6 +108,7 @@ private:
|
||||
MutableBufferSequence buffers_;
|
||||
socket_base::message_flags& out_flags_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -34,20 +34,22 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
class win_iocp_socket_send_op : public operation
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_send_op);
|
||||
|
||||
win_iocp_socket_send_op(socket_ops::weak_cancel_token_type cancel_token,
|
||||
const ConstBufferSequence& buffers, Handler& handler)
|
||||
const ConstBufferSequence& buffers, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
: operation(&win_iocp_socket_send_op::do_complete),
|
||||
cancel_token_(cancel_token),
|
||||
buffers_(buffers),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -59,7 +61,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -99,6 +101,7 @@ private:
|
||||
socket_ops::weak_cancel_token_type cancel_token_;
|
||||
ConstBufferSequence buffers_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include <cstring>
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
@ -51,7 +51,7 @@ namespace detail {
|
||||
|
||||
template <typename Protocol>
|
||||
class win_iocp_socket_service :
|
||||
public service_base<win_iocp_socket_service<Protocol> >,
|
||||
public execution_context_service_base<win_iocp_socket_service<Protocol> >,
|
||||
public win_iocp_socket_service_base
|
||||
{
|
||||
public:
|
||||
@ -129,9 +129,10 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
win_iocp_socket_service(asio::io_context& io_context)
|
||||
: service_base<win_iocp_socket_service<Protocol> >(io_context),
|
||||
win_iocp_socket_service_base(io_context)
|
||||
win_iocp_socket_service(execution_context& context)
|
||||
: execution_context_service_base<
|
||||
win_iocp_socket_service<Protocol> >(context),
|
||||
win_iocp_socket_service_base(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -323,18 +324,20 @@ public:
|
||||
|
||||
// Start an asynchronous send. The data being sent must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_send_to(implementation_type& impl,
|
||||
const ConstBufferSequence& buffers, const endpoint_type& destination,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
socket_base::message_flags flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
|
||||
typedef win_iocp_socket_send_op<
|
||||
ConstBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_send_to"));
|
||||
|
||||
buffer_sequence_adapter<asio::const_buffer,
|
||||
@ -347,17 +350,18 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous wait until data can be sent without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_send_to(implementation_type& impl, const null_buffers&,
|
||||
const endpoint_type&, socket_base::message_flags, Handler& handler)
|
||||
const endpoint_type&, socket_base::message_flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_null_buffers_op<Handler> op;
|
||||
typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_send_to(null_buffers)"));
|
||||
|
||||
start_reactor_op(impl, select_reactor::write_op, p.p);
|
||||
@ -403,19 +407,22 @@ public:
|
||||
// Start an asynchronous receive. The buffer for the data being received and
|
||||
// the sender_endpoint object must both be valid for the lifetime of the
|
||||
// asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive_from(implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, endpoint_type& sender_endp,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
socket_base::message_flags flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_recvfrom_op<
|
||||
MutableBufferSequence, endpoint_type, Handler> op;
|
||||
typedef win_iocp_socket_recvfrom_op<MutableBufferSequence,
|
||||
endpoint_type, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(sender_endp, impl.cancel_token_, buffers, handler);
|
||||
p.p = new (p.v) op(sender_endp, impl.cancel_token_,
|
||||
buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive_from"));
|
||||
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
@ -427,18 +434,18 @@ public:
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
void async_receive_from(implementation_type& impl,
|
||||
const null_buffers&, endpoint_type& sender_endpoint,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive_from(implementation_type& impl, const null_buffers&,
|
||||
endpoint_type& sender_endpoint, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_null_buffers_op<Handler> op;
|
||||
typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive_from(null_buffers)"));
|
||||
|
||||
// Reset endpoint since it can be given no sensible value at this time.
|
||||
@ -478,50 +485,23 @@ public:
|
||||
return ec;
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
// Accept a new connection.
|
||||
typename Protocol::socket accept(implementation_type& impl,
|
||||
io_context* peer_io_context, endpoint_type* peer_endpoint,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
typename Protocol::socket peer(
|
||||
peer_io_context ? *peer_io_context : io_context_);
|
||||
|
||||
std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
|
||||
socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
|
||||
impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
|
||||
peer_endpoint ? &addr_len : 0, ec));
|
||||
|
||||
// On success, assign new connection to peer socket object.
|
||||
if (new_socket.get() != invalid_socket)
|
||||
{
|
||||
if (peer_endpoint)
|
||||
peer_endpoint->resize(addr_len);
|
||||
peer.assign(impl.protocol_, new_socket.get(), ec);
|
||||
if (!ec)
|
||||
new_socket.release();
|
||||
}
|
||||
|
||||
return peer;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
// Start an asynchronous accept. The peer and peer_endpoint objects
|
||||
// must be valid until the accept's handler is invoked.
|
||||
template <typename Socket, typename Handler>
|
||||
template <typename Socket, typename Handler, typename IoExecutor>
|
||||
void async_accept(implementation_type& impl, Socket& peer,
|
||||
endpoint_type* peer_endpoint, Handler& handler)
|
||||
endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_accept_op<Socket, protocol_type, Handler> op;
|
||||
typedef win_iocp_socket_accept_op<Socket,
|
||||
protocol_type, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
bool enable_connection_aborted =
|
||||
(impl.state_ & socket_ops::enable_connection_aborted) != 0;
|
||||
p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,
|
||||
peer_endpoint, enable_connection_aborted, handler);
|
||||
peer_endpoint, enable_connection_aborted, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_accept"));
|
||||
|
||||
start_accept_op(impl, peer.is_open(), p.p->new_socket(),
|
||||
@ -534,22 +514,23 @@ public:
|
||||
#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_context* peer_io_context,
|
||||
endpoint_type* peer_endpoint, Handler& handler)
|
||||
template <typename PeerIoExecutor, typename Handler, typename IoExecutor>
|
||||
void async_move_accept(implementation_type& impl,
|
||||
const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_move_accept_op<protocol_type, Handler> op;
|
||||
typedef win_iocp_socket_move_accept_op<
|
||||
protocol_type, PeerIoExecutor, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
bool enable_connection_aborted =
|
||||
(impl.state_ & socket_ops::enable_connection_aborted) != 0;
|
||||
p.p = new (p.v) op(*this, impl.socket_, impl.protocol_,
|
||||
peer_io_context ? *peer_io_context : io_context_,
|
||||
peer_endpoint, enable_connection_aborted, handler);
|
||||
peer_io_ex, peer_endpoint, enable_connection_aborted,
|
||||
handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_accept"));
|
||||
|
||||
start_accept_op(impl, false, p.p->new_socket(),
|
||||
@ -570,17 +551,18 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous connect.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_connect(implementation_type& impl,
|
||||
const endpoint_type& peer_endpoint, Handler& handler)
|
||||
const endpoint_type& peer_endpoint, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_connect_op<Handler> op;
|
||||
typedef win_iocp_socket_connect_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.socket_, handler);
|
||||
p.p = new (p.v) op(impl.socket_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_connect"));
|
||||
|
||||
start_connect_op(impl, impl.protocol_.family(), impl.protocol_.type(),
|
||||
|
@ -20,7 +20,7 @@
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
@ -85,8 +85,7 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
ASIO_DECL win_iocp_socket_service_base(
|
||||
asio::io_context& io_context);
|
||||
ASIO_DECL win_iocp_socket_service_base(execution_context& context);
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void base_shutdown();
|
||||
@ -210,20 +209,20 @@ public:
|
||||
|
||||
// Asynchronously wait for the socket to become ready to read, ready to
|
||||
// write, or to have pending error conditions.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_wait(base_implementation_type& impl,
|
||||
socket_base::wait_type w, Handler& handler)
|
||||
socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_wait_op<Handler> op;
|
||||
typedef win_iocp_wait_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_wait"));
|
||||
|
||||
switch (w)
|
||||
@ -271,18 +270,19 @@ public:
|
||||
|
||||
// Start an asynchronous send. The data being sent must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_send(base_implementation_type& impl,
|
||||
const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
const ConstBufferSequence& buffers, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
|
||||
typedef win_iocp_socket_send_op<
|
||||
ConstBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_send"));
|
||||
|
||||
buffer_sequence_adapter<asio::const_buffer,
|
||||
@ -295,17 +295,17 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous wait until data can be sent without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_send(base_implementation_type& impl, const null_buffers&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_null_buffers_op<Handler> op;
|
||||
typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_send(null_buffers)"));
|
||||
|
||||
start_reactor_op(impl, select_reactor::write_op, p.p);
|
||||
@ -337,18 +337,21 @@ public:
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_recv_op<MutableBufferSequence, Handler> op;
|
||||
typedef win_iocp_socket_recv_op<
|
||||
MutableBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.state_, impl.cancel_token_, buffers, handler);
|
||||
p.p = new (p.v) op(impl.state_, impl.cancel_token_,
|
||||
buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive"));
|
||||
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
@ -361,17 +364,18 @@ public:
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
void async_receive(base_implementation_type& impl, const null_buffers&,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive(base_implementation_type& impl,
|
||||
const null_buffers&, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_null_buffers_op<Handler> op;
|
||||
typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive(null_buffers)"));
|
||||
|
||||
start_null_buffers_receive_op(impl, flags, p.p);
|
||||
@ -410,18 +414,22 @@ public:
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive_with_flags(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
socket_base::message_flags& out_flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_socket_recvmsg_op<MutableBufferSequence, Handler> op;
|
||||
typedef win_iocp_socket_recvmsg_op<
|
||||
MutableBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, buffers, out_flags, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_,
|
||||
buffers, out_flags, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive_with_flags"));
|
||||
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
@ -432,18 +440,19 @@ public:
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive_with_flags(base_implementation_type& impl,
|
||||
const null_buffers&, socket_base::message_flags in_flags,
|
||||
socket_base::message_flags& out_flags, Handler& handler)
|
||||
socket_base::message_flags& out_flags, Handler& handler,
|
||||
const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef win_iocp_null_buffers_op<Handler> op;
|
||||
typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler);
|
||||
p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
|
||||
ASIO_HANDLER_CREATION((context_, *p.p, "socket",
|
||||
&impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
|
||||
|
||||
// Reset out_flags since it can be given no sensible value at this time.
|
||||
@ -518,8 +527,8 @@ protected:
|
||||
base_implementation_type& impl);
|
||||
|
||||
// Helper function to get the reactor. If no reactor has been created yet, a
|
||||
// new one is obtained from the io_context and a pointer to it is cached in
|
||||
// this service.
|
||||
// new one is obtained from the execution context and a pointer to it is
|
||||
// cached in this service.
|
||||
ASIO_DECL select_reactor& get_reactor();
|
||||
|
||||
// The type of a ConnectEx function pointer, as old SDKs may not provide it.
|
||||
@ -553,8 +562,8 @@ protected:
|
||||
// - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
|
||||
ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);
|
||||
|
||||
// The io_context used to obtain the reactor, if required.
|
||||
asio::io_context& io_context_;
|
||||
// The execution context used to obtain the reactor, if required.
|
||||
execution_context& context_;
|
||||
|
||||
// The IOCP service used for running asynchronous operations and dispatching
|
||||
// handlers.
|
||||
|
@ -34,20 +34,21 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class win_iocp_wait_op : public reactor_op
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(win_iocp_wait_op);
|
||||
|
||||
win_iocp_wait_op(socket_ops::weak_cancel_token_type cancel_token,
|
||||
Handler& handler)
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: reactor_op(&win_iocp_wait_op::do_perform,
|
||||
&win_iocp_wait_op::do_complete),
|
||||
cancel_token_(cancel_token),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static status do_perform(reactor_op*)
|
||||
@ -64,7 +65,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
win_iocp_wait_op* o(static_cast<win_iocp_wait_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -109,6 +110,7 @@ public:
|
||||
private:
|
||||
socket_ops::weak_cancel_token_type cancel_token_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -24,7 +24,13 @@
|
||||
#include "asio/detail/memory.hpp"
|
||||
#include "asio/detail/wait_handler.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
@ -32,7 +38,7 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class win_object_handle_service :
|
||||
public service_base<win_object_handle_service>
|
||||
public execution_context_service_base<win_object_handle_service>
|
||||
{
|
||||
public:
|
||||
// The native type of an object handle.
|
||||
@ -79,8 +85,7 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
ASIO_DECL win_object_handle_service(
|
||||
asio::io_context& io_context);
|
||||
ASIO_DECL win_object_handle_service(execution_context& context);
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void shutdown();
|
||||
@ -129,16 +134,17 @@ public:
|
||||
asio::error_code& ec);
|
||||
|
||||
/// Start an asynchronous wait.
|
||||
template <typename Handler>
|
||||
void async_wait(implementation_type& impl, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_wait(implementation_type& impl,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef wait_handler<Handler> op;
|
||||
typedef wait_handler<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_.context(), *p.p, "object_handle",
|
||||
ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "object_handle",
|
||||
&impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "async_wait"));
|
||||
|
||||
start_wait_op(impl, p.p);
|
||||
@ -157,8 +163,13 @@ private:
|
||||
static ASIO_DECL VOID CALLBACK wait_callback(
|
||||
PVOID param, BOOLEAN timeout);
|
||||
|
||||
// The io_context implementation used to post completions.
|
||||
io_context_impl& io_context_;
|
||||
// The scheduler used to post completions.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
scheduler_impl& scheduler_;
|
||||
|
||||
// Mutex to protect access to internal state.
|
||||
mutex mutex_;
|
||||
|
@ -23,7 +23,13 @@
|
||||
#include "asio/detail/atomic_count.hpp"
|
||||
#include "asio/detail/winrt_async_op.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
@ -31,13 +37,13 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class winrt_async_manager
|
||||
: public asio::detail::service_base<winrt_async_manager>
|
||||
: public execution_context_service_base<winrt_async_manager>
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
winrt_async_manager(asio::io_context& io_context)
|
||||
: asio::detail::service_base<winrt_async_manager>(io_context),
|
||||
io_context_(use_service<io_context_impl>(io_context)),
|
||||
winrt_async_manager(execution_context& context)
|
||||
: execution_context_service_base<winrt_async_manager>(context),
|
||||
scheduler_(use_service<scheduler_impl>(context)),
|
||||
outstanding_ops_(1)
|
||||
{
|
||||
}
|
||||
@ -185,12 +191,12 @@ public:
|
||||
asio::system_category());
|
||||
break;
|
||||
}
|
||||
io_context_.post_deferred_completion(handler);
|
||||
scheduler_.post_deferred_completion(handler);
|
||||
if (--outstanding_ops_ == 0)
|
||||
promise_.set_value();
|
||||
});
|
||||
|
||||
io_context_.work_started();
|
||||
scheduler_.work_started();
|
||||
++outstanding_ops_;
|
||||
action->Completed = on_completed;
|
||||
}
|
||||
@ -222,12 +228,12 @@ public:
|
||||
asio::system_category());
|
||||
break;
|
||||
}
|
||||
io_context_.post_deferred_completion(handler);
|
||||
scheduler_.post_deferred_completion(handler);
|
||||
if (--outstanding_ops_ == 0)
|
||||
promise_.set_value();
|
||||
});
|
||||
|
||||
io_context_.work_started();
|
||||
scheduler_.work_started();
|
||||
++outstanding_ops_;
|
||||
operation->Completed = on_completed;
|
||||
}
|
||||
@ -263,19 +269,24 @@ public:
|
||||
asio::system_category());
|
||||
break;
|
||||
}
|
||||
io_context_.post_deferred_completion(handler);
|
||||
scheduler_.post_deferred_completion(handler);
|
||||
if (--outstanding_ops_ == 0)
|
||||
promise_.set_value();
|
||||
});
|
||||
|
||||
io_context_.work_started();
|
||||
scheduler_.work_started();
|
||||
++outstanding_ops_;
|
||||
operation->Completed = on_completed;
|
||||
}
|
||||
|
||||
private:
|
||||
// The io_context implementation used to post completed handlers.
|
||||
io_context_impl& io_context_;
|
||||
// The scheduler implementation used to post completed handlers.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
scheduler_impl& scheduler_;
|
||||
|
||||
// Count of outstanding operations.
|
||||
atomic_count outstanding_ops_;
|
||||
|
@ -33,7 +33,7 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Protocol, typename Handler>
|
||||
template <typename Protocol, typename Handler, typename IoExecutor>
|
||||
class winrt_resolve_op :
|
||||
public winrt_async_op<
|
||||
Windows::Foundation::Collections::IVectorView<
|
||||
@ -46,15 +46,17 @@ public:
|
||||
typedef asio::ip::basic_resolver_query<Protocol> query_type;
|
||||
typedef asio::ip::basic_resolver_results<Protocol> results_type;
|
||||
|
||||
winrt_resolve_op(const query_type& query, Handler& handler)
|
||||
winrt_resolve_op(const query_type& query,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: winrt_async_op<
|
||||
Windows::Foundation::Collections::IVectorView<
|
||||
Windows::Networking::EndpointPair^>^>(
|
||||
&winrt_resolve_op::do_complete),
|
||||
query_(query),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -63,7 +65,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
winrt_resolve_op* o(static_cast<winrt_resolve_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -106,6 +108,7 @@ public:
|
||||
private:
|
||||
query_type query_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "asio/ip/basic_resolver_query.hpp"
|
||||
#include "asio/ip/basic_resolver_results.hpp"
|
||||
#include "asio/post.hpp"
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
@ -28,6 +29,12 @@
|
||||
#include "asio/detail/winrt_resolve_op.hpp"
|
||||
#include "asio/detail/winrt_utils.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
@ -35,7 +42,7 @@ namespace detail {
|
||||
|
||||
template <typename Protocol>
|
||||
class winrt_resolver_service :
|
||||
public service_base<winrt_resolver_service<Protocol> >
|
||||
public execution_context_service_base<winrt_resolver_service<Protocol> >
|
||||
{
|
||||
public:
|
||||
// The implementation type of the resolver. A cancellation token is used to
|
||||
@ -53,10 +60,11 @@ public:
|
||||
typedef asio::ip::basic_resolver_results<Protocol> results_type;
|
||||
|
||||
// Constructor.
|
||||
winrt_resolver_service(asio::io_context& io_context)
|
||||
: service_base<winrt_resolver_service<Protocol> >(io_context),
|
||||
io_context_(use_service<io_context_impl>(io_context)),
|
||||
async_manager_(use_service<winrt_async_manager>(io_context))
|
||||
winrt_resolver_service(execution_context& context)
|
||||
: execution_context_service_base<
|
||||
winrt_resolver_service<Protocol> >(context),
|
||||
scheduler_(use_service<scheduler_impl>(context)),
|
||||
async_manager_(use_service<winrt_async_manager>(context))
|
||||
{
|
||||
}
|
||||
|
||||
@ -71,7 +79,7 @@ public:
|
||||
}
|
||||
|
||||
// Perform any fork-related housekeeping.
|
||||
void notify_fork(asio::io_context::fork_event)
|
||||
void notify_fork(execution_context::fork_event)
|
||||
{
|
||||
}
|
||||
|
||||
@ -130,20 +138,20 @@ public:
|
||||
}
|
||||
|
||||
// Asynchronously resolve a query to a list of entries.
|
||||
template <typename Handler>
|
||||
void async_resolve(implementation_type& impl,
|
||||
const query_type& query, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_resolve(implementation_type& impl, const query_type& query,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef winrt_resolve_op<Protocol, Handler> op;
|
||||
typedef winrt_resolve_op<Protocol, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(query, handler);
|
||||
p.p = new (p.v) op(query, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_.context(),
|
||||
ASIO_HANDLER_CREATION((scheduler_.context(),
|
||||
*p.p, "resolver", &impl, 0, "async_resolve"));
|
||||
(void)impl;
|
||||
|
||||
@ -159,7 +167,7 @@ public:
|
||||
{
|
||||
p.p->ec_ = asio::error_code(
|
||||
e->HResult, asio::system_category());
|
||||
io_context_.post_immediate_completion(p.p, is_continuation);
|
||||
scheduler_.post_immediate_completion(p.p, is_continuation);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
}
|
||||
@ -173,18 +181,24 @@ public:
|
||||
}
|
||||
|
||||
// Asynchronously resolve an endpoint to a list of entries.
|
||||
template <typename Handler>
|
||||
void async_resolve(implementation_type&,
|
||||
const endpoint_type&, Handler& handler)
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_resolve(implementation_type&, const endpoint_type&,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const results_type results;
|
||||
io_context_.get_io_context().post(
|
||||
detail::bind_handler(handler, ec, results));
|
||||
asio::post(io_ex, detail::bind_handler(handler, ec, results));
|
||||
}
|
||||
|
||||
private:
|
||||
io_context_impl& io_context_;
|
||||
// The scheduler implementation used for delivering completions.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
scheduler_impl& scheduler_;
|
||||
|
||||
winrt_async_manager& async_manager_;
|
||||
};
|
||||
|
||||
|
@ -33,18 +33,19 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
class winrt_socket_connect_op :
|
||||
public winrt_async_op<void>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(winrt_socket_connect_op);
|
||||
|
||||
winrt_socket_connect_op(Handler& handler)
|
||||
winrt_socket_connect_op(Handler& handler, const IoExecutor& io_ex)
|
||||
: winrt_async_op<void>(&winrt_socket_connect_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -53,7 +54,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
winrt_socket_connect_op* o(static_cast<winrt_socket_connect_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -80,6 +81,7 @@ public:
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -33,20 +33,22 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
|
||||
class winrt_socket_recv_op :
|
||||
public winrt_async_op<Windows::Storage::Streams::IBuffer^>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(winrt_socket_recv_op);
|
||||
|
||||
winrt_socket_recv_op(const MutableBufferSequence& buffers, Handler& handler)
|
||||
winrt_socket_recv_op(const MutableBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: winrt_async_op<Windows::Storage::Streams::IBuffer^>(
|
||||
&winrt_socket_recv_op::do_complete),
|
||||
buffers_(buffers),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -55,7 +57,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
winrt_socket_recv_op* o(static_cast<winrt_socket_recv_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -100,6 +102,7 @@ public:
|
||||
private:
|
||||
MutableBufferSequence buffers_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -33,19 +33,21 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
class winrt_socket_send_op :
|
||||
public winrt_async_op<unsigned int>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(winrt_socket_send_op);
|
||||
|
||||
winrt_socket_send_op(const ConstBufferSequence& buffers, Handler& handler)
|
||||
winrt_socket_send_op(const ConstBufferSequence& buffers,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
: winrt_async_op<unsigned int>(&winrt_socket_send_op::do_complete),
|
||||
buffers_(buffers),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler))
|
||||
handler_(ASIO_MOVE_CAST(Handler)(handler)),
|
||||
io_executor_(io_ex)
|
||||
{
|
||||
handler_work<Handler>::start(handler_);
|
||||
handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
|
||||
}
|
||||
|
||||
static void do_complete(void* owner, operation* base,
|
||||
@ -54,7 +56,7 @@ public:
|
||||
// Take ownership of the operation object.
|
||||
winrt_socket_send_op* o(static_cast<winrt_socket_send_op*>(base));
|
||||
ptr p = { asio::detail::addressof(o->handler_), o, o };
|
||||
handler_work<Handler> w(o->handler_);
|
||||
handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
@ -91,6 +93,7 @@ public:
|
||||
private:
|
||||
ConstBufferSequence buffers_;
|
||||
Handler handler_;
|
||||
IoExecutor io_executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -20,7 +20,7 @@
|
||||
#if defined(ASIO_WINDOWS_RUNTIME)
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
#include "asio/detail/winrt_socket_connect_op.hpp"
|
||||
#include "asio/detail/winrt_ssocket_service_base.hpp"
|
||||
@ -33,7 +33,7 @@ namespace detail {
|
||||
|
||||
template <typename Protocol>
|
||||
class winrt_ssocket_service :
|
||||
public service_base<winrt_ssocket_service<Protocol> >,
|
||||
public execution_context_service_base<winrt_ssocket_service<Protocol> >,
|
||||
public winrt_ssocket_service_base
|
||||
{
|
||||
public:
|
||||
@ -61,9 +61,9 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
winrt_ssocket_service(asio::io_context& io_context)
|
||||
: service_base<winrt_ssocket_service<Protocol> >(io_context),
|
||||
winrt_ssocket_service_base(io_context)
|
||||
winrt_ssocket_service(execution_context& context)
|
||||
: execution_context_service_base<winrt_ssocket_service<Protocol> >(context),
|
||||
winrt_ssocket_service_base(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -210,20 +210,21 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous connect.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_connect(implementation_type& impl,
|
||||
const endpoint_type& peer_endpoint, Handler& handler)
|
||||
const endpoint_type& peer_endpoint,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef winrt_socket_connect_op<Handler> op;
|
||||
typedef winrt_socket_connect_op<Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
p.p = new (p.v) op(handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_.context(),
|
||||
ASIO_HANDLER_CREATION((scheduler_.context(),
|
||||
*p.p, "socket", &impl, 0, "async_connect"));
|
||||
|
||||
start_connect_op(impl, peer_endpoint.data(), p.p, is_continuation);
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/socket_base.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
@ -30,6 +30,12 @@
|
||||
#include "asio/detail/winrt_socket_recv_op.hpp"
|
||||
#include "asio/detail/winrt_socket_send_op.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
@ -61,8 +67,7 @@ public:
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
ASIO_DECL winrt_ssocket_service_base(
|
||||
asio::io_context& io_context);
|
||||
ASIO_DECL winrt_ssocket_service_base(execution_context& context);
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
ASIO_DECL void base_shutdown();
|
||||
@ -192,21 +197,21 @@ public:
|
||||
|
||||
// Start an asynchronous send. The data being sent must be valid for the
|
||||
// lifetime of the asynchronous operation.
|
||||
template <typename ConstBufferSequence, typename Handler>
|
||||
template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
|
||||
void async_send(base_implementation_type& impl,
|
||||
const ConstBufferSequence& buffers,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
const ConstBufferSequence& buffers, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef winrt_socket_send_op<ConstBufferSequence, Handler> op;
|
||||
typedef winrt_socket_send_op<ConstBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(buffers, handler);
|
||||
p.p = new (p.v) op(buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_.context(),
|
||||
ASIO_HANDLER_CREATION((scheduler_.context(),
|
||||
*p.p, "socket", &impl, 0, "async_send"));
|
||||
|
||||
start_send_op(impl,
|
||||
@ -217,13 +222,13 @@ public:
|
||||
}
|
||||
|
||||
// Start an asynchronous wait until data can be sent without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_send(base_implementation_type&, const null_buffers&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.get_io_context().post(
|
||||
asio::post(io_ex,
|
||||
detail::bind_handler(handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
@ -248,21 +253,22 @@ public:
|
||||
|
||||
// Start an asynchronous receive. The buffer for the data being received
|
||||
// must be valid for the lifetime of the asynchronous operation.
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
template <typename MutableBufferSequence,
|
||||
typename Handler, typename IoExecutor>
|
||||
void async_receive(base_implementation_type& impl,
|
||||
const MutableBufferSequence& buffers,
|
||||
socket_base::message_flags flags, Handler& handler)
|
||||
const MutableBufferSequence& buffers, socket_base::message_flags flags,
|
||||
Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
bool is_continuation =
|
||||
asio_handler_cont_helpers::is_continuation(handler);
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef winrt_socket_recv_op<MutableBufferSequence, Handler> op;
|
||||
typedef winrt_socket_recv_op<MutableBufferSequence, Handler, IoExecutor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(buffers, handler);
|
||||
p.p = new (p.v) op(buffers, handler, io_ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((io_context_.context(),
|
||||
ASIO_HANDLER_CREATION((scheduler_.context(),
|
||||
*p.p, "socket", &impl, 0, "async_receive"));
|
||||
|
||||
start_receive_op(impl,
|
||||
@ -273,13 +279,13 @@ public:
|
||||
}
|
||||
|
||||
// Wait until data can be received without blocking.
|
||||
template <typename Handler>
|
||||
template <typename Handler, typename IoExecutor>
|
||||
void async_receive(base_implementation_type&, const null_buffers&,
|
||||
socket_base::message_flags, Handler& handler)
|
||||
socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
const std::size_t bytes_transferred = 0;
|
||||
io_context_.get_io_context().post(
|
||||
asio::post(io_ex,
|
||||
detail::bind_handler(handler, ec, bytes_transferred));
|
||||
}
|
||||
|
||||
@ -332,8 +338,13 @@ protected:
|
||||
winrt_async_op<Windows::Storage::Streams::IBuffer^>* op,
|
||||
bool is_continuation);
|
||||
|
||||
// The io_context implementation used for delivering completions.
|
||||
io_context_impl& io_context_;
|
||||
// The scheduler implementation used for delivering completions.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
scheduler_impl& scheduler_;
|
||||
|
||||
// The manager that keeps track of outstanding operations.
|
||||
winrt_async_manager& async_manager_;
|
||||
|
@ -28,7 +28,13 @@
|
||||
#include "asio/detail/timer_queue_base.hpp"
|
||||
#include "asio/detail/timer_queue_set.hpp"
|
||||
#include "asio/detail/wait_op.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/win_iocp_io_context.hpp"
|
||||
#else // defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/scheduler.hpp"
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
# include "asio/detail/thread.hpp"
|
||||
@ -40,11 +46,11 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class winrt_timer_scheduler
|
||||
: public asio::detail::service_base<winrt_timer_scheduler>
|
||||
: public execution_context_service_base<winrt_timer_scheduler>
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
ASIO_DECL winrt_timer_scheduler(asio::io_context& io_context);
|
||||
ASIO_DECL winrt_timer_scheduler(execution_context& context);
|
||||
|
||||
// Destructor.
|
||||
ASIO_DECL ~winrt_timer_scheduler();
|
||||
@ -53,8 +59,7 @@ public:
|
||||
ASIO_DECL void shutdown();
|
||||
|
||||
// Recreate internal descriptors following a fork.
|
||||
ASIO_DECL void notify_fork(
|
||||
asio::io_context::fork_event fork_ev);
|
||||
ASIO_DECL void notify_fork(execution_context::fork_event fork_ev);
|
||||
|
||||
// Initialise the task. No effect as this class uses its own thread.
|
||||
ASIO_DECL void init_task();
|
||||
@ -100,8 +105,13 @@ private:
|
||||
// Helper function to remove a timer queue.
|
||||
ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
|
||||
|
||||
// The io_context implementation used to post completions.
|
||||
io_context_impl& io_context_;
|
||||
// The scheduler implementation used to post completions.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef class win_iocp_io_context scheduler_impl;
|
||||
#else
|
||||
typedef class scheduler scheduler_impl;
|
||||
#endif
|
||||
scheduler_impl& scheduler_;
|
||||
|
||||
// Mutex used to protect internal variables.
|
||||
asio::detail::mutex mutex_;
|
||||
|
@ -109,13 +109,14 @@ public:
|
||||
class id;
|
||||
class service;
|
||||
|
||||
protected:
|
||||
public:
|
||||
/// Constructor.
|
||||
ASIO_DECL execution_context();
|
||||
|
||||
/// Destructor.
|
||||
ASIO_DECL ~execution_context();
|
||||
|
||||
protected:
|
||||
/// Shuts down all services in the context.
|
||||
/**
|
||||
* This function is implemented as follows:
|
||||
|
@ -100,8 +100,8 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Protocol, typename EndpointSequence>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type*)
|
||||
@ -112,8 +112,8 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Protocol, typename EndpointSequence>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints, asio::error_code& ec,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type*)
|
||||
@ -124,8 +124,8 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
}
|
||||
|
||||
#if !defined(ASIO_NO_DEPRECATED)
|
||||
template <typename Protocol, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
template <typename Protocol, typename Executor, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
|
||||
{
|
||||
asio::error_code ec;
|
||||
@ -134,8 +134,8 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Protocol, typename Iterator>
|
||||
inline Iterator connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor, typename Iterator>
|
||||
inline Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, asio::error_code& ec,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
|
||||
{
|
||||
@ -143,8 +143,9 @@ inline Iterator connect(basic_socket<Protocol>& s,
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
template <typename Protocol, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end)
|
||||
template <typename Protocol, typename Executor, typename Iterator>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, Iterator end)
|
||||
{
|
||||
asio::error_code ec;
|
||||
Iterator result = connect(s, begin, end, ec);
|
||||
@ -152,16 +153,16 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end)
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Protocol, typename Iterator>
|
||||
inline Iterator connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor, typename Iterator>
|
||||
inline Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, Iterator end, asio::error_code& ec)
|
||||
{
|
||||
return connect(s, begin, end, detail::default_connect_condition(), ec);
|
||||
}
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
typename ConnectCondition>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename EndpointSequence, typename ConnectCondition>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints, ConnectCondition connect_condition,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type*)
|
||||
@ -173,9 +174,9 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
typename ConnectCondition>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename EndpointSequence, typename ConnectCondition>
|
||||
typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints, ConnectCondition connect_condition,
|
||||
asio::error_code& ec,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
@ -187,8 +188,9 @@ typename Protocol::endpoint connect(basic_socket<Protocol>& s,
|
||||
}
|
||||
|
||||
#if !defined(ASIO_NO_DEPRECATED)
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, ConnectCondition connect_condition,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
|
||||
{
|
||||
@ -198,8 +200,9 @@ Iterator connect(basic_socket<Protocol>& s,
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition>
|
||||
inline Iterator connect(basic_socket<Protocol>& s,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename ConnectCondition>
|
||||
inline Iterator connect(basic_socket<Protocol, Executor>& s,
|
||||
Iterator begin, ConnectCondition connect_condition,
|
||||
asio::error_code& ec,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
|
||||
@ -208,8 +211,9 @@ inline Iterator connect(basic_socket<Protocol>& s,
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
Iterator end, ConnectCondition connect_condition)
|
||||
{
|
||||
asio::error_code ec;
|
||||
@ -218,9 +222,11 @@ Iterator connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
ConnectCondition connect_condition, asio::error_code& ec)
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename ConnectCondition>
|
||||
Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
Iterator end, ConnectCondition connect_condition,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
|
||||
@ -284,12 +290,12 @@ namespace detail
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler>
|
||||
class range_connect_op : base_from_connect_condition<ConnectCondition>
|
||||
{
|
||||
public:
|
||||
range_connect_op(basic_socket<Protocol>& sock,
|
||||
range_connect_op(basic_socket<Protocol, Executor>& sock,
|
||||
const EndpointSequence& endpoints,
|
||||
const ConnectCondition& connect_condition,
|
||||
RangeConnectHandler& handler)
|
||||
@ -381,69 +387,71 @@ namespace detail
|
||||
}
|
||||
|
||||
//private:
|
||||
basic_socket<Protocol>& socket_;
|
||||
basic_socket<Protocol, Executor>& socket_;
|
||||
EndpointSequence endpoints_;
|
||||
std::size_t index_;
|
||||
int start_;
|
||||
RangeConnectHandler handler_;
|
||||
};
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
range_connect_op<Protocol, EndpointSequence,
|
||||
range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>* this_handler)
|
||||
{
|
||||
return asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
range_connect_op<Protocol, EndpointSequence,
|
||||
range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>* this_handler)
|
||||
{
|
||||
asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler>
|
||||
inline bool asio_handler_is_continuation(
|
||||
range_connect_op<Protocol, EndpointSequence,
|
||||
range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>* this_handler)
|
||||
{
|
||||
return asio_handler_cont_helpers::is_continuation(
|
||||
this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function, typename Protocol, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler>
|
||||
template <typename Function, typename Executor, typename Protocol,
|
||||
typename EndpointSequence, typename ConnectCondition,
|
||||
typename RangeConnectHandler>
|
||||
inline void asio_handler_invoke(Function& function,
|
||||
range_connect_op<Protocol, EndpointSequence,
|
||||
range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>* this_handler)
|
||||
{
|
||||
asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function, typename Protocol, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler>
|
||||
template <typename Function, typename Executor, typename Protocol,
|
||||
typename EndpointSequence, typename ConnectCondition,
|
||||
typename RangeConnectHandler>
|
||||
inline void asio_handler_invoke(const Function& function,
|
||||
range_connect_op<Protocol, EndpointSequence,
|
||||
range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>* this_handler)
|
||||
{
|
||||
asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Protocol, typename Iterator,
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
class iterator_connect_op : base_from_connect_condition<ConnectCondition>
|
||||
{
|
||||
public:
|
||||
iterator_connect_op(basic_socket<Protocol>& sock,
|
||||
iterator_connect_op(basic_socket<Protocol, Executor>& sock,
|
||||
const Iterator& begin, const Iterator& end,
|
||||
const ConnectCondition& connect_condition,
|
||||
IteratorConnectHandler& handler)
|
||||
@ -527,57 +535,59 @@ namespace detail
|
||||
}
|
||||
|
||||
//private:
|
||||
basic_socket<Protocol>& socket_;
|
||||
basic_socket<Protocol, Executor>& socket_;
|
||||
Iterator iter_;
|
||||
Iterator end_;
|
||||
int start_;
|
||||
IteratorConnectHandler handler_;
|
||||
};
|
||||
|
||||
template <typename Protocol, typename Iterator,
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
inline void* asio_handler_allocate(std::size_t size,
|
||||
iterator_connect_op<Protocol, Iterator,
|
||||
iterator_connect_op<Protocol, Executor, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>* this_handler)
|
||||
{
|
||||
return asio_handler_alloc_helpers::allocate(
|
||||
size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Protocol, typename Iterator,
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size,
|
||||
iterator_connect_op<Protocol, Iterator,
|
||||
iterator_connect_op<Protocol, Executor, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>* this_handler)
|
||||
{
|
||||
asio_handler_alloc_helpers::deallocate(
|
||||
pointer, size, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Protocol, typename Iterator,
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
inline bool asio_handler_is_continuation(
|
||||
iterator_connect_op<Protocol, Iterator,
|
||||
iterator_connect_op<Protocol, Executor, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>* this_handler)
|
||||
{
|
||||
return asio_handler_cont_helpers::is_continuation(
|
||||
this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function, typename Protocol, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
template <typename Function, typename Executor, typename Protocol,
|
||||
typename Iterator, typename ConnectCondition,
|
||||
typename IteratorConnectHandler>
|
||||
inline void asio_handler_invoke(Function& function,
|
||||
iterator_connect_op<Protocol, Iterator,
|
||||
iterator_connect_op<Protocol, Executor, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>* this_handler)
|
||||
{
|
||||
asio_handler_invoke_helpers::invoke(
|
||||
function, this_handler->handler_);
|
||||
}
|
||||
|
||||
template <typename Function, typename Protocol, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
template <typename Function, typename Executor, typename Protocol,
|
||||
typename Iterator, typename ConnectCondition,
|
||||
typename IteratorConnectHandler>
|
||||
inline void asio_handler_invoke(const Function& function,
|
||||
iterator_connect_op<Protocol, Iterator,
|
||||
iterator_connect_op<Protocol, Executor, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>* this_handler)
|
||||
{
|
||||
asio_handler_invoke_helpers::invoke(
|
||||
@ -587,17 +597,17 @@ namespace detail
|
||||
|
||||
#if !defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler, typename Allocator>
|
||||
struct associated_allocator<
|
||||
detail::range_connect_op<Protocol, EndpointSequence,
|
||||
detail::range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>, Allocator>
|
||||
{
|
||||
typedef typename associated_allocator<
|
||||
RangeConnectHandler, Allocator>::type type;
|
||||
|
||||
static type get(
|
||||
const detail::range_connect_op<Protocol, EndpointSequence,
|
||||
const detail::range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>& h,
|
||||
const Allocator& a = Allocator()) ASIO_NOEXCEPT
|
||||
{
|
||||
@ -606,38 +616,39 @@ struct associated_allocator<
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler, typename Executor>
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler, typename Executor1>
|
||||
struct associated_executor<
|
||||
detail::range_connect_op<Protocol, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>, Executor>
|
||||
detail::range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>, Executor1>
|
||||
{
|
||||
typedef typename associated_executor<
|
||||
RangeConnectHandler, Executor>::type type;
|
||||
RangeConnectHandler, Executor1>::type type;
|
||||
|
||||
static type get(
|
||||
const detail::range_connect_op<Protocol, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>& h,
|
||||
const Executor& ex = Executor()) ASIO_NOEXCEPT
|
||||
const detail::range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, RangeConnectHandler>& h,
|
||||
const Executor1& ex = Executor1()) ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<RangeConnectHandler,
|
||||
Executor>::get(h.handler_, ex);
|
||||
Executor1>::get(h.handler_, ex);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition,
|
||||
typename IteratorConnectHandler, typename Allocator>
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler,
|
||||
typename Allocator>
|
||||
struct associated_allocator<
|
||||
detail::iterator_connect_op<Protocol, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>,
|
||||
detail::iterator_connect_op<Protocol, Executor,
|
||||
Iterator, ConnectCondition, IteratorConnectHandler>,
|
||||
Allocator>
|
||||
{
|
||||
typedef typename associated_allocator<
|
||||
IteratorConnectHandler, Allocator>::type type;
|
||||
|
||||
static type get(
|
||||
const detail::iterator_connect_op<Protocol, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>& h,
|
||||
const detail::iterator_connect_op<Protocol, Executor,
|
||||
Iterator, ConnectCondition, IteratorConnectHandler>& h,
|
||||
const Allocator& a = Allocator()) ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_allocator<IteratorConnectHandler,
|
||||
@ -645,33 +656,35 @@ struct associated_allocator<
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Protocol, typename Iterator, typename ConnectCondition,
|
||||
typename IteratorConnectHandler, typename Executor>
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler,
|
||||
typename Executor1>
|
||||
struct associated_executor<
|
||||
detail::iterator_connect_op<Protocol, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>,
|
||||
Executor>
|
||||
detail::iterator_connect_op<Protocol, Executor,
|
||||
Iterator, ConnectCondition, IteratorConnectHandler>,
|
||||
Executor1>
|
||||
{
|
||||
typedef typename associated_executor<
|
||||
IteratorConnectHandler, Executor>::type type;
|
||||
IteratorConnectHandler, Executor1>::type type;
|
||||
|
||||
static type get(
|
||||
const detail::iterator_connect_op<Protocol, Iterator,
|
||||
ConnectCondition, IteratorConnectHandler>& h,
|
||||
const Executor& ex = Executor()) ASIO_NOEXCEPT
|
||||
const detail::iterator_connect_op<Protocol, Executor,
|
||||
Iterator, ConnectCondition, IteratorConnectHandler>& h,
|
||||
const Executor1& ex = Executor1()) ASIO_NOEXCEPT
|
||||
{
|
||||
return associated_executor<IteratorConnectHandler,
|
||||
Executor>::get(h.handler_, ex);
|
||||
Executor1>::get(h.handler_, ex);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
typename RangeConnectHandler>
|
||||
template <typename Protocol, typename Executor,
|
||||
typename EndpointSequence, typename RangeConnectHandler>
|
||||
inline ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
||||
void (asio::error_code, typename Protocol::endpoint))
|
||||
async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
async_connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints,
|
||||
ASIO_MOVE_ARG(RangeConnectHandler) handler,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type*)
|
||||
@ -685,8 +698,8 @@ async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
void (asio::error_code, typename Protocol::endpoint)>
|
||||
init(handler);
|
||||
|
||||
detail::range_connect_op<Protocol, EndpointSequence,
|
||||
detail::default_connect_condition,
|
||||
detail::range_connect_op<Protocol, Executor,
|
||||
EndpointSequence, detail::default_connect_condition,
|
||||
ASIO_HANDLER_TYPE(RangeConnectHandler,
|
||||
void (asio::error_code, typename Protocol::endpoint))>(s,
|
||||
endpoints, detail::default_connect_condition(),
|
||||
@ -696,11 +709,11 @@ async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
}
|
||||
|
||||
#if !defined(ASIO_NO_DEPRECATED)
|
||||
template <typename Protocol, typename Iterator,
|
||||
typename IteratorConnectHandler>
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename IteratorConnectHandler>
|
||||
inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator))
|
||||
async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
ASIO_MOVE_ARG(IteratorConnectHandler) handler,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
|
||||
{
|
||||
@ -712,7 +725,7 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_completion<IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator)> init(handler);
|
||||
|
||||
detail::iterator_connect_op<Protocol, Iterator,
|
||||
detail::iterator_connect_op<Protocol, Executor, Iterator,
|
||||
detail::default_connect_condition, ASIO_HANDLER_TYPE(
|
||||
IteratorConnectHandler, void (asio::error_code, Iterator))>(s,
|
||||
begin, Iterator(), detail::default_connect_condition(),
|
||||
@ -722,10 +735,11 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
template <typename Protocol, typename Iterator, typename IteratorConnectHandler>
|
||||
template <typename Protocol, typename Executor,
|
||||
typename Iterator, typename IteratorConnectHandler>
|
||||
inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator))
|
||||
async_connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
|
||||
ASIO_MOVE_ARG(IteratorConnectHandler) handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
@ -736,7 +750,7 @@ async_connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
async_completion<IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator)> init(handler);
|
||||
|
||||
detail::iterator_connect_op<Protocol, Iterator,
|
||||
detail::iterator_connect_op<Protocol, Executor, Iterator,
|
||||
detail::default_connect_condition, ASIO_HANDLER_TYPE(
|
||||
IteratorConnectHandler, void (asio::error_code, Iterator))>(s,
|
||||
begin, end, detail::default_connect_condition(),
|
||||
@ -745,12 +759,12 @@ async_connect(basic_socket<Protocol>& s, Iterator begin, Iterator end,
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
template <typename Protocol, typename EndpointSequence,
|
||||
template <typename Protocol, typename Executor, typename EndpointSequence,
|
||||
typename ConnectCondition, typename RangeConnectHandler>
|
||||
inline ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
||||
void (asio::error_code, typename Protocol::endpoint))
|
||||
async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
ConnectCondition connect_condition,
|
||||
async_connect(basic_socket<Protocol, Executor>& s,
|
||||
const EndpointSequence& endpoints, ConnectCondition connect_condition,
|
||||
ASIO_MOVE_ARG(RangeConnectHandler) handler,
|
||||
typename enable_if<is_endpoint_sequence<
|
||||
EndpointSequence>::value>::type*)
|
||||
@ -764,7 +778,7 @@ async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
void (asio::error_code, typename Protocol::endpoint)>
|
||||
init(handler);
|
||||
|
||||
detail::range_connect_op<Protocol, EndpointSequence,
|
||||
detail::range_connect_op<Protocol, Executor, EndpointSequence,
|
||||
ConnectCondition, ASIO_HANDLER_TYPE(RangeConnectHandler,
|
||||
void (asio::error_code, typename Protocol::endpoint))>(s,
|
||||
endpoints, connect_condition, init.completion_handler)(
|
||||
@ -774,11 +788,11 @@ async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints,
|
||||
}
|
||||
|
||||
#if !defined(ASIO_NO_DEPRECATED)
|
||||
template <typename Protocol, typename Iterator,
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator))
|
||||
async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
ConnectCondition connect_condition,
|
||||
ASIO_MOVE_ARG(IteratorConnectHandler) handler,
|
||||
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
|
||||
@ -791,8 +805,8 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_completion<IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator)> init(handler);
|
||||
|
||||
detail::iterator_connect_op<Protocol, Iterator,
|
||||
ConnectCondition, ASIO_HANDLER_TYPE(
|
||||
detail::iterator_connect_op<Protocol, Executor,
|
||||
Iterator, ConnectCondition, ASIO_HANDLER_TYPE(
|
||||
IteratorConnectHandler, void (asio::error_code, Iterator))>(s,
|
||||
begin, Iterator(), connect_condition, init.completion_handler)(
|
||||
asio::error_code(), 1);
|
||||
@ -801,11 +815,11 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
}
|
||||
#endif // !defined(ASIO_NO_DEPRECATED)
|
||||
|
||||
template <typename Protocol, typename Iterator,
|
||||
template <typename Protocol, typename Executor, typename Iterator,
|
||||
typename ConnectCondition, typename IteratorConnectHandler>
|
||||
inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator))
|
||||
async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
|
||||
Iterator end, ConnectCondition connect_condition,
|
||||
ASIO_MOVE_ARG(IteratorConnectHandler) handler)
|
||||
{
|
||||
@ -817,8 +831,8 @@ async_connect(basic_socket<Protocol>& s, Iterator begin,
|
||||
async_completion<IteratorConnectHandler,
|
||||
void (asio::error_code, Iterator)> init(handler);
|
||||
|
||||
detail::iterator_connect_op<Protocol, Iterator,
|
||||
ConnectCondition, ASIO_HANDLER_TYPE(
|
||||
detail::iterator_connect_op<Protocol, Executor,
|
||||
Iterator, ConnectCondition, ASIO_HANDLER_TYPE(
|
||||
IteratorConnectHandler, void (asio::error_code, Iterator))>(s,
|
||||
begin, end, connect_condition, init.completion_handler)(
|
||||
asio::error_code(), 1);
|
||||
|
@ -34,13 +34,14 @@
|
||||
namespace asio {
|
||||
|
||||
io_context::io_context()
|
||||
: impl_(add_impl(new impl_type(*this, ASIO_CONCURRENCY_HINT_DEFAULT)))
|
||||
: impl_(add_impl(new impl_type(*this,
|
||||
ASIO_CONCURRENCY_HINT_DEFAULT, false)))
|
||||
{
|
||||
}
|
||||
|
||||
io_context::io_context(int concurrency_hint)
|
||||
: impl_(add_impl(new impl_type(*this, concurrency_hint == 1
|
||||
? ASIO_CONCURRENCY_HINT_1 : concurrency_hint)))
|
||||
? ASIO_CONCURRENCY_HINT_1 : concurrency_hint, false)))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ struct system_context::thread_function
|
||||
};
|
||||
|
||||
system_context::system_context()
|
||||
: scheduler_(use_service<detail::scheduler>(*this))
|
||||
: scheduler_(add_scheduler(new detail::scheduler(*this, 0, false)))
|
||||
{
|
||||
scheduler_.work_started();
|
||||
|
||||
@ -66,6 +66,13 @@ void system_context::join()
|
||||
threads_.join();
|
||||
}
|
||||
|
||||
detail::scheduler& system_context::add_scheduler(detail::scheduler* s)
|
||||
{
|
||||
detail::scoped_ptr<detail::scheduler> scoped_impl(s);
|
||||
asio::add_service<detail::scheduler>(*this, scoped_impl.get());
|
||||
return *scoped_impl.release();
|
||||
}
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
@ -34,7 +34,7 @@ struct thread_pool::thread_function
|
||||
};
|
||||
|
||||
thread_pool::thread_pool()
|
||||
: scheduler_(use_service<detail::scheduler>(*this))
|
||||
: scheduler_(add_scheduler(new detail::scheduler(*this, 0, false)))
|
||||
{
|
||||
scheduler_.work_started();
|
||||
|
||||
@ -44,7 +44,8 @@ thread_pool::thread_pool()
|
||||
}
|
||||
|
||||
thread_pool::thread_pool(std::size_t num_threads)
|
||||
: scheduler_(use_service<detail::scheduler>(*this))
|
||||
: scheduler_(add_scheduler(new detail::scheduler(*this, num_threads == 1
|
||||
? ASIO_CONCURRENCY_HINT_1 : num_threads, false)))
|
||||
{
|
||||
scheduler_.work_started();
|
||||
|
||||
@ -65,8 +66,18 @@ void thread_pool::stop()
|
||||
|
||||
void thread_pool::join()
|
||||
{
|
||||
scheduler_.work_finished();
|
||||
threads_.join();
|
||||
if (!threads_.empty())
|
||||
{
|
||||
scheduler_.work_finished();
|
||||
threads_.join();
|
||||
}
|
||||
}
|
||||
|
||||
detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s)
|
||||
{
|
||||
detail::scoped_ptr<detail::scheduler> scoped_impl(s);
|
||||
asio::add_service<detail::scheduler>(*this, scoped_impl.get());
|
||||
return *scoped_impl.release();
|
||||
}
|
||||
|
||||
} // namespace asio
|
||||
|
@ -23,7 +23,8 @@
|
||||
#include "asio/detail/string_view.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/executor.hpp"
|
||||
#include "asio/ip/basic_resolver_iterator.hpp"
|
||||
#include "asio/ip/basic_resolver_query.hpp"
|
||||
#include "asio/ip/basic_resolver_results.hpp"
|
||||
@ -43,6 +44,15 @@
|
||||
namespace asio {
|
||||
namespace ip {
|
||||
|
||||
#if !defined(ASIO_IP_BASIC_RESOLVER_FWD_DECL)
|
||||
#define ASIO_IP_BASIC_RESOLVER_FWD_DECL
|
||||
|
||||
// Forward declaration with defaulted arguments.
|
||||
template <typename InternetProtocol, typename Executor = executor>
|
||||
class basic_resolver;
|
||||
|
||||
#endif // !defined(ASIO_IP_BASIC_RESOLVER_FWD_DECL)
|
||||
|
||||
/// Provides endpoint resolution functionality.
|
||||
/**
|
||||
* The basic_resolver class template provides the ability to resolve a query
|
||||
@ -52,13 +62,13 @@ namespace ip {
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename InternetProtocol>
|
||||
template <typename InternetProtocol, typename Executor>
|
||||
class basic_resolver
|
||||
: public resolver_base
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef io_context::executor_type executor_type;
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// The protocol type.
|
||||
typedef InternetProtocol protocol_type;
|
||||
@ -77,16 +87,33 @@ public:
|
||||
/// The results type.
|
||||
typedef basic_resolver_results<InternetProtocol> results_type;
|
||||
|
||||
/// Constructor.
|
||||
/// Construct with executor.
|
||||
/**
|
||||
* This constructor creates a basic_resolver.
|
||||
*
|
||||
* @param io_context The io_context object that the resolver will use to
|
||||
* @param ex The I/O executor that the resolver will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* resolver.
|
||||
*/
|
||||
explicit basic_resolver(asio::io_context& io_context)
|
||||
: impl_(io_context)
|
||||
explicit basic_resolver(const executor_type& ex)
|
||||
: impl_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct with execution context.
|
||||
/**
|
||||
* This constructor creates a basic_resolver.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the resolver will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the resolver.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_resolver(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
}
|
||||
|
||||
@ -99,7 +126,7 @@ public:
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_resolver(io_context&) constructor.
|
||||
* constructed using the @c basic_resolver(const executor_type&) constructor.
|
||||
*/
|
||||
basic_resolver(basic_resolver&& other)
|
||||
: impl_(std::move(other.impl_))
|
||||
@ -116,7 +143,7 @@ public:
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_resolver(io_context&) constructor.
|
||||
* constructed using the @c basic_resolver(const executor_type&) constructor.
|
||||
*/
|
||||
basic_resolver& operator=(basic_resolver&& other)
|
||||
{
|
||||
@ -573,9 +600,9 @@ public:
|
||||
* resolver::results_type results // Resolved endpoints as a range.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* A successful resolve operation is guaranteed to pass a non-empty range to
|
||||
* the handler.
|
||||
@ -594,8 +621,8 @@ public:
|
||||
asio::async_completion<ResolveHandler,
|
||||
void (asio::error_code, results_type)> init(handler);
|
||||
|
||||
impl_.get_service().async_resolve(
|
||||
impl_.get_implementation(), q, init.completion_handler);
|
||||
impl_.get_service().async_resolve(impl_.get_implementation(), q,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -625,9 +652,9 @@ public:
|
||||
* resolver::results_type results // Resolved endpoints as a range.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* A successful resolve operation is guaranteed to pass a non-empty range to
|
||||
* the handler.
|
||||
@ -682,9 +709,9 @@ public:
|
||||
* resolver::results_type results // Resolved endpoints as a range.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* A successful resolve operation is guaranteed to pass a non-empty range to
|
||||
* the handler.
|
||||
@ -719,8 +746,8 @@ public:
|
||||
asio::async_completion<ResolveHandler,
|
||||
void (asio::error_code, results_type)> init(handler);
|
||||
|
||||
impl_.get_service().async_resolve(
|
||||
impl_.get_implementation(), q, init.completion_handler);
|
||||
impl_.get_service().async_resolve(impl_.get_implementation(), q,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -752,9 +779,9 @@ public:
|
||||
* resolver::results_type results // Resolved endpoints as a range.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* A successful resolve operation is guaranteed to pass a non-empty range to
|
||||
* the handler.
|
||||
@ -812,9 +839,9 @@ public:
|
||||
* resolver::results_type results // Resolved endpoints as a range.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* A successful resolve operation is guaranteed to pass a non-empty range to
|
||||
* the handler.
|
||||
@ -850,8 +877,8 @@ public:
|
||||
asio::async_completion<ResolveHandler,
|
||||
void (asio::error_code, results_type)> init(handler);
|
||||
|
||||
impl_.get_service().async_resolve(
|
||||
impl_.get_implementation(), q, init.completion_handler);
|
||||
impl_.get_service().async_resolve(impl_.get_implementation(), q,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -915,9 +942,9 @@ public:
|
||||
* resolver::results_type results // Resolved endpoints as a range.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* A successful resolve operation is guaranteed to pass a non-empty range to
|
||||
* the handler.
|
||||
@ -936,8 +963,8 @@ public:
|
||||
asio::async_completion<ResolveHandler,
|
||||
void (asio::error_code, results_type)> init(handler);
|
||||
|
||||
impl_.get_service().async_resolve(
|
||||
impl_.get_implementation(), e, init.completion_handler);
|
||||
impl_.get_service().async_resolve(impl_.get_implementation(), e,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
@ -949,10 +976,12 @@ private:
|
||||
|
||||
# if defined(ASIO_WINDOWS_RUNTIME)
|
||||
asio::detail::io_object_impl<
|
||||
asio::detail::winrt_resolver_service<InternetProtocol> > impl_;
|
||||
asio::detail::winrt_resolver_service<InternetProtocol>,
|
||||
Executor> impl_;
|
||||
# else
|
||||
asio::detail::io_object_impl<
|
||||
asio::detail::resolver_service<InternetProtocol> > impl_;
|
||||
asio::detail::resolver_service<InternetProtocol>,
|
||||
Executor> impl_;
|
||||
# endif
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace multicast {
|
||||
* @par Examples
|
||||
* Setting the option to join a multicast group:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::address multicast_address =
|
||||
* asio::ip::address::from_string("225.0.0.1");
|
||||
@ -60,7 +60,7 @@ typedef asio::ip::detail::socket_option::multicast_request<
|
||||
* @par Examples
|
||||
* Setting the option to leave a multicast group:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::address multicast_address =
|
||||
* asio::ip::address::from_string("225.0.0.1");
|
||||
@ -88,7 +88,7 @@ typedef asio::ip::detail::socket_option::multicast_request<
|
||||
* @par Examples
|
||||
* Setting the option:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::address_v4 local_interface =
|
||||
* asio::ip::address_v4::from_string("1.2.3.4");
|
||||
@ -116,7 +116,7 @@ typedef asio::ip::detail::socket_option::network_interface<
|
||||
* @par Examples
|
||||
* Setting the option:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::multicast::hops option(4);
|
||||
* socket.set_option(option);
|
||||
@ -125,7 +125,7 @@ typedef asio::ip::detail::socket_option::network_interface<
|
||||
* @par
|
||||
* Getting the current option value:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::multicast::hops option;
|
||||
* socket.get_option(option);
|
||||
@ -153,7 +153,7 @@ typedef asio::ip::detail::socket_option::multicast_hops<
|
||||
* @par Examples
|
||||
* Setting the option:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::multicast::enable_loopback option(true);
|
||||
* socket.set_option(option);
|
||||
@ -162,7 +162,7 @@ typedef asio::ip::detail::socket_option::multicast_hops<
|
||||
* @par
|
||||
* Getting the current option value:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::multicast::enable_loopback option;
|
||||
* socket.get_option(option);
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
* @par Examples
|
||||
* Setting the option:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::no_delay option(true);
|
||||
* socket.set_option(option);
|
||||
@ -108,7 +108,7 @@ public:
|
||||
* @par
|
||||
* Getting the current option value:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::tcp::no_delay option;
|
||||
* socket.get_option(option);
|
||||
|
@ -32,7 +32,7 @@ namespace unicast {
|
||||
* @par Examples
|
||||
* Setting the option:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::unicast::hops option(4);
|
||||
* socket.set_option(option);
|
||||
@ -41,7 +41,7 @@ namespace unicast {
|
||||
* @par
|
||||
* Getting the current option value:
|
||||
* @code
|
||||
* asio::ip::udp::socket socket(io_context);
|
||||
* asio::ip::udp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::unicast::hops option;
|
||||
* socket.get_option(option);
|
||||
|
@ -31,7 +31,7 @@ namespace ip {
|
||||
* @par Examples
|
||||
* Setting the option:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::v6_only option(true);
|
||||
* socket.set_option(option);
|
||||
@ -40,7 +40,7 @@ namespace ip {
|
||||
* @par
|
||||
* Getting the current option value:
|
||||
* @code
|
||||
* asio::ip::tcp::socket socket(io_context);
|
||||
* asio::ip::tcp::socket socket(my_context);
|
||||
* ...
|
||||
* asio::ip::v6_only option;
|
||||
* socket.get_option(option);
|
||||
|
@ -32,27 +32,28 @@ namespace asio {
|
||||
namespace local {
|
||||
|
||||
/// Create a pair of connected sockets.
|
||||
template <typename Protocol>
|
||||
void connect_pair(basic_socket<Protocol>& socket1,
|
||||
basic_socket<Protocol>& socket2);
|
||||
template <typename Protocol, typename Executor1, typename Executor2>
|
||||
void connect_pair(basic_socket<Protocol, Executor1>& socket1,
|
||||
basic_socket<Protocol, Executor2>& socket2);
|
||||
|
||||
/// Create a pair of connected sockets.
|
||||
template <typename Protocol>
|
||||
ASIO_SYNC_OP_VOID connect_pair(basic_socket<Protocol>& socket1,
|
||||
basic_socket<Protocol>& socket2, asio::error_code& ec);
|
||||
template <typename Protocol, typename Executor1, typename Executor2>
|
||||
ASIO_SYNC_OP_VOID connect_pair(basic_socket<Protocol, Executor1>& socket1,
|
||||
basic_socket<Protocol, Executor2>& socket2, asio::error_code& ec);
|
||||
|
||||
template <typename Protocol>
|
||||
inline void connect_pair(basic_socket<Protocol>& socket1,
|
||||
basic_socket<Protocol>& socket2)
|
||||
template <typename Protocol, typename Executor1, typename Executor2>
|
||||
inline void connect_pair(basic_socket<Protocol, Executor1>& socket1,
|
||||
basic_socket<Protocol, Executor2>& socket2)
|
||||
{
|
||||
asio::error_code ec;
|
||||
connect_pair(socket1, socket2, ec);
|
||||
asio::detail::throw_error(ec, "connect_pair");
|
||||
}
|
||||
|
||||
template <typename Protocol>
|
||||
inline ASIO_SYNC_OP_VOID connect_pair(basic_socket<Protocol>& socket1,
|
||||
basic_socket<Protocol>& socket2, asio::error_code& ec)
|
||||
template <typename Protocol, typename Executor1, typename Executor2>
|
||||
inline ASIO_SYNC_OP_VOID connect_pair(
|
||||
basic_socket<Protocol, Executor1>& socket1,
|
||||
basic_socket<Protocol, Executor2>& socket2, asio::error_code& ec)
|
||||
{
|
||||
// Check that this function is only being used with a UNIX domain socket.
|
||||
asio::local::basic_endpoint<Protocol>* tmp
|
||||
|
661
asio/include/asio/posix/basic_descriptor.hpp
Normal file
661
asio/include/asio/posix/basic_descriptor.hpp
Normal file
@ -0,0 +1,661 @@
|
||||
//
|
||||
// posix/basic_descriptor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_POSIX_BASIC_DESCRIPTOR_HPP
|
||||
#define ASIO_POSIX_BASIC_DESCRIPTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#include "asio/async_result.hpp"
|
||||
#include "asio/detail/handler_type_requirements.hpp"
|
||||
#include "asio/detail/io_object_impl.hpp"
|
||||
#include "asio/detail/reactive_descriptor_service.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/execution_context.hpp"
|
||||
#include "asio/executor.hpp"
|
||||
#include "asio/posix/descriptor_base.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
# include <utility>
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace posix {
|
||||
|
||||
/// Provides POSIX descriptor functionality.
|
||||
/**
|
||||
* The posix::basic_descriptor class template provides the ability to wrap a
|
||||
* POSIX descriptor.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
template <typename Executor = executor>
|
||||
class basic_descriptor
|
||||
: public descriptor_base
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// The native representation of a descriptor.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_handle_type;
|
||||
#else
|
||||
typedef detail::reactive_descriptor_service::native_handle_type
|
||||
native_handle_type;
|
||||
#endif
|
||||
|
||||
/// A descriptor is always the lowest layer.
|
||||
typedef basic_descriptor lowest_layer_type;
|
||||
|
||||
/// Construct a descriptor without opening it.
|
||||
/**
|
||||
* This constructor creates a descriptor without opening it.
|
||||
*
|
||||
* @param ex The I/O executor that the descriptor will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*/
|
||||
explicit basic_descriptor(const executor_type& ex)
|
||||
: impl_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a descriptor without opening it.
|
||||
/**
|
||||
* This constructor creates a descriptor without opening it.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the descriptor will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the descriptor.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_descriptor(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a descriptor on an existing native descriptor.
|
||||
/**
|
||||
* This constructor creates a descriptor object to hold an existing native
|
||||
* descriptor.
|
||||
*
|
||||
* @param ex The I/O executor that the descriptor will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*
|
||||
* @param native_descriptor A native descriptor.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_descriptor(const executor_type& ex,
|
||||
const native_handle_type& native_descriptor)
|
||||
: impl_(ex)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_descriptor, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
/// Construct a descriptor on an existing native descriptor.
|
||||
/**
|
||||
* This constructor creates a descriptor object to hold an existing native
|
||||
* descriptor.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the descriptor will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the descriptor.
|
||||
*
|
||||
* @param native_descriptor A native descriptor.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_descriptor(ExecutionContext& context,
|
||||
const native_handle_type& native_descriptor,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: impl_(context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_descriptor, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a descriptor from another.
|
||||
/**
|
||||
* This constructor moves a descriptor from one object to another.
|
||||
*
|
||||
* @param other The other descriptor object from which the move will
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_descriptor(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_descriptor(basic_descriptor&& other)
|
||||
: impl_(std::move(other.impl_))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a descriptor from another.
|
||||
/**
|
||||
* This assignment operator moves a descriptor from one object to another.
|
||||
*
|
||||
* @param other The other descriptor object from which the move will
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_descriptor(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_descriptor& operator=(basic_descriptor&& other)
|
||||
{
|
||||
impl_ = std::move(other.impl_);
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Get the executor associated with the object.
|
||||
executor_type get_executor() ASIO_NOEXCEPT
|
||||
{
|
||||
return impl_.get_executor();
|
||||
}
|
||||
|
||||
/// Get a reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a reference to the lowest layer in a stack of
|
||||
* layers. Since a descriptor cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A reference to the lowest layer in the stack of layers. Ownership
|
||||
* is not transferred to the caller.
|
||||
*/
|
||||
lowest_layer_type& lowest_layer()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const reference to the lowest layer in a stack of
|
||||
* layers. Since a descriptor cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A const reference to the lowest layer in the stack of layers.
|
||||
* Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assign an existing native descriptor to the descriptor.
|
||||
/*
|
||||
* This function opens the descriptor to hold an existing native descriptor.
|
||||
*
|
||||
* @param native_descriptor A native descriptor.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void assign(const native_handle_type& native_descriptor)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_descriptor, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
/// Assign an existing native descriptor to the descriptor.
|
||||
/*
|
||||
* This function opens the descriptor to hold an existing native descriptor.
|
||||
*
|
||||
* @param native_descriptor A native descriptor.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().assign(
|
||||
impl_.get_implementation(), native_descriptor, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Determine whether the descriptor is open.
|
||||
bool is_open() const
|
||||
{
|
||||
return impl_.get_service().is_open(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Close the descriptor.
|
||||
/**
|
||||
* This function is used to close the descriptor. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. Note that, even if
|
||||
* the function indicates an error, the underlying descriptor is closed.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "close");
|
||||
}
|
||||
|
||||
/// Close the descriptor.
|
||||
/**
|
||||
* This function is used to close the descriptor. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any. Note that, even if
|
||||
* the function indicates an error, the underlying descriptor is closed.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Get the native descriptor representation.
|
||||
/**
|
||||
* This function may be used to obtain the underlying representation of the
|
||||
* descriptor. This is intended to allow access to native descriptor
|
||||
* functionality that is not otherwise provided.
|
||||
*/
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
return impl_.get_service().native_handle(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Release ownership of the native descriptor implementation.
|
||||
/**
|
||||
* This function may be used to obtain the underlying representation of the
|
||||
* descriptor. After calling this function, @c is_open() returns false. The
|
||||
* caller is responsible for closing the descriptor.
|
||||
*
|
||||
* All outstanding asynchronous read or write operations will finish
|
||||
* immediately, and the handlers for cancelled operations will be passed the
|
||||
* asio::error::operation_aborted error.
|
||||
*/
|
||||
native_handle_type release()
|
||||
{
|
||||
return impl_.get_service().release(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the descriptor.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void cancel()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "cancel");
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the descriptor.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Perform an IO control command on the descriptor.
|
||||
/**
|
||||
* This function is used to execute an IO control command on the descriptor.
|
||||
*
|
||||
* @param command The IO control command to be performed on the descriptor.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @sa IoControlCommand @n
|
||||
* asio::posix::descriptor_base::bytes_readable @n
|
||||
* asio::posix::descriptor_base::non_blocking_io
|
||||
*
|
||||
* @par Example
|
||||
* Getting the number of bytes ready to read:
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(my_context);
|
||||
* ...
|
||||
* asio::posix::stream_descriptor::bytes_readable command;
|
||||
* descriptor.io_control(command);
|
||||
* std::size_t bytes_readable = command.get();
|
||||
* @endcode
|
||||
*/
|
||||
template <typename IoControlCommand>
|
||||
void io_control(IoControlCommand& command)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().io_control(impl_.get_implementation(), command, ec);
|
||||
asio::detail::throw_error(ec, "io_control");
|
||||
}
|
||||
|
||||
/// Perform an IO control command on the descriptor.
|
||||
/**
|
||||
* This function is used to execute an IO control command on the descriptor.
|
||||
*
|
||||
* @param command The IO control command to be performed on the descriptor.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @sa IoControlCommand @n
|
||||
* asio::posix::descriptor_base::bytes_readable @n
|
||||
* asio::posix::descriptor_base::non_blocking_io
|
||||
*
|
||||
* @par Example
|
||||
* Getting the number of bytes ready to read:
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(my_context);
|
||||
* ...
|
||||
* asio::posix::stream_descriptor::bytes_readable command;
|
||||
* asio::error_code ec;
|
||||
* descriptor.io_control(command, ec);
|
||||
* if (ec)
|
||||
* {
|
||||
* // An error occurred.
|
||||
* }
|
||||
* std::size_t bytes_readable = command.get();
|
||||
* @endcode
|
||||
*/
|
||||
template <typename IoControlCommand>
|
||||
ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().io_control(impl_.get_implementation(), command, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Gets the non-blocking mode of the descriptor.
|
||||
/**
|
||||
* @returns @c true if the descriptor's synchronous operations will fail with
|
||||
* asio::error::would_block if they are unable to perform the requested
|
||||
* operation immediately. If @c false, synchronous operations will block
|
||||
* until complete.
|
||||
*
|
||||
* @note The non-blocking mode has no effect on the behaviour of asynchronous
|
||||
* operations. Asynchronous operations will never fail with the error
|
||||
* asio::error::would_block.
|
||||
*/
|
||||
bool non_blocking() const
|
||||
{
|
||||
return impl_.get_service().non_blocking(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the descriptor.
|
||||
/**
|
||||
* @param mode If @c true, the descriptor's synchronous operations will fail
|
||||
* with asio::error::would_block if they are unable to perform the
|
||||
* requested operation immediately. If @c false, synchronous operations will
|
||||
* block until complete.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @note The non-blocking mode has no effect on the behaviour of asynchronous
|
||||
* operations. Asynchronous operations will never fail with the error
|
||||
* asio::error::would_block.
|
||||
*/
|
||||
void non_blocking(bool mode)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
|
||||
asio::detail::throw_error(ec, "non_blocking");
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the descriptor.
|
||||
/**
|
||||
* @param mode If @c true, the descriptor's synchronous operations will fail
|
||||
* with asio::error::would_block if they are unable to perform the
|
||||
* requested operation immediately. If @c false, synchronous operations will
|
||||
* block until complete.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @note The non-blocking mode has no effect on the behaviour of asynchronous
|
||||
* operations. Asynchronous operations will never fail with the error
|
||||
* asio::error::would_block.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID non_blocking(
|
||||
bool mode, asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Gets the non-blocking mode of the native descriptor implementation.
|
||||
/**
|
||||
* This function is used to retrieve the non-blocking mode of the underlying
|
||||
* native descriptor. This mode has no effect on the behaviour of the
|
||||
* descriptor object's synchronous operations.
|
||||
*
|
||||
* @returns @c true if the underlying descriptor is in non-blocking mode and
|
||||
* direct system calls may fail with asio::error::would_block (or the
|
||||
* equivalent system error).
|
||||
*
|
||||
* @note The current non-blocking mode is cached by the descriptor object.
|
||||
* Consequently, the return value may be incorrect if the non-blocking mode
|
||||
* was set directly on the native descriptor.
|
||||
*/
|
||||
bool native_non_blocking() const
|
||||
{
|
||||
return impl_.get_service().native_non_blocking(
|
||||
impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the native descriptor implementation.
|
||||
/**
|
||||
* This function is used to modify the non-blocking mode of the underlying
|
||||
* native descriptor. It has no effect on the behaviour of the descriptor
|
||||
* object's synchronous operations.
|
||||
*
|
||||
* @param mode If @c true, the underlying descriptor is put into non-blocking
|
||||
* mode and direct system calls may fail with asio::error::would_block
|
||||
* (or the equivalent system error).
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. If the @c mode is
|
||||
* @c false, but the current value of @c non_blocking() is @c true, this
|
||||
* function fails with asio::error::invalid_argument, as the
|
||||
* combination does not make sense.
|
||||
*/
|
||||
void native_non_blocking(bool mode)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().native_non_blocking(
|
||||
impl_.get_implementation(), mode, ec);
|
||||
asio::detail::throw_error(ec, "native_non_blocking");
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the native descriptor implementation.
|
||||
/**
|
||||
* This function is used to modify the non-blocking mode of the underlying
|
||||
* native descriptor. It has no effect on the behaviour of the descriptor
|
||||
* object's synchronous operations.
|
||||
*
|
||||
* @param mode If @c true, the underlying descriptor is put into non-blocking
|
||||
* mode and direct system calls may fail with asio::error::would_block
|
||||
* (or the equivalent system error).
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any. If the @c mode is
|
||||
* @c false, but the current value of @c non_blocking() is @c true, this
|
||||
* function fails with asio::error::invalid_argument, as the
|
||||
* combination does not make sense.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID native_non_blocking(
|
||||
bool mode, asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().native_non_blocking(
|
||||
impl_.get_implementation(), mode, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Wait for the descriptor to become ready to read, ready to write, or to
|
||||
/// have pending error conditions.
|
||||
/**
|
||||
* This function is used to perform a blocking wait for a descriptor to enter
|
||||
* a ready to read, write or error condition state.
|
||||
*
|
||||
* @param w Specifies the desired descriptor state.
|
||||
*
|
||||
* @par Example
|
||||
* Waiting for a descriptor to become readable.
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(my_context);
|
||||
* ...
|
||||
* descriptor.wait(asio::posix::stream_descriptor::wait_read);
|
||||
* @endcode
|
||||
*/
|
||||
void wait(wait_type w)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().wait(impl_.get_implementation(), w, ec);
|
||||
asio::detail::throw_error(ec, "wait");
|
||||
}
|
||||
|
||||
/// Wait for the descriptor to become ready to read, ready to write, or to
|
||||
/// have pending error conditions.
|
||||
/**
|
||||
* This function is used to perform a blocking wait for a descriptor to enter
|
||||
* a ready to read, write or error condition state.
|
||||
*
|
||||
* @param w Specifies the desired descriptor state.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @par Example
|
||||
* Waiting for a descriptor to become readable.
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(my_context);
|
||||
* ...
|
||||
* asio::error_code ec;
|
||||
* descriptor.wait(asio::posix::stream_descriptor::wait_read, ec);
|
||||
* @endcode
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID wait(wait_type w, asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().wait(impl_.get_implementation(), w, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Asynchronously wait for the descriptor to become ready to read, ready to
|
||||
/// write, or to have pending error conditions.
|
||||
/**
|
||||
* This function is used to perform an asynchronous wait for a descriptor to
|
||||
* enter a ready to read, write or error condition state.
|
||||
*
|
||||
* @param w Specifies the desired descriptor state.
|
||||
*
|
||||
* @param handler The handler to be called when the wait operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error // Result of operation
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* void wait_handler(const asio::error_code& error)
|
||||
* {
|
||||
* if (!error)
|
||||
* {
|
||||
* // Wait succeeded.
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* asio::posix::stream_descriptor descriptor(my_context);
|
||||
* ...
|
||||
* descriptor.async_wait(
|
||||
* asio::posix::stream_descriptor::wait_read,
|
||||
* wait_handler);
|
||||
* @endcode
|
||||
*/
|
||||
template <typename WaitHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WaitHandler,
|
||||
void (asio::error_code))
|
||||
async_wait(wait_type w, 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.
|
||||
ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
|
||||
|
||||
async_completion<WaitHandler,
|
||||
void (asio::error_code)> init(handler);
|
||||
|
||||
impl_.get_service().async_wait(impl_.get_implementation(), w,
|
||||
init.completion_handler, impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Protected destructor to prevent deletion through this type.
|
||||
/**
|
||||
* This function destroys the descriptor, cancelling any outstanding
|
||||
* asynchronous wait operations associated with the descriptor as if by
|
||||
* calling @c cancel.
|
||||
*/
|
||||
~basic_descriptor()
|
||||
{
|
||||
}
|
||||
|
||||
detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
basic_descriptor(const basic_descriptor&) ASIO_DELETED;
|
||||
basic_descriptor& operator=(const basic_descriptor&) ASIO_DELETED;
|
||||
};
|
||||
|
||||
} // namespace posix
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#endif // ASIO_POSIX_BASIC_DESCRIPTOR_HPP
|
407
asio/include/asio/posix/basic_stream_descriptor.hpp
Normal file
407
asio/include/asio/posix/basic_stream_descriptor.hpp
Normal file
@ -0,0 +1,407 @@
|
||||
//
|
||||
// posix/basic_stream_descriptor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
|
||||
#define ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/posix/descriptor.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
namespace asio {
|
||||
namespace posix {
|
||||
|
||||
/// Provides stream-oriented descriptor functionality.
|
||||
/**
|
||||
* The posix::basic_stream_descriptor class template provides asynchronous and
|
||||
* blocking stream-oriented descriptor functionality.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*
|
||||
* @par Concepts:
|
||||
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
||||
*/
|
||||
template <typename Executor = executor>
|
||||
class basic_stream_descriptor
|
||||
: public basic_descriptor<Executor>
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
/// The native representation of a descriptor.
|
||||
typedef typename basic_descriptor<Executor>::native_handle_type
|
||||
native_handle_type;
|
||||
|
||||
/// Construct a stream descriptor without opening it.
|
||||
/**
|
||||
* This constructor creates a stream descriptor without opening it. The
|
||||
* descriptor needs to be opened and then connected or accepted before data
|
||||
* can be sent or received on it.
|
||||
*
|
||||
* @param ex The I/O executor that the descriptor will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*/
|
||||
explicit basic_stream_descriptor(const executor_type& ex)
|
||||
: basic_descriptor<Executor>(ex)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a stream descriptor without opening it.
|
||||
/**
|
||||
* This constructor creates a stream descriptor without opening it. The
|
||||
* descriptor needs to be opened and then connected or accepted before data
|
||||
* can be sent or received on it.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the descriptor will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the descriptor.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
explicit basic_stream_descriptor(ExecutionContext& context,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_descriptor<Executor>(context)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a stream descriptor on an existing native descriptor.
|
||||
/**
|
||||
* This constructor creates a stream descriptor object to hold an existing
|
||||
* native descriptor.
|
||||
*
|
||||
* @param ex The I/O executor that the descriptor will use, by default, to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*
|
||||
* @param native_descriptor The new underlying descriptor implementation.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
basic_stream_descriptor(const executor_type& ex,
|
||||
const native_handle_type& native_descriptor)
|
||||
: basic_descriptor<Executor>(ex, native_descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a stream descriptor on an existing native descriptor.
|
||||
/**
|
||||
* This constructor creates a stream descriptor object to hold an existing
|
||||
* native descriptor.
|
||||
*
|
||||
* @param context An execution context which provides the I/O executor that
|
||||
* the descriptor will use, by default, to dispatch handlers for any
|
||||
* asynchronous operations performed on the descriptor.
|
||||
*
|
||||
* @param native_descriptor The new underlying descriptor implementation.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
template <typename ExecutionContext>
|
||||
basic_stream_descriptor(ExecutionContext& context,
|
||||
const native_handle_type& native_descriptor,
|
||||
typename enable_if<
|
||||
is_convertible<ExecutionContext&, execution_context&>::value
|
||||
>::type* = 0)
|
||||
: basic_descriptor<Executor>(context, native_descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a stream descriptor from another.
|
||||
/**
|
||||
* This constructor moves a stream descriptor from one object to another.
|
||||
*
|
||||
* @param other The other stream descriptor object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_stream_descriptor(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_stream_descriptor(basic_stream_descriptor&& other)
|
||||
: descriptor(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a stream descriptor from another.
|
||||
/**
|
||||
* This assignment operator moves a stream descriptor from one object to
|
||||
* another.
|
||||
*
|
||||
* @param other The other stream descriptor object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c basic_stream_descriptor(const executor_type&)
|
||||
* constructor.
|
||||
*/
|
||||
basic_stream_descriptor& operator=(basic_stream_descriptor&& other)
|
||||
{
|
||||
descriptor::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Write some data to the descriptor.
|
||||
/**
|
||||
* This function is used to write data to the stream descriptor. The function
|
||||
* call will block until one or more bytes of the data has been written
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the descriptor.
|
||||
*
|
||||
* @returns The number of bytes written.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. An error code of
|
||||
* asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* descriptor.write_some(asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->impl_.get_service().write_some(
|
||||
this->impl_.get_implementation(), buffers, ec);
|
||||
asio::detail::throw_error(ec, "write_some");
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Write some data to the descriptor.
|
||||
/**
|
||||
* This function is used to write data to the stream descriptor. The function
|
||||
* call will block until one or more bytes of the data has been written
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the descriptor.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return this->impl_.get_service().write_some(
|
||||
this->impl_.get_implementation(), buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write.
|
||||
/**
|
||||
* This function is used to asynchronously write data to the stream
|
||||
* descriptor. The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the descriptor.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the write operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes written.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The write operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref async_write function if you need to ensure that all
|
||||
* data is written before the asynchronous operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* descriptor.async_write_some(asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
||||
void (asio::error_code, std::size_t))
|
||||
async_write_some(const ConstBufferSequence& buffers,
|
||||
ASIO_MOVE_ARG(WriteHandler) handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a WriteHandler.
|
||||
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||
|
||||
asio::async_completion<WriteHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_write_some(
|
||||
this->impl_.get_implementation(),
|
||||
buffers, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
/// Read some data from the descriptor.
|
||||
/**
|
||||
* This function is used to read data from the stream descriptor. The function
|
||||
* call will block until one or more bytes of data has been read successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. An error code of
|
||||
* asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* descriptor.read_some(asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->impl_.get_service().read_some(
|
||||
this->impl_.get_implementation(), buffers, ec);
|
||||
asio::detail::throw_error(ec, "read_some");
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Read some data from the descriptor.
|
||||
/**
|
||||
* This function is used to read data from the stream descriptor. The function
|
||||
* call will block until one or more bytes of data has been read successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return this->impl_.get_service().read_some(
|
||||
this->impl_.get_implementation(), buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read.
|
||||
/**
|
||||
* This function is used to asynchronously read data from the stream
|
||||
* descriptor. The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the read operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes read.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. On
|
||||
* immediate completion, invocation of the handler will be performed in a
|
||||
* manner equivalent to using asio::post().
|
||||
*
|
||||
* @note The read operation may not read all of the requested number of bytes.
|
||||
* Consider using the @ref async_read function if you need to ensure that the
|
||||
* requested amount of data is read before the asynchronous operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* descriptor.async_read_some(asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
||||
void (asio::error_code, std::size_t))
|
||||
async_read_some(const MutableBufferSequence& buffers,
|
||||
ASIO_MOVE_ARG(ReadHandler) handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a ReadHandler.
|
||||
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||
|
||||
asio::async_completion<ReadHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
this->impl_.get_service().async_read_some(
|
||||
this->impl_.get_implementation(),
|
||||
buffers, init.completion_handler,
|
||||
this->impl_.get_implementation_executor());
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace posix
|
||||
} // namespace asio
|
||||
|
||||
#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#endif // ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
|
@ -20,594 +20,18 @@
|
||||
#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#include "asio/async_result.hpp"
|
||||
#include "asio/detail/handler_type_requirements.hpp"
|
||||
#include "asio/detail/io_object_impl.hpp"
|
||||
#include "asio/detail/reactive_descriptor_service.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/posix/descriptor_base.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
# include <utility>
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include "asio/posix/basic_descriptor.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace posix {
|
||||
|
||||
/// Provides POSIX descriptor functionality.
|
||||
/**
|
||||
* The posix::descriptor class template provides the ability to wrap a
|
||||
* POSIX descriptor.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*/
|
||||
class descriptor
|
||||
: public descriptor_base
|
||||
{
|
||||
public:
|
||||
/// The type of the executor associated with the object.
|
||||
typedef io_context::executor_type executor_type;
|
||||
|
||||
/// The native representation of a descriptor.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined native_handle_type;
|
||||
#else
|
||||
typedef detail::reactive_descriptor_service::native_handle_type
|
||||
native_handle_type;
|
||||
#endif
|
||||
|
||||
/// A descriptor is always the lowest layer.
|
||||
typedef descriptor lowest_layer_type;
|
||||
|
||||
/// Construct a descriptor without opening it.
|
||||
/**
|
||||
* This constructor creates a descriptor without opening it.
|
||||
*
|
||||
* @param io_context The io_context object that the descriptor will use to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*/
|
||||
explicit descriptor(asio::io_context& io_context)
|
||||
: impl_(io_context)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a descriptor on an existing native descriptor.
|
||||
/**
|
||||
* This constructor creates a descriptor object to hold an existing native
|
||||
* descriptor.
|
||||
*
|
||||
* @param io_context The io_context object that the descriptor will use to
|
||||
* dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*
|
||||
* @param native_descriptor A native descriptor.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
descriptor(asio::io_context& io_context,
|
||||
const native_handle_type& native_descriptor)
|
||||
: impl_(io_context)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_descriptor, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a descriptor from another.
|
||||
/**
|
||||
* This constructor moves a descriptor from one object to another.
|
||||
*
|
||||
* @param other The other descriptor object from which the move will
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c descriptor(io_context&) constructor.
|
||||
*/
|
||||
descriptor(descriptor&& other)
|
||||
: impl_(std::move(other.impl_))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a descriptor from another.
|
||||
/**
|
||||
* This assignment operator moves a descriptor from one object to another.
|
||||
*
|
||||
* @param other The other descriptor object from which the move will
|
||||
* occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c descriptor(io_context&) constructor.
|
||||
*/
|
||||
descriptor& operator=(descriptor&& other)
|
||||
{
|
||||
impl_ = std::move(other.impl_);
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Get the executor associated with the object.
|
||||
executor_type get_executor() ASIO_NOEXCEPT
|
||||
{
|
||||
return impl_.get_executor();
|
||||
}
|
||||
|
||||
/// Get a reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a reference to the lowest layer in a stack of
|
||||
* layers. Since a descriptor cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A reference to the lowest layer in the stack of layers. Ownership
|
||||
* is not transferred to the caller.
|
||||
*/
|
||||
lowest_layer_type& lowest_layer()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const reference to the lowest layer in a stack of
|
||||
* layers. Since a descriptor cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A const reference to the lowest layer in the stack of layers.
|
||||
* Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assign an existing native descriptor to the descriptor.
|
||||
/*
|
||||
* This function opens the descriptor to hold an existing native descriptor.
|
||||
*
|
||||
* @param native_descriptor A native descriptor.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void assign(const native_handle_type& native_descriptor)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().assign(impl_.get_implementation(),
|
||||
native_descriptor, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
/// Assign an existing native descriptor to the descriptor.
|
||||
/*
|
||||
* This function opens the descriptor to hold an existing native descriptor.
|
||||
*
|
||||
* @param native_descriptor A native descriptor.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().assign(
|
||||
impl_.get_implementation(), native_descriptor, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Determine whether the descriptor is open.
|
||||
bool is_open() const
|
||||
{
|
||||
return impl_.get_service().is_open(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Close the descriptor.
|
||||
/**
|
||||
* This function is used to close the descriptor. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. Note that, even if
|
||||
* the function indicates an error, the underlying descriptor is closed.
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "close");
|
||||
}
|
||||
|
||||
/// Close the descriptor.
|
||||
/**
|
||||
* This function is used to close the descriptor. Any asynchronous read or
|
||||
* write operations will be cancelled immediately, and will complete with the
|
||||
* asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any. Note that, even if
|
||||
* the function indicates an error, the underlying descriptor is closed.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID close(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().close(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Get the native descriptor representation.
|
||||
/**
|
||||
* This function may be used to obtain the underlying representation of the
|
||||
* descriptor. This is intended to allow access to native descriptor
|
||||
* functionality that is not otherwise provided.
|
||||
*/
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
return impl_.get_service().native_handle(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Release ownership of the native descriptor implementation.
|
||||
/**
|
||||
* This function may be used to obtain the underlying representation of the
|
||||
* descriptor. After calling this function, @c is_open() returns false. The
|
||||
* caller is responsible for closing the descriptor.
|
||||
*
|
||||
* All outstanding asynchronous read or write operations will finish
|
||||
* immediately, and the handlers for cancelled operations will be passed the
|
||||
* asio::error::operation_aborted error.
|
||||
*/
|
||||
native_handle_type release()
|
||||
{
|
||||
return impl_.get_service().release(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the descriptor.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the asio::error::operation_aborted error.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
void cancel()
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "cancel");
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the descriptor.
|
||||
/**
|
||||
* This function causes all outstanding asynchronous read or write operations
|
||||
* to finish immediately, and the handlers for cancelled operations will be
|
||||
* passed the asio::error::operation_aborted error.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().cancel(impl_.get_implementation(), ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Perform an IO control command on the descriptor.
|
||||
/**
|
||||
* This function is used to execute an IO control command on the descriptor.
|
||||
*
|
||||
* @param command The IO control command to be performed on the descriptor.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @sa IoControlCommand @n
|
||||
* asio::posix::descriptor_base::bytes_readable @n
|
||||
* asio::posix::descriptor_base::non_blocking_io
|
||||
*
|
||||
* @par Example
|
||||
* Getting the number of bytes ready to read:
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(io_context);
|
||||
* ...
|
||||
* asio::posix::stream_descriptor::bytes_readable command;
|
||||
* descriptor.io_control(command);
|
||||
* std::size_t bytes_readable = command.get();
|
||||
* @endcode
|
||||
*/
|
||||
template <typename IoControlCommand>
|
||||
void io_control(IoControlCommand& command)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().io_control(impl_.get_implementation(), command, ec);
|
||||
asio::detail::throw_error(ec, "io_control");
|
||||
}
|
||||
|
||||
/// Perform an IO control command on the descriptor.
|
||||
/**
|
||||
* This function is used to execute an IO control command on the descriptor.
|
||||
*
|
||||
* @param command The IO control command to be performed on the descriptor.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @sa IoControlCommand @n
|
||||
* asio::posix::descriptor_base::bytes_readable @n
|
||||
* asio::posix::descriptor_base::non_blocking_io
|
||||
*
|
||||
* @par Example
|
||||
* Getting the number of bytes ready to read:
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(io_context);
|
||||
* ...
|
||||
* asio::posix::stream_descriptor::bytes_readable command;
|
||||
* asio::error_code ec;
|
||||
* descriptor.io_control(command, ec);
|
||||
* if (ec)
|
||||
* {
|
||||
* // An error occurred.
|
||||
* }
|
||||
* std::size_t bytes_readable = command.get();
|
||||
* @endcode
|
||||
*/
|
||||
template <typename IoControlCommand>
|
||||
ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().io_control(impl_.get_implementation(), command, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Gets the non-blocking mode of the descriptor.
|
||||
/**
|
||||
* @returns @c true if the descriptor's synchronous operations will fail with
|
||||
* asio::error::would_block if they are unable to perform the requested
|
||||
* operation immediately. If @c false, synchronous operations will block
|
||||
* until complete.
|
||||
*
|
||||
* @note The non-blocking mode has no effect on the behaviour of asynchronous
|
||||
* operations. Asynchronous operations will never fail with the error
|
||||
* asio::error::would_block.
|
||||
*/
|
||||
bool non_blocking() const
|
||||
{
|
||||
return impl_.get_service().non_blocking(impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the descriptor.
|
||||
/**
|
||||
* @param mode If @c true, the descriptor's synchronous operations will fail
|
||||
* with asio::error::would_block if they are unable to perform the
|
||||
* requested operation immediately. If @c false, synchronous operations will
|
||||
* block until complete.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*
|
||||
* @note The non-blocking mode has no effect on the behaviour of asynchronous
|
||||
* operations. Asynchronous operations will never fail with the error
|
||||
* asio::error::would_block.
|
||||
*/
|
||||
void non_blocking(bool mode)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
|
||||
asio::detail::throw_error(ec, "non_blocking");
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the descriptor.
|
||||
/**
|
||||
* @param mode If @c true, the descriptor's synchronous operations will fail
|
||||
* with asio::error::would_block if they are unable to perform the
|
||||
* requested operation immediately. If @c false, synchronous operations will
|
||||
* block until complete.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @note The non-blocking mode has no effect on the behaviour of asynchronous
|
||||
* operations. Asynchronous operations will never fail with the error
|
||||
* asio::error::would_block.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID non_blocking(
|
||||
bool mode, asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Gets the non-blocking mode of the native descriptor implementation.
|
||||
/**
|
||||
* This function is used to retrieve the non-blocking mode of the underlying
|
||||
* native descriptor. This mode has no effect on the behaviour of the
|
||||
* descriptor object's synchronous operations.
|
||||
*
|
||||
* @returns @c true if the underlying descriptor is in non-blocking mode and
|
||||
* direct system calls may fail with asio::error::would_block (or the
|
||||
* equivalent system error).
|
||||
*
|
||||
* @note The current non-blocking mode is cached by the descriptor object.
|
||||
* Consequently, the return value may be incorrect if the non-blocking mode
|
||||
* was set directly on the native descriptor.
|
||||
*/
|
||||
bool native_non_blocking() const
|
||||
{
|
||||
return impl_.get_service().native_non_blocking(
|
||||
impl_.get_implementation());
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the native descriptor implementation.
|
||||
/**
|
||||
* This function is used to modify the non-blocking mode of the underlying
|
||||
* native descriptor. It has no effect on the behaviour of the descriptor
|
||||
* object's synchronous operations.
|
||||
*
|
||||
* @param mode If @c true, the underlying descriptor is put into non-blocking
|
||||
* mode and direct system calls may fail with asio::error::would_block
|
||||
* (or the equivalent system error).
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. If the @c mode is
|
||||
* @c false, but the current value of @c non_blocking() is @c true, this
|
||||
* function fails with asio::error::invalid_argument, as the
|
||||
* combination does not make sense.
|
||||
*/
|
||||
void native_non_blocking(bool mode)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().native_non_blocking(
|
||||
impl_.get_implementation(), mode, ec);
|
||||
asio::detail::throw_error(ec, "native_non_blocking");
|
||||
}
|
||||
|
||||
/// Sets the non-blocking mode of the native descriptor implementation.
|
||||
/**
|
||||
* This function is used to modify the non-blocking mode of the underlying
|
||||
* native descriptor. It has no effect on the behaviour of the descriptor
|
||||
* object's synchronous operations.
|
||||
*
|
||||
* @param mode If @c true, the underlying descriptor is put into non-blocking
|
||||
* mode and direct system calls may fail with asio::error::would_block
|
||||
* (or the equivalent system error).
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any. If the @c mode is
|
||||
* @c false, but the current value of @c non_blocking() is @c true, this
|
||||
* function fails with asio::error::invalid_argument, as the
|
||||
* combination does not make sense.
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID native_non_blocking(
|
||||
bool mode, asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().native_non_blocking(
|
||||
impl_.get_implementation(), mode, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Wait for the descriptor to become ready to read, ready to write, or to
|
||||
/// have pending error conditions.
|
||||
/**
|
||||
* This function is used to perform a blocking wait for a descriptor to enter
|
||||
* a ready to read, write or error condition state.
|
||||
*
|
||||
* @param w Specifies the desired descriptor state.
|
||||
*
|
||||
* @par Example
|
||||
* Waiting for a descriptor to become readable.
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(io_context);
|
||||
* ...
|
||||
* descriptor.wait(asio::posix::stream_descriptor::wait_read);
|
||||
* @endcode
|
||||
*/
|
||||
void wait(wait_type w)
|
||||
{
|
||||
asio::error_code ec;
|
||||
impl_.get_service().wait(impl_.get_implementation(), w, ec);
|
||||
asio::detail::throw_error(ec, "wait");
|
||||
}
|
||||
|
||||
/// Wait for the descriptor to become ready to read, ready to write, or to
|
||||
/// have pending error conditions.
|
||||
/**
|
||||
* This function is used to perform a blocking wait for a descriptor to enter
|
||||
* a ready to read, write or error condition state.
|
||||
*
|
||||
* @param w Specifies the desired descriptor state.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @par Example
|
||||
* Waiting for a descriptor to become readable.
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(io_context);
|
||||
* ...
|
||||
* asio::error_code ec;
|
||||
* descriptor.wait(asio::posix::stream_descriptor::wait_read, ec);
|
||||
* @endcode
|
||||
*/
|
||||
ASIO_SYNC_OP_VOID wait(wait_type w, asio::error_code& ec)
|
||||
{
|
||||
impl_.get_service().wait(impl_.get_implementation(), w, ec);
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
/// Asynchronously wait for the descriptor to become ready to read, ready to
|
||||
/// write, or to have pending error conditions.
|
||||
/**
|
||||
* This function is used to perform an asynchronous wait for a descriptor to
|
||||
* enter a ready to read, write or error condition state.
|
||||
*
|
||||
* @param w Specifies the desired descriptor state.
|
||||
*
|
||||
* @param handler The handler to be called when the wait operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error // Result of operation
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* void wait_handler(const asio::error_code& error)
|
||||
* {
|
||||
* if (!error)
|
||||
* {
|
||||
* // Wait succeeded.
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* asio::posix::stream_descriptor descriptor(io_context);
|
||||
* ...
|
||||
* descriptor.async_wait(
|
||||
* asio::posix::stream_descriptor::wait_read,
|
||||
* wait_handler);
|
||||
* @endcode
|
||||
*/
|
||||
template <typename WaitHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WaitHandler,
|
||||
void (asio::error_code))
|
||||
async_wait(wait_type w, 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.
|
||||
ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
|
||||
|
||||
async_completion<WaitHandler,
|
||||
void (asio::error_code)> init(handler);
|
||||
|
||||
impl_.get_service().async_wait(
|
||||
impl_.get_implementation(), w, init.completion_handler);
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Protected destructor to prevent deletion through this type.
|
||||
/**
|
||||
* This function destroys the descriptor, cancelling any outstanding
|
||||
* asynchronous wait operations associated with the descriptor as if by
|
||||
* calling @c cancel.
|
||||
*/
|
||||
~descriptor()
|
||||
{
|
||||
}
|
||||
|
||||
detail::io_object_impl<detail::reactive_descriptor_service> impl_;
|
||||
|
||||
private:
|
||||
// Disallow copying and assignment.
|
||||
descriptor(const descriptor&) ASIO_DELETED;
|
||||
descriptor& operator=(const descriptor&) ASIO_DELETED;
|
||||
};
|
||||
/// Typedef for the typical usage of basic_descriptor.
|
||||
typedef basic_descriptor<> descriptor;
|
||||
|
||||
} // namespace posix
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
// || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#endif // ASIO_POSIX_DESCRIPTOR_HPP
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
* asio::posix::stream_descriptor descriptor(io_context);
|
||||
* asio::posix::stream_descriptor descriptor(my_context);
|
||||
* ...
|
||||
* asio::descriptor_base::bytes_readable command(true);
|
||||
* descriptor.io_control(command);
|
||||
|
@ -16,331 +16,17 @@
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/posix/descriptor.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|
||||
|| defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
#include "asio/posix/basic_stream_descriptor.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace posix {
|
||||
|
||||
/// Provides stream-oriented descriptor functionality.
|
||||
/**
|
||||
* The posix::stream_descriptor class template provides asynchronous and
|
||||
* blocking stream-oriented descriptor functionality.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* @e Distinct @e objects: Safe.@n
|
||||
* @e Shared @e objects: Unsafe.
|
||||
*
|
||||
* @par Concepts:
|
||||
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
|
||||
*/
|
||||
class stream_descriptor
|
||||
: public descriptor
|
||||
{
|
||||
public:
|
||||
/// Construct a stream_descriptor without opening it.
|
||||
/**
|
||||
* This constructor creates a stream descriptor without opening it. The
|
||||
* descriptor needs to be opened and then connected or accepted before data
|
||||
* can be sent or received on it.
|
||||
*
|
||||
* @param io_context The io_context object that the stream descriptor will
|
||||
* use to dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*/
|
||||
explicit stream_descriptor(asio::io_context& io_context)
|
||||
: descriptor(io_context)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a stream_descriptor on an existing native descriptor.
|
||||
/**
|
||||
* This constructor creates a stream descriptor object to hold an existing
|
||||
* native descriptor.
|
||||
*
|
||||
* @param io_context The io_context object that the stream descriptor will
|
||||
* use to dispatch handlers for any asynchronous operations performed on the
|
||||
* descriptor.
|
||||
*
|
||||
* @param native_descriptor The new underlying descriptor implementation.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure.
|
||||
*/
|
||||
stream_descriptor(asio::io_context& io_context,
|
||||
const native_handle_type& native_descriptor)
|
||||
: descriptor(io_context, native_descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a stream_descriptor from another.
|
||||
/**
|
||||
* This constructor moves a stream descriptor from one object to another.
|
||||
*
|
||||
* @param other The other stream_descriptor object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c stream_descriptor(io_context&) constructor.
|
||||
*/
|
||||
stream_descriptor(stream_descriptor&& other)
|
||||
: descriptor(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a stream_descriptor from another.
|
||||
/**
|
||||
* This assignment operator moves a stream descriptor from one object to
|
||||
* another.
|
||||
*
|
||||
* @param other The other stream_descriptor object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the moved-from object is in the same state as if
|
||||
* constructed using the @c stream_descriptor(io_context&) constructor.
|
||||
*/
|
||||
stream_descriptor& operator=(stream_descriptor&& other)
|
||||
{
|
||||
descriptor::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Write some data to the descriptor.
|
||||
/**
|
||||
* This function is used to write data to the stream descriptor. The function
|
||||
* call will block until one or more bytes of the data has been written
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the descriptor.
|
||||
*
|
||||
* @returns The number of bytes written.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. An error code of
|
||||
* asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* descriptor.write_some(asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = impl_.get_service().write_some(
|
||||
impl_.get_implementation(), buffers, ec);
|
||||
asio::detail::throw_error(ec, "write_some");
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Write some data to the descriptor.
|
||||
/**
|
||||
* This function is used to write data to the stream descriptor. The function
|
||||
* call will block until one or more bytes of the data has been written
|
||||
* successfully, or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the descriptor.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes written. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The write_some operation may not transmit all of the data to the
|
||||
* peer. Consider using the @ref write function if you need to ensure that
|
||||
* all data is written before the blocking operation completes.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return impl_.get_service().write_some(
|
||||
impl_.get_implementation(), buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write.
|
||||
/**
|
||||
* This function is used to asynchronously write data to the stream
|
||||
* descriptor. The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more data buffers to be written to the descriptor.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the write operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes written.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
*
|
||||
* @note The write operation may not transmit all of the data to the peer.
|
||||
* Consider using the @ref async_write function if you need to ensure that all
|
||||
* data is written before the asynchronous operation completes.
|
||||
*
|
||||
* @par Example
|
||||
* To write a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* descriptor.async_write_some(asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on writing multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
||||
void (asio::error_code, std::size_t))
|
||||
async_write_some(const ConstBufferSequence& buffers,
|
||||
ASIO_MOVE_ARG(WriteHandler) handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a WriteHandler.
|
||||
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||
|
||||
asio::async_completion<WriteHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
impl_.get_service().async_write_some(
|
||||
impl_.get_implementation(), buffers, init.completion_handler);
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
/// Read some data from the descriptor.
|
||||
/**
|
||||
* This function is used to read data from the stream descriptor. The function
|
||||
* call will block until one or more bytes of data has been read successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
* @throws asio::system_error Thrown on failure. An error code of
|
||||
* asio::error::eof indicates that the connection was closed by the
|
||||
* peer.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* descriptor.read_some(asio::buffer(data, size));
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = impl_.get_service().read_some(
|
||||
impl_.get_implementation(), buffers, ec);
|
||||
asio::detail::throw_error(ec, "read_some");
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Read some data from the descriptor.
|
||||
/**
|
||||
* This function is used to read data from the stream descriptor. The function
|
||||
* call will block until one or more bytes of data has been read successfully,
|
||||
* or until an error occurs.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
* @returns The number of bytes read. Returns 0 if an error occurred.
|
||||
*
|
||||
* @note The read_some operation may not read all of the requested number of
|
||||
* bytes. Consider using the @ref read function if you need to ensure that
|
||||
* the requested amount of data is read before the blocking operation
|
||||
* completes.
|
||||
*/
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return impl_.get_service().read_some(
|
||||
impl_.get_implementation(), buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read.
|
||||
/**
|
||||
* This function is used to asynchronously read data from the stream
|
||||
* descriptor. The function call always returns immediately.
|
||||
*
|
||||
* @param buffers One or more buffers into which the data will be read.
|
||||
* Although the buffers object may be copied as necessary, ownership of the
|
||||
* underlying memory blocks is retained by the caller, which must guarantee
|
||||
* that they remain valid until the handler is called.
|
||||
*
|
||||
* @param handler The handler to be called when the read operation completes.
|
||||
* Copies will be made of the handler as required. The function signature of
|
||||
* the handler must be:
|
||||
* @code void handler(
|
||||
* const asio::error_code& error, // Result of operation.
|
||||
* std::size_t bytes_transferred // Number of bytes read.
|
||||
* ); @endcode
|
||||
* Regardless of whether the asynchronous operation completes immediately or
|
||||
* not, the handler will not be invoked from within this function. Invocation
|
||||
* of the handler will be performed in a manner equivalent to using
|
||||
* asio::io_context::post().
|
||||
*
|
||||
* @note The read operation may not read all of the requested number of bytes.
|
||||
* Consider using the @ref async_read function if you need to ensure that the
|
||||
* requested amount of data is read before the asynchronous operation
|
||||
* completes.
|
||||
*
|
||||
* @par Example
|
||||
* To read into a single data buffer use the @ref buffer function as follows:
|
||||
* @code
|
||||
* descriptor.async_read_some(asio::buffer(data, size), handler);
|
||||
* @endcode
|
||||
* See the @ref buffer documentation for information on reading into multiple
|
||||
* buffers in one go, and how to use it with arrays, boost::array or
|
||||
* std::vector.
|
||||
*/
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
||||
void (asio::error_code, std::size_t))
|
||||
async_read_some(const MutableBufferSequence& buffers,
|
||||
ASIO_MOVE_ARG(ReadHandler) handler)
|
||||
{
|
||||
// If you get an error on the following line it means that your handler does
|
||||
// not meet the documented type requirements for a ReadHandler.
|
||||
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||
|
||||
asio::async_completion<ReadHandler,
|
||||
void (asio::error_code, std::size_t)> init(handler);
|
||||
|
||||
impl_.get_service().async_read_some(
|
||||
impl_.get_implementation(), buffers, init.completion_handler);
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
};
|
||||
/// Typedef for the typical usage of a stream-oriented descriptor.
|
||||
typedef basic_stream_descriptor<> stream_descriptor;
|
||||
|
||||
} // namespace posix
|
||||
} // namespace asio
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user