From 59066d80b26e1d5b83b60d127ee17948d9ae9702 Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Sun, 17 Feb 2019 19:29:45 -1000 Subject: [PATCH] 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); --- example/cpp03/http/server2/server.cpp | 2 +- example/cpp03/http/server3/connection.cpp | 26 +- example/cpp03/http/server4/server.cpp | 2 +- example/cpp03/nonblocking/third_party_lib.cpp | 10 +- example/cpp03/porthopper/server.cpp | 8 +- example/cpp03/services/basic_logger.hpp | 6 +- example/cpp03/services/logger_service.cpp | 6 - example/cpp03/services/logger_service.hpp | 12 +- .../timeouts/blocking_token_tcp_client.cpp | 12 +- example/cpp03/tutorial/daytime3/server.cpp | 6 +- example/cpp03/tutorial/daytime7/server.cpp | 6 +- example/cpp03/windows/transmit_file.cpp | 16 +- .../cpp11/invocation/prioritised_handlers.cpp | 2 +- example/cpp11/operations/composed_5.cpp | 2 +- .../timeouts/blocking_token_tcp_client.cpp | 12 +- example/cpp11/timeouts/server.cpp | 6 +- example/cpp17/coroutines_ts/chat_server.cpp | 2 +- .../double_buffered_echo_server.cpp | 2 +- example/cpp17/coroutines_ts/echo_server.cpp | 2 +- .../cpp17/coroutines_ts/range_based_for.cpp | 2 +- .../coroutines_ts/refactored_echo_server.cpp | 2 +- include/boost/asio.hpp | 9 + include/boost/asio/basic_datagram_socket.hpp | 270 ++++-- include/boost/asio/basic_deadline_timer.hpp | 120 ++- include/boost/asio/basic_raw_socket.hpp | 272 ++++-- .../boost/asio/basic_seq_packet_socket.hpp | 225 +++-- include/boost/asio/basic_serial_port.hpp | 841 +++++++++++++++++ include/boost/asio/basic_signal_set.hpp | 534 +++++++++++ include/boost/asio/basic_socket.hpp | 257 +++-- include/boost/asio/basic_socket_acceptor.hpp | 877 ++++++++++++++---- include/boost/asio/basic_socket_streambuf.hpp | 6 +- include/boost/asio/basic_stream_socket.hpp | 244 +++-- include/boost/asio/basic_waitable_timer.hpp | 123 ++- include/boost/asio/connect.hpp | 173 ++-- include/boost/asio/coroutine.hpp | 4 +- .../asio/detail/deadline_timer_service.hpp | 20 +- .../boost/asio/detail/descriptor_read_op.hpp | 14 +- .../boost/asio/detail/descriptor_write_op.hpp | 14 +- include/boost/asio/detail/handler_work.hpp | 32 +- .../impl/reactive_descriptor_service.ipp | 6 +- .../impl/reactive_serial_port_service.ipp | 6 +- .../impl/reactive_socket_service_base.ipp | 5 +- .../detail/impl/resolver_service_base.ipp | 62 +- include/boost/asio/detail/impl/scheduler.ipp | 52 +- .../asio/detail/impl/signal_set_service.ipp | 40 +- .../detail/impl/win_iocp_handle_service.ipp | 7 +- .../asio/detail/impl/win_iocp_io_context.ipp | 41 +- .../impl/win_iocp_serial_port_service.ipp | 6 +- .../impl/win_iocp_socket_service_base.ipp | 8 +- .../detail/impl/win_object_handle_service.ipp | 33 +- .../impl/winrt_ssocket_service_base.ipp | 28 +- .../detail/impl/winrt_timer_scheduler.hpp | 6 +- .../detail/impl/winrt_timer_scheduler.ipp | 13 +- .../boost/asio/detail/io_object_executor.hpp | 129 +++ include/boost/asio/detail/io_object_impl.hpp | 82 +- .../boost/asio/detail/null_socket_service.hpp | 113 ++- .../detail/reactive_descriptor_service.hpp | 51 +- .../asio/detail/reactive_null_buffers_op.hpp | 12 +- .../detail/reactive_serial_port_service.hpp | 22 +- .../asio/detail/reactive_socket_accept_op.hpp | 34 +- .../detail/reactive_socket_connect_op.hpp | 13 +- .../asio/detail/reactive_socket_recv_op.hpp | 16 +- .../detail/reactive_socket_recvfrom_op.hpp | 14 +- .../detail/reactive_socket_recvmsg_op.hpp | 13 +- .../asio/detail/reactive_socket_send_op.hpp | 16 +- .../asio/detail/reactive_socket_sendto_op.hpp | 14 +- .../asio/detail/reactive_socket_service.hpp | 113 +-- .../detail/reactive_socket_service_base.hpp | 81 +- .../boost/asio/detail/reactive_wait_op.hpp | 12 +- .../boost/asio/detail/resolve_endpoint_op.hpp | 34 +- .../boost/asio/detail/resolve_query_op.hpp | 32 +- .../boost/asio/detail/resolver_service.hpp | 34 +- .../asio/detail/resolver_service_base.hpp | 39 +- include/boost/asio/detail/scheduler.hpp | 13 +- include/boost/asio/detail/signal_handler.hpp | 12 +- .../boost/asio/detail/signal_set_service.hpp | 34 +- include/boost/asio/detail/thread_group.hpp | 6 + include/boost/asio/detail/wait_handler.hpp | 14 +- .../asio/detail/win_iocp_handle_read_op.hpp | 14 +- .../asio/detail/win_iocp_handle_service.hpp | 70 +- .../asio/detail/win_iocp_handle_write_op.hpp | 13 +- .../boost/asio/detail/win_iocp_io_context.hpp | 12 +- .../asio/detail/win_iocp_null_buffers_op.hpp | 12 +- .../detail/win_iocp_serial_port_service.hpp | 22 +- .../asio/detail/win_iocp_socket_accept_op.hpp | 30 +- .../detail/win_iocp_socket_connect_op.hpp | 13 +- .../asio/detail/win_iocp_socket_recv_op.hpp | 13 +- .../detail/win_iocp_socket_recvfrom_op.hpp | 14 +- .../detail/win_iocp_socket_recvmsg_op.hpp | 13 +- .../asio/detail/win_iocp_socket_send_op.hpp | 13 +- .../asio/detail/win_iocp_socket_service.hpp | 130 ++- .../detail/win_iocp_socket_service_base.hpp | 99 +- .../boost/asio/detail/win_iocp_wait_op.hpp | 12 +- .../asio/detail/win_object_handle_service.hpp | 33 +- .../boost/asio/detail/winrt_async_manager.hpp | 37 +- .../boost/asio/detail/winrt_resolve_op.hpp | 13 +- .../asio/detail/winrt_resolver_service.hpp | 52 +- .../asio/detail/winrt_socket_connect_op.hpp | 12 +- .../asio/detail/winrt_socket_recv_op.hpp | 13 +- .../asio/detail/winrt_socket_send_op.hpp | 13 +- .../asio/detail/winrt_ssocket_service.hpp | 21 +- .../detail/winrt_ssocket_service_base.hpp | 57 +- .../asio/detail/winrt_timer_scheduler.hpp | 24 +- include/boost/asio/execution_context.hpp | 3 +- include/boost/asio/impl/connect.hpp | 232 ++--- include/boost/asio/impl/io_context.ipp | 5 +- include/boost/asio/impl/system_context.ipp | 9 +- include/boost/asio/impl/thread_pool.ipp | 19 +- include/boost/asio/ip/basic_resolver.hpp | 103 +- include/boost/asio/ip/multicast.hpp | 14 +- include/boost/asio/ip/tcp.hpp | 4 +- include/boost/asio/ip/unicast.hpp | 4 +- include/boost/asio/ip/v6_only.hpp | 4 +- include/boost/asio/local/connect_pair.hpp | 25 +- include/boost/asio/posix/basic_descriptor.hpp | 663 +++++++++++++ .../asio/posix/basic_stream_descriptor.hpp | 409 ++++++++ include/boost/asio/posix/descriptor.hpp | 584 +----------- include/boost/asio/posix/descriptor_base.hpp | 2 +- .../boost/asio/posix/stream_descriptor.hpp | 322 +------ include/boost/asio/read.hpp | 36 +- include/boost/asio/read_at.hpp | 24 +- include/boost/asio/read_until.hpp | 48 +- include/boost/asio/serial_port.hpp | 707 +------------- include/boost/asio/signal_set.hpp | 391 +------- include/boost/asio/socket_base.hpp | 50 +- include/boost/asio/ssl/detail/stream_core.hpp | 7 +- include/boost/asio/ssl/stream.hpp | 12 +- include/boost/asio/system_context.hpp | 3 + include/boost/asio/thread_pool.hpp | 3 + include/boost/asio/ts/netfwd.hpp | 39 +- .../asio/windows/basic_object_handle.hpp | 397 ++++++++ .../asio/windows/basic_overlapped_handle.hpp | 354 +++++++ .../windows/basic_random_access_handle.hpp | 420 +++++++++ .../asio/windows/basic_stream_handle.hpp | 404 ++++++++ include/boost/asio/windows/object_handle.hpp | 314 +------ .../boost/asio/windows/overlapped_handle.hpp | 268 +----- .../asio/windows/random_access_handle.hpp | 340 +------ include/boost/asio/windows/stream_handle.hpp | 324 +------ include/boost/asio/write.hpp | 36 +- include/boost/asio/write_at.hpp | 24 +- test/Jamfile.v2 | 14 + test/basic_serial_port.cpp | 26 + test/basic_signal_set.cpp | 25 + test/basic_socket.cpp | 25 + test/ip/icmp.cpp | 36 +- test/ip/tcp.cpp | 122 ++- test/ip/udp.cpp | 36 +- test/latency/tcp_server.cpp | 2 +- test/local/datagram_protocol.cpp | 17 +- test/local/stream_protocol.cpp | 17 +- test/posix/basic_descriptor.cpp | 25 + test/posix/basic_stream_descriptor.cpp | 25 + test/posix/stream_descriptor.cpp | 11 +- test/serial_port.cpp | 26 +- test/signal_set.cpp | 6 + test/system_timer.cpp | 3 +- test/windows/basic_object_handle.cpp | 25 + test/windows/basic_overlapped_handle.cpp | 25 + test/windows/basic_random_access_handle.cpp | 25 + test/windows/basic_stream_handle.cpp | 25 + test/windows/object_handle.cpp | 27 +- test/windows/random_access_handle.cpp | 29 +- test/windows/stream_handle.cpp | 29 +- 163 files changed, 8245 insertions(+), 5159 deletions(-) create mode 100644 include/boost/asio/basic_serial_port.hpp create mode 100644 include/boost/asio/basic_signal_set.hpp create mode 100644 include/boost/asio/detail/io_object_executor.hpp create mode 100644 include/boost/asio/posix/basic_descriptor.hpp create mode 100644 include/boost/asio/posix/basic_stream_descriptor.hpp create mode 100644 include/boost/asio/windows/basic_object_handle.hpp create mode 100644 include/boost/asio/windows/basic_overlapped_handle.hpp create mode 100644 include/boost/asio/windows/basic_random_access_handle.hpp create mode 100644 include/boost/asio/windows/basic_stream_handle.hpp create mode 100644 test/basic_serial_port.cpp create mode 100644 test/basic_signal_set.cpp create mode 100644 test/basic_socket.cpp create mode 100644 test/posix/basic_descriptor.cpp create mode 100644 test/posix/basic_stream_descriptor.cpp create mode 100644 test/windows/basic_object_handle.cpp create mode 100644 test/windows/basic_overlapped_handle.cpp create mode 100644 test/windows/basic_random_access_handle.cpp create mode 100644 test/windows/basic_stream_handle.cpp diff --git a/example/cpp03/http/server2/server.cpp b/example/cpp03/http/server2/server.cpp index 367708c59d..7b0538bf70 100644 --- a/example/cpp03/http/server2/server.cpp +++ b/example/cpp03/http/server2/server.cpp @@ -33,7 +33,7 @@ server::server(const std::string& address, const std::string& port, signals_.async_wait(boost::bind(&server::handle_stop, this)); // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(acceptor_.get_executor().context()); + boost::asio::ip::tcp::resolver resolver(acceptor_.get_executor()); boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(address, port).begin(); acceptor_.open(endpoint.protocol()); diff --git a/example/cpp03/http/server3/connection.cpp b/example/cpp03/http/server3/connection.cpp index 378ded16b2..e60ef0eaa1 100644 --- a/example/cpp03/http/server3/connection.cpp +++ b/example/cpp03/http/server3/connection.cpp @@ -19,7 +19,7 @@ namespace server3 { connection::connection(boost::asio::io_context& io_context, request_handler& handler) : strand_(io_context), - socket_(io_context), + socket_(strand_), request_handler_(handler) { } @@ -32,10 +32,9 @@ boost::asio::ip::tcp::socket& connection::socket() void connection::start() { socket_.async_read_some(boost::asio::buffer(buffer_), - boost::asio::bind_executor(strand_, - boost::bind(&connection::handle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); + boost::bind(&connection::handle_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); } void connection::handle_read(const boost::system::error_code& e, @@ -51,25 +50,22 @@ void connection::handle_read(const boost::system::error_code& e, { request_handler_.handle_request(request_, reply_); boost::asio::async_write(socket_, reply_.to_buffers(), - boost::asio::bind_executor(strand_, - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error))); + boost::bind(&connection::handle_write, shared_from_this(), + boost::asio::placeholders::error)); } else if (!result) { reply_ = reply::stock_reply(reply::bad_request); boost::asio::async_write(socket_, reply_.to_buffers(), - boost::asio::bind_executor(strand_, - boost::bind(&connection::handle_write, shared_from_this(), - boost::asio::placeholders::error))); + boost::bind(&connection::handle_write, shared_from_this(), + boost::asio::placeholders::error)); } else { socket_.async_read_some(boost::asio::buffer(buffer_), - boost::asio::bind_executor(strand_, - boost::bind(&connection::handle_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); + boost::bind(&connection::handle_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); } } diff --git a/example/cpp03/http/server4/server.cpp b/example/cpp03/http/server4/server.cpp index 9a8d39e1ea..ee61d73b96 100644 --- a/example/cpp03/http/server4/server.cpp +++ b/example/cpp03/http/server4/server.cpp @@ -45,7 +45,7 @@ void server::operator()(boost::system::error_code ec, std::size_t length) do { // Create a new socket for the next incoming connection. - socket_.reset(new tcp::socket(acceptor_->get_executor().context())); + socket_.reset(new tcp::socket(acceptor_->get_executor())); // Accept a new connection. The "yield" pseudo-keyword saves the current // line number and exits the coroutine's "reenter" block. We use the diff --git a/example/cpp03/nonblocking/third_party_lib.cpp b/example/cpp03/nonblocking/third_party_lib.cpp index 1148947615..a6508d382e 100644 --- a/example/cpp03/nonblocking/third_party_lib.cpp +++ b/example/cpp03/nonblocking/third_party_lib.cpp @@ -83,9 +83,9 @@ class connection public: typedef boost::shared_ptr pointer; - static pointer create(boost::asio::io_context& io_context) + static pointer create(const boost::asio::executor& ex) { - return pointer(new connection(io_context)); + return pointer(new connection(ex)); } tcp::socket& socket() @@ -102,8 +102,8 @@ class connection } private: - connection(boost::asio::io_context& io_context) - : socket_(io_context), + connection(const boost::asio::executor& ex) + : socket_(ex), session_impl_(socket_), read_in_progress_(false), write_in_progress_(false) @@ -193,7 +193,7 @@ class server void start_accept() { connection::pointer new_connection = - connection::create(acceptor_.get_executor().context()); + connection::create(acceptor_.get_executor()); acceptor_.async_accept(new_connection->socket(), boost::bind(&server::handle_accept, this, new_connection, diff --git a/example/cpp03/porthopper/server.cpp b/example/cpp03/porthopper/server.cpp index e8c9f8af67..03820fe416 100644 --- a/example/cpp03/porthopper/server.cpp +++ b/example/cpp03/porthopper/server.cpp @@ -36,8 +36,7 @@ class server next_frame_number_(1) { // Start waiting for a new control connection. - tcp_socket_ptr new_socket( - new tcp::socket(acceptor_.get_executor().context())); + tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_executor())); acceptor_.async_accept(*new_socket, boost::bind(&server::handle_accept, this, boost::asio::placeholders::error, new_socket)); @@ -60,8 +59,7 @@ class server } // Start waiting for a new control connection. - tcp_socket_ptr new_socket( - new tcp::socket(acceptor_.get_executor().context())); + tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_executor())); acceptor_.async_accept(*new_socket, boost::bind(&server::handle_accept, this, boost::asio::placeholders::error, new_socket)); @@ -75,7 +73,7 @@ class server { // Delay handling of the control request to simulate network latency. timer_ptr delay_timer( - new boost::asio::steady_timer(acceptor_.get_executor().context())); + new boost::asio::steady_timer(acceptor_.get_executor())); delay_timer->expires_after(boost::asio::chrono::seconds(2)); delay_timer->async_wait( boost::bind(&server::handle_control_request_timer, this, diff --git a/example/cpp03/services/basic_logger.hpp b/example/cpp03/services/basic_logger.hpp index 6f0aeb426f..41642c77db 100644 --- a/example/cpp03/services/basic_logger.hpp +++ b/example/cpp03/services/basic_logger.hpp @@ -34,13 +34,13 @@ class basic_logger /** * This constructor creates a logger. * - * @param io_context The io_context object used to locate the logger service. + * @param context The execution context used to locate the logger service. * * @param identifier An identifier for this logger. */ - explicit basic_logger(boost::asio::io_context& io_context, + explicit basic_logger(boost::asio::execution_context& context, const std::string& identifier) - : service_(boost::asio::use_service(io_context)), + : service_(boost::asio::use_service(context)), impl_(service_.null()) { service_.create(impl_, identifier); diff --git a/example/cpp03/services/logger_service.cpp b/example/cpp03/services/logger_service.cpp index 82fcb223c5..43b8ce6d33 100644 --- a/example/cpp03/services/logger_service.cpp +++ b/example/cpp03/services/logger_service.cpp @@ -9,9 +9,3 @@ // #include "logger_service.hpp" - -namespace services { - -boost::asio::io_context::id logger_service::id; - -} // namespace services diff --git a/example/cpp03/services/logger_service.hpp b/example/cpp03/services/logger_service.hpp index 84ac5a195c..0ba733b99c 100644 --- a/example/cpp03/services/logger_service.hpp +++ b/example/cpp03/services/logger_service.hpp @@ -25,11 +25,11 @@ namespace services { /// Service implementation for the logger. class logger_service - : public boost::asio::io_context::service + : public boost::asio::execution_context::service { public: - /// The unique service identifier. - static boost::asio::io_context::id id; + /// The type used to identify this service in the execution context. + typedef logger_service key_type; /// The backend implementation of a logger. struct logger_impl @@ -42,8 +42,8 @@ class logger_service typedef logger_impl* impl_type; /// Constructor creates a thread to run a private io_context. - logger_service(boost::asio::io_context& io_context) - : boost::asio::io_context::service(io_context), + logger_service(boost::asio::execution_context& context) + : boost::asio::execution_context::service(context), work_io_context_(), work_(boost::asio::make_work_guard(work_io_context_)), work_thread_(new boost::thread( @@ -62,7 +62,7 @@ class logger_service } /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() + void shutdown() { } diff --git a/example/cpp03/timeouts/blocking_token_tcp_client.cpp b/example/cpp03/timeouts/blocking_token_tcp_client.cpp index 0903d87864..b8ee4fcd74 100644 --- a/example/cpp03/timeouts/blocking_token_tcp_client.cpp +++ b/example/cpp03/timeouts/blocking_token_tcp_client.cpp @@ -22,13 +22,17 @@ using boost::asio::ip::tcp; +// We will use our sockets only with an io_context. +typedef boost::asio::basic_stream_socket tcp_socket; + //---------------------------------------------------------------------- // A custom completion token that makes asynchronous operations behave as // though they are blocking calls with a timeout. struct close_after { - close_after(boost::asio::chrono::steady_clock::duration t, tcp::socket& s) + close_after(boost::asio::chrono::steady_clock::duration t, tcp_socket& s) : timeout_(t), socket_(s) { } @@ -37,7 +41,7 @@ struct close_after boost::asio::chrono::steady_clock::duration timeout_; // The socket to be closed if the operation does not complete in time. - tcp::socket& socket_; + tcp_socket& socket_; }; namespace boost { @@ -125,7 +129,7 @@ class async_result private: boost::asio::chrono::steady_clock::duration timeout_; - tcp::socket& socket_; + tcp_socket& socket_; boost::system::error_code ec_; T t_; }; @@ -151,7 +155,7 @@ int main(int argc, char* argv[]) tcp::resolver::results_type endpoints = tcp::resolver(io_context).resolve(argv[1], argv[2]); - tcp::socket socket(io_context); + tcp_socket socket(io_context); // Run an asynchronous connect operation with a timeout. boost::asio::async_connect(socket, endpoints, diff --git a/example/cpp03/tutorial/daytime3/server.cpp b/example/cpp03/tutorial/daytime3/server.cpp index bf8263c3d6..2e8e3de3aa 100644 --- a/example/cpp03/tutorial/daytime3/server.cpp +++ b/example/cpp03/tutorial/daytime3/server.cpp @@ -70,7 +70,8 @@ class tcp_server { public: tcp_server(boost::asio::io_context& io_context) - : acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) + : io_context_(io_context), + acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) { start_accept(); } @@ -79,7 +80,7 @@ class tcp_server void start_accept() { tcp_connection::pointer new_connection = - tcp_connection::create(acceptor_.get_executor().context()); + tcp_connection::create(io_context_); acceptor_.async_accept(new_connection->socket(), boost::bind(&tcp_server::handle_accept, this, new_connection, @@ -97,6 +98,7 @@ class tcp_server start_accept(); } + boost::asio::io_context& io_context_; tcp::acceptor acceptor_; }; diff --git a/example/cpp03/tutorial/daytime7/server.cpp b/example/cpp03/tutorial/daytime7/server.cpp index 11b4198ab9..2175f798ef 100644 --- a/example/cpp03/tutorial/daytime7/server.cpp +++ b/example/cpp03/tutorial/daytime7/server.cpp @@ -69,7 +69,8 @@ class tcp_server { public: tcp_server(boost::asio::io_context& io_context) - : acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) + : io_context_(io_context), + acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) { start_accept(); } @@ -78,7 +79,7 @@ class tcp_server void start_accept() { tcp_connection::pointer new_connection = - tcp_connection::create(acceptor_.get_executor().context()); + tcp_connection::create(io_context_); acceptor_.async_accept(new_connection->socket(), boost::bind(&tcp_server::handle_accept, this, new_connection, @@ -96,6 +97,7 @@ class tcp_server start_accept(); } + boost::asio::io_context& io_context_; tcp::acceptor acceptor_; }; diff --git a/example/cpp03/windows/transmit_file.cpp b/example/cpp03/windows/transmit_file.cpp index 2f2f05c735..c4e14b6bb9 100644 --- a/example/cpp03/windows/transmit_file.cpp +++ b/example/cpp03/windows/transmit_file.cpp @@ -22,9 +22,15 @@ using boost::asio::ip::tcp; using boost::asio::windows::overlapped_ptr; using boost::asio::windows::random_access_handle; +typedef boost::asio::basic_stream_socket tcp_socket; + +typedef boost::asio::basic_socket_acceptor tcp_acceptor; + // A wrapper for the TransmitFile overlapped I/O operation. template -void transmit_file(tcp::socket& socket, +void transmit_file(tcp_socket& socket, random_access_handle& file, Handler handler) { // Construct an OVERLAPPED-derived object to contain the handler. @@ -65,7 +71,7 @@ class connection return pointer(new connection(io_context, filename)); } - tcp::socket& socket() + tcp_socket& socket() { return socket_; } @@ -96,10 +102,10 @@ class connection size_t /*bytes_transferred*/) { boost::system::error_code ignored_ec; - socket_.shutdown(tcp::socket::shutdown_both, ignored_ec); + socket_.shutdown(tcp_socket::shutdown_both, ignored_ec); } - tcp::socket socket_; + tcp_socket socket_; std::string filename_; random_access_handle file_; }; @@ -137,7 +143,7 @@ class server start_accept(); } - tcp::acceptor acceptor_; + tcp_acceptor acceptor_; std::string filename_; }; diff --git a/example/cpp11/invocation/prioritised_handlers.cpp b/example/cpp11/invocation/prioritised_handlers.cpp index 101c97f02f..c52cda2182 100644 --- a/example/cpp11/invocation/prioritised_handlers.cpp +++ b/example/cpp11/invocation/prioritised_handlers.cpp @@ -15,7 +15,7 @@ using boost::asio::ip::tcp; -class handler_priority_queue : boost::asio::execution_context +class handler_priority_queue : public boost::asio::execution_context { public: template diff --git a/example/cpp11/operations/composed_5.cpp b/example/cpp11/operations/composed_5.cpp index 0d2a00ca17..e757b413a6 100644 --- a/example/cpp11/operations/composed_5.cpp +++ b/example/cpp11/operations/composed_5.cpp @@ -179,7 +179,7 @@ auto async_write_messages(tcp::socket& socket, // Create a steady_timer to be used for the delay between messages. std::unique_ptr delay_timer( - new boost::asio::steady_timer(socket.get_executor().context())); + new boost::asio::steady_timer(socket.get_executor())); // Initiate the underlying operations by explicitly calling our intermediate // completion handler's function call operator. diff --git a/example/cpp11/timeouts/blocking_token_tcp_client.cpp b/example/cpp11/timeouts/blocking_token_tcp_client.cpp index e13b0b1779..c1f3aae21b 100644 --- a/example/cpp11/timeouts/blocking_token_tcp_client.cpp +++ b/example/cpp11/timeouts/blocking_token_tcp_client.cpp @@ -22,13 +22,17 @@ using boost::asio::ip::tcp; +// We will use our sockets only with an io_context. +using tcp_socket = boost::asio::basic_stream_socket< + tcp, boost::asio::io_context::executor_type>; + //---------------------------------------------------------------------- // A custom completion token that makes asynchronous operations behave as // though they are blocking calls with a timeout. struct close_after { - close_after(std::chrono::steady_clock::duration t, tcp::socket& s) + close_after(std::chrono::steady_clock::duration t, tcp_socket& s) : timeout_(t), socket_(s) { } @@ -37,7 +41,7 @@ struct close_after std::chrono::steady_clock::duration timeout_; // The socket to be closed if the operation does not complete in time. - tcp::socket& socket_; + tcp_socket& socket_; }; namespace boost { @@ -125,7 +129,7 @@ class async_result private: std::chrono::steady_clock::duration timeout_; - tcp::socket& socket_; + tcp_socket& socket_; boost::system::error_code error_; T t_; }; @@ -150,7 +154,7 @@ int main(int argc, char* argv[]) // Resolve the host name and service to a list of endpoints. auto endpoints = tcp::resolver(io_context).resolve(argv[1], argv[2]); - tcp::socket socket(io_context); + tcp_socket socket(io_context); // Run an asynchronous connect operation with a timeout. boost::asio::async_connect(socket, endpoints, diff --git a/example/cpp11/timeouts/server.cpp b/example/cpp11/timeouts/server.cpp index 94ae83efc3..1583732ba6 100644 --- a/example/cpp11/timeouts/server.cpp +++ b/example/cpp11/timeouts/server.cpp @@ -329,10 +329,10 @@ class tcp_session channel& channel_; tcp::socket socket_; std::string input_buffer_; - steady_timer input_deadline_{socket_.get_executor().context()}; + steady_timer input_deadline_{socket_.get_executor()}; std::deque output_queue_; - steady_timer non_empty_output_queue_{socket_.get_executor().context()}; - steady_timer output_deadline_{socket_.get_executor().context()}; + steady_timer non_empty_output_queue_{socket_.get_executor()}; + steady_timer output_deadline_{socket_.get_executor()}; }; typedef std::shared_ptr tcp_session_ptr; diff --git a/example/cpp17/coroutines_ts/chat_server.cpp b/example/cpp17/coroutines_ts/chat_server.cpp index cf6260ea57..a329c7e896 100644 --- a/example/cpp17/coroutines_ts/chat_server.cpp +++ b/example/cpp17/coroutines_ts/chat_server.cpp @@ -84,7 +84,7 @@ class chat_session public: chat_session(tcp::socket socket, chat_room& room) : socket_(std::move(socket)), - timer_(socket_.get_executor().context()), + timer_(socket_.get_executor()), room_(room) { timer_.expires_at(std::chrono::steady_clock::time_point::max()); diff --git a/example/cpp17/coroutines_ts/double_buffered_echo_server.cpp b/example/cpp17/coroutines_ts/double_buffered_echo_server.cpp index 2355df29c0..1dca39a94a 100644 --- a/example/cpp17/coroutines_ts/double_buffered_echo_server.cpp +++ b/example/cpp17/coroutines_ts/double_buffered_echo_server.cpp @@ -64,7 +64,7 @@ awaitable listener() auto executor = co_await this_coro::executor(); auto token = co_await this_coro::token(); - tcp::acceptor acceptor(executor.context(), {tcp::v4(), 55555}); + tcp::acceptor acceptor(executor, {tcp::v4(), 55555}); for (;;) { tcp::socket socket = co_await acceptor.async_accept(token); diff --git a/example/cpp17/coroutines_ts/echo_server.cpp b/example/cpp17/coroutines_ts/echo_server.cpp index 7f663effe9..c806312a08 100644 --- a/example/cpp17/coroutines_ts/echo_server.cpp +++ b/example/cpp17/coroutines_ts/echo_server.cpp @@ -49,7 +49,7 @@ awaitable listener() auto executor = co_await this_coro::executor(); auto token = co_await this_coro::token(); - tcp::acceptor acceptor(executor.context(), {tcp::v4(), 55555}); + tcp::acceptor acceptor(executor, {tcp::v4(), 55555}); for (;;) { tcp::socket socket = co_await acceptor.async_accept(token); diff --git a/example/cpp17/coroutines_ts/range_based_for.cpp b/example/cpp17/coroutines_ts/range_based_for.cpp index a43f888395..92499f69bd 100644 --- a/example/cpp17/coroutines_ts/range_based_for.cpp +++ b/example/cpp17/coroutines_ts/range_based_for.cpp @@ -71,7 +71,7 @@ class connections connection_iter end() { return connection_iter(acceptor_, - tcp::socket(acceptor_.get_executor().context())); + tcp::socket(acceptor_.get_executor())); } }; diff --git a/example/cpp17/coroutines_ts/refactored_echo_server.cpp b/example/cpp17/coroutines_ts/refactored_echo_server.cpp index 57bf3f379a..e43baebbdb 100644 --- a/example/cpp17/coroutines_ts/refactored_echo_server.cpp +++ b/example/cpp17/coroutines_ts/refactored_echo_server.cpp @@ -58,7 +58,7 @@ awaitable listener() auto executor = co_await this_coro::executor(); auto token = co_await this_coro::token(); - tcp::acceptor acceptor(executor.context(), {tcp::v4(), 55555}); + tcp::acceptor acceptor(executor, {tcp::v4(), 55555}); for (;;) { tcp::socket socket = co_await acceptor.async_accept(token); diff --git a/include/boost/asio.hpp b/include/boost/asio.hpp index 01a59492aa..01bd18b8d0 100644 --- a/include/boost/asio.hpp +++ b/include/boost/asio.hpp @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -95,6 +98,8 @@ #include #include #include +#include +#include #include #include #include @@ -118,6 +123,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include diff --git a/include/boost/asio/basic_datagram_socket.hpp b/include/boost/asio/basic_datagram_socket.hpp index 9294039301..feae9e3f18 100644 --- a/include/boost/asio/basic_datagram_socket.hpp +++ b/include/boost/asio/basic_datagram_socket.hpp @@ -28,6 +28,15 @@ namespace boost { namespace asio { +#if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL) +#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL + +// Forward declaration with defaulted arguments. +template +class basic_datagram_socket; + +#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL) + /// Provides datagram-oriented socket functionality. /** * The basic_datagram_socket class template provides asynchronous and blocking @@ -37,17 +46,28 @@ namespace asio { * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. */ -template +template class basic_datagram_socket - : public basic_socket + : public basic_socket { public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the socket type to another executor. + template + struct rebind_executor + { + /// The socket type when rebound to the specified executor. + typedef basic_datagram_socket 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::native_handle_type native_handle_type; #endif /// The protocol type. @@ -61,12 +81,29 @@ class basic_datagram_socket * 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(const executor_type& ex) + : basic_socket(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. */ - explicit basic_datagram_socket(boost::asio::io_context& io_context) - : basic_socket(io_context) + template + explicit basic_datagram_socket(ExecutionContext& context, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket(context) { } @@ -74,17 +111,37 @@ class basic_datagram_socket /** * 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 boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(const executor_type& ex, const protocol_type& protocol) + : basic_socket(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 boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_context& io_context, - const protocol_type& protocol) - : basic_socket(io_context, protocol) + template + basic_datagram_socket(ExecutionContext& context, + const protocol_type& protocol, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket(context, protocol) { } @@ -95,18 +152,42 @@ class basic_datagram_socket * 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 boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_context& io_context, - const endpoint_type& endpoint) - : basic_socket(io_context, endpoint) + basic_datagram_socket(const executor_type& ex, const endpoint_type& endpoint) + : basic_socket(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 boost::system::system_error Thrown on failure. + */ + template + basic_datagram_socket(ExecutionContext& context, + const endpoint_type& endpoint, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket(context, endpoint) { } @@ -115,9 +196,8 @@ class basic_datagram_socket * 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. * @@ -125,9 +205,34 @@ class basic_datagram_socket * * @throws boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_context& io_context, + basic_datagram_socket(const executor_type& ex, const protocol_type& protocol, const native_handle_type& native_socket) - : basic_socket(io_context, protocol, native_socket) + : basic_socket(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 boost::system::system_error Thrown on failure. + */ + template + basic_datagram_socket(ExecutionContext& context, + const protocol_type& protocol, const native_handle_type& native_socket, + typename enable_if< + is_convertible::value + >::type* = 0) + : basic_socket(context, protocol, native_socket) { } @@ -140,10 +245,11 @@ class basic_datagram_socket * 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(std::move(other)) + : basic_socket(std::move(other)) { } @@ -156,11 +262,12 @@ class basic_datagram_socket * 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::operator=(std::move(other)); + basic_socket::operator=(std::move(other)); return *this; } @@ -173,12 +280,16 @@ class basic_datagram_socket * 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 - basic_datagram_socket(basic_datagram_socket&& other, - typename enable_if::value>::type* = 0) - : basic_socket(std::move(other)) + template + basic_datagram_socket(basic_datagram_socket&& other, + typename enable_if< + is_convertible::value + && is_convertible::value + >::type* = 0) + : basic_socket(std::move(other)) { } @@ -192,14 +303,17 @@ class basic_datagram_socket * 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 enable_if::value, - basic_datagram_socket>::type& operator=( - basic_datagram_socket&& other) + template + typename enable_if< + is_convertible::value + && is_convertible::value, + basic_datagram_socket& + >::type operator=(basic_datagram_socket&& other) { - basic_socket::operator=(std::move(other)); + basic_socket::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -316,9 +430,9 @@ class basic_datagram_socket * 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 - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @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 @@ -347,7 +461,8 @@ class basic_datagram_socket void (boost::system::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(); } @@ -372,9 +487,9 @@ class basic_datagram_socket * 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 - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @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 @@ -395,7 +510,8 @@ class basic_datagram_socket void (boost::system::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(); } @@ -509,9 +625,9 @@ class basic_datagram_socket * 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 - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To send a single data buffer use the @ref buffer function as follows: @@ -539,9 +655,9 @@ class basic_datagram_socket async_completion 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(); } @@ -569,9 +685,9 @@ class basic_datagram_socket * 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 - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, @@ -589,7 +705,7 @@ class basic_datagram_socket 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(); } @@ -701,9 +817,9 @@ class basic_datagram_socket * 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 - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @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 @@ -733,7 +849,8 @@ class basic_datagram_socket void (boost::system::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(); } @@ -758,9 +875,9 @@ class basic_datagram_socket * 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 - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @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 @@ -781,7 +898,8 @@ class basic_datagram_socket void (boost::system::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(); } @@ -898,9 +1016,9 @@ class basic_datagram_socket * 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 - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). * * @par Example * To receive into a single data buffer use the @ref buffer function as @@ -927,7 +1045,8 @@ class basic_datagram_socket 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(); } @@ -957,9 +1076,9 @@ class basic_datagram_socket * 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 - * boost::asio::io_context::post(). + * not, the handler will not be invoked from within this function. On + * immediate completion, invocation of the handler will be performed in a + * manner equivalent to using boost::asio::post(). */ template BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, @@ -977,7 +1096,8 @@ class basic_datagram_socket 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(); } diff --git a/include/boost/asio/basic_deadline_timer.hpp b/include/boost/asio/basic_deadline_timer.hpp index 5f1123b4be..598cff117c 100644 --- a/include/boost/asio/basic_deadline_timer.hpp +++ b/include/boost/asio/basic_deadline_timer.hpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -52,7 +54,7 @@ namespace asio { * Performing a blocking wait: * @code * // Construct a timer without setting an expiry time. - * boost::asio::deadline_timer timer(io_context); + * boost::asio::deadline_timer timer(my_context); * * // Set an expiry time relative to now. * timer.expires_from_now(boost::posix_time::seconds(5)); @@ -75,7 +77,7 @@ namespace asio { * ... * * // Construct a timer with an absolute expiry time. - * boost::asio::deadline_timer timer(io_context, + * boost::asio::deadline_timer timer(my_context, * boost::posix_time::time_from_string("2005-12-07 23:59:59.000")); * * // Start an asynchronous wait. @@ -122,12 +124,13 @@ namespace asio { * it contains the value boost::asio::error::operation_aborted. */ template > + typename TimeTraits = boost::asio::time_traits