diff --git a/doc/asio.qbk b/doc/asio.qbk index 77f3a01e33..7b3de5adb2 100644 --- a/doc/asio.qbk +++ b/doc/asio.qbk @@ -20,8 +20,10 @@ ] [template mdash[] '''— '''] -[template indexterm1[term1] ''''''[term1]''''''] -[template indexterm2[term1 term2] ''''''[term1]''''''[term2]''''''] +[template half_open_range[text] '''['''[text])] +[template indexterm1[id term1] ''''''[term1]''''''] +[template indexterm2[id term1 term2] ''''''[term1]''''''[term2]''''''] +[template inline_note[text] \[['Note:] [text] '''—'''['end note]\] ] [template ticket[number]''''''#[number]''''''] [def __POSIX__ /POSIX/] [def __Windows__ /Windows/] @@ -31,9 +33,11 @@ [def __getsockname__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getsockname.html `getsockname()`]] [def __getsockopt__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getsockopt.html `getsockopt()`]] [def __ioctl__ [@http://www.opengroup.org/onlinepubs/000095399/functions/ioctl.html `ioctl()`]] +[def __poll__ [@http://www.opengroup.org/onlinepubs/000095399/functions/poll.html `poll()`]] [def __recvfrom__ [@http://www.opengroup.org/onlinepubs/000095399/functions/recvfrom.html `recvfrom()`]] [def __sendto__ [@http://www.opengroup.org/onlinepubs/000095399/functions/sendto.html `sendto()`]] [def __setsockopt__ [@http://www.opengroup.org/onlinepubs/000095399/functions/setsockopt.html `setsockopt()`]] +[def __shutdown__ [@http://www.opengroup.org/onlinepubs/000095399/functions/shutdown.html `shutdown()`]] [def __socket__ [@http://www.opengroup.org/onlinepubs/000095399/functions/socket.html `socket()`]] [/=============================================================================] diff --git a/doc/examples.qbk b/doc/examples.qbk index de88f02cb9..fded5d8ea2 100644 --- a/doc/examples.qbk +++ b/doc/examples.qbk @@ -116,13 +116,13 @@ cancelling all outstanding asynchronous operations. [heading HTTP Server 2] -An HTTP server using an io_service-per-CPU design. +An HTTP server using an io_context-per-CPU design. * [@boost_asio/example/cpp03/http/server2/connection.cpp] * [@boost_asio/example/cpp03/http/server2/connection.hpp] * [@boost_asio/example/cpp03/http/server2/header.hpp] -* [@boost_asio/example/cpp03/http/server2/io_service_pool.cpp] -* [@boost_asio/example/cpp03/http/server2/io_service_pool.hpp] +* [@boost_asio/example/cpp03/http/server2/io_context_pool.cpp] +* [@boost_asio/example/cpp03/http/server2/io_context_pool.hpp] * [@boost_asio/example/cpp03/http/server2/main.cpp] * [@boost_asio/example/cpp03/http/server2/mime_types.cpp] * [@boost_asio/example/cpp03/http/server2/mime_types.hpp] @@ -139,7 +139,7 @@ An HTTP server using an io_service-per-CPU design. [heading HTTP Server 3] -An HTTP server using a single io_service and a thread pool calling `io_service::run()`. +An HTTP server using a single io_context and a thread pool calling `io_context::run()`. * [@boost_asio/example/cpp03/http/server3/connection.cpp] * [@boost_asio/example/cpp03/http/server3/connection.hpp] @@ -227,7 +227,7 @@ decode structures for transmission over a socket. [heading Services] This example demonstrates how to integrate custom functionality (in this case, -for logging) into asio's [link boost_asio.reference.io_service io_service], and +for logging) into asio's [link boost_asio.reference.io_context io_context], and how to use a custom service with [link boost_asio.reference.basic_stream_socket basic_stream_socket<>]. diff --git a/doc/overview/async.qbk b/doc/overview/async.qbk index 37d2064be0..65eb6b4a56 100644 --- a/doc/overview/async.qbk +++ b/doc/overview/async.qbk @@ -30,8 +30,8 @@ read or write on a socket.] [mdash] Asynchronous Operation Processor [:Executes asynchronous operations and queues events on a completion event -queue when operations complete. From a high-level point of view, services like -`stream_socket_service` are asynchronous operation processors.] +queue when operations complete. From a high-level point of view, internal +services like `reactive_socket_service` are asynchronous operation processors.] [mdash] Completion Event Queue @@ -52,14 +52,14 @@ a completed event to its caller.] [:Calls the asynchronous event demultiplexer to dequeue events, and dispatches the completion handler (i.e. invokes the function object) associated with the -event. This abstraction is represented by the `io_service` class.] +event. This abstraction is represented by the `io_context` class.] [mdash] Initiator [:Application-specific code that starts asynchronous operations. The initiator interacts with an asynchronous operation processor via a high-level interface such as `basic_stream_socket`, which in turn delegates to a service like -`stream_socket_service`.] +`reactive_socket_service`.] [heading Implementation Using Reactor] @@ -97,7 +97,7 @@ calling an overlapped function such as `AcceptEx`.] [mdash] Completion Event Queue [:This is implemented by the operating system, and is associated with an I/O -completion port. There is one I/O completion port for each `io_service` +completion port. There is one I/O completion port for each `io_context` instance.] [mdash] Asynchronous Event Demultiplexer diff --git a/doc/overview/basics.qbk b/doc/overview/basics.qbk index 425462af4b..b1aa56a3d5 100644 --- a/doc/overview/basics.qbk +++ b/doc/overview/basics.qbk @@ -17,15 +17,15 @@ operations. [$boost_asio/sync_op.png] -[*Your program] will have at least one [*io_service] object. The [*io_service] +[*Your program] will have at least one [*io_context] object. The [*io_context] represents [*your program]'s link to the [*operating system]'s I/O services. - boost::asio::io_service io_service; + boost::asio::io_context io_context; To perform I/O operations [*your program] will need an [*I/O object] such as a TCP socket: - boost::asio::ip::tcp::socket socket(io_service); + boost::asio::ip::tcp::socket socket(io_context); When a synchronous connect operation is performed, the following sequence of events occurs: @@ -35,15 +35,15 @@ object]: socket.connect(server_endpoint); -2. The [*I/O object] forwards the request to the [*io_service]. +2. The [*I/O object] forwards the request to the [*io_context]. -3. The [*io_service] calls on the [*operating system] to perform the connect +3. The [*io_context] calls on the [*operating system] to perform the connect operation. 4. The [*operating system] returns the result of the operation to the -[*io_service]. +[*io_context]. -5. The [*io_service] translates any error resulting from the operation into an +5. The [*io_context] translates any error resulting from the operation into an object of type `boost::system::error_code`. An `error_code` may be compared with specific values, or tested as a boolean (where a `false` result means that no error occurred). The result is then forwarded back up to the [*I/O object]. @@ -76,9 +76,9 @@ The exact signature required depends on the asynchronous operation being performed. The reference documentation indicates the appropriate form for each operation. -2. The [*I/O object] forwards the request to the [*io_service]. +2. The [*I/O object] forwards the request to the [*io_context]. -3. The [*io_service] signals to the [*operating system] that it should start an +3. The [*io_context] signals to the [*operating system] that it should start an asynchronous connect. Time passes. (In the synchronous case this wait would have been contained @@ -87,15 +87,15 @@ entirely within the duration of the connect operation.) [$boost_asio/async_op2.png] 4. The [*operating system] indicates that the connect operation has completed -by placing the result on a queue, ready to be picked up by the [*io_service]. +by placing the result on a queue, ready to be picked up by the [*io_context]. -5. [*Your program] must make a call to `io_service::run()` (or to one of the -similar [*io_service] member functions) in order for the result to be -retrieved. A call to `io_service::run()` blocks while there are unfinished +5. [*Your program] must make a call to `io_context::run()` (or to one of the +similar [*io_context] member functions) in order for the result to be +retrieved. A call to `io_context::run()` blocks while there are unfinished asynchronous operations, so you would typically call it as soon as you have started your first asynchronous operation. -6. While inside the call to `io_service::run()`, the [*io_service] dequeues the +6. While inside the call to `io_context::run()`, the [*io_context] dequeues the result of the operation, translates it into an `error_code`, and then passes it to [*your completion handler]. diff --git a/doc/overview/bsd_sockets.qbk b/doc/overview/bsd_sockets.qbk index f1b4e3d6de..a7a5e97210 100644 --- a/doc/overview/bsd_sockets.qbk +++ b/doc/overview/bsd_sockets.qbk @@ -166,10 +166,10 @@ The following table shows the mapping between the BSD socket API and Boost.Asio: [`poll()`, `select()`, `pselect()`] - [ [link boost_asio.reference.io_service.run io_service::run()], - [link boost_asio.reference.io_service.run_one io_service::run_one()], - [link boost_asio.reference.io_service.poll io_service::poll()], - [link boost_asio.reference.io_service.poll_one io_service::poll_one()] + [ [link boost_asio.reference.io_context.run io_context::run()], + [link boost_asio.reference.io_context.run_one io_context::run_one()], + [link boost_asio.reference.io_context.poll io_context::poll()], + [link boost_asio.reference.io_context.poll_one io_context::poll_one()] Note: in conjunction with asynchronous operations. ] ] diff --git a/doc/overview/buffers.qbk b/doc/overview/buffers.qbk index b94795ccc9..94fb5f2634 100644 --- a/doc/overview/buffers.qbk +++ b/doc/overview/buffers.qbk @@ -45,7 +45,7 @@ an opaque representation of contiguous memory, where: mechanisms for automatically determining the size of a buffer from an array, `boost::array` or `std::vector` of POD elements, or from a `std::string`. -* Type safety violations must be explicitly requested using the `buffer_cast` +* The underlying memory is explicitly accessed using the `data()` member function. In general an application should never need to do this, but it is required by the library implementation to pass the raw memory to the underlying operating system functions. diff --git a/doc/overview/cpp2011.qbk b/doc/overview/cpp2011.qbk index 2758236ca6..aa2e55cf6e 100644 --- a/doc/overview/cpp2011.qbk +++ b/doc/overview/cpp2011.qbk @@ -33,7 +33,7 @@ Windows handles. Move support allows you to write code like: - tcp::socket make_socket(io_service& i) + tcp::socket make_socket(io_context& i) { tcp::socket s(i); ... diff --git a/doc/overview/handler_tracking.qbk b/doc/overview/handler_tracking.qbk index 7c5f1586d2..07f6f7d0e4 100644 --- a/doc/overview/handler_tracking.qbk +++ b/doc/overview/handler_tracking.qbk @@ -67,7 +67,7 @@ The `` takes one of the following forms: [~n] [The handler number `n` was destroyed without having been invoked. This is usually the case for any unfinished asynchronous operations when the - `io_service` is destroyed.] + `io_context` is destroyed.] ] [ [n*m] diff --git a/doc/overview/implementation.qbk b/doc/overview/implementation.qbk index 0f4b07c7f2..0308e1ce70 100644 --- a/doc/overview/implementation.qbk +++ b/doc/overview/implementation.qbk @@ -22,10 +22,10 @@ descriptors in the process cannot be permitted to exceed `FD_SETSIZE`. Threads: * Demultiplexing using `select` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -42,10 +42,10 @@ Demultiplexing mechanism: Threads: * Demultiplexing using `epoll` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -63,10 +63,10 @@ Demultiplexing mechanism: Threads: * Demultiplexing using [^/dev/poll] is performed in one of the threads that -calls `io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +calls `io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -85,10 +85,10 @@ descriptors in the process cannot be permitted to exceed `FD_SETSIZE`. Threads: * Demultiplexing using `select` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -106,10 +106,10 @@ Demultiplexing mechanism: Threads: * Demultiplexing using `kqueue` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -127,10 +127,10 @@ Demultiplexing mechanism: Threads: * Demultiplexing using `kqueue` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -149,10 +149,10 @@ descriptors in the process cannot be permitted to exceed `FD_SETSIZE`. Threads: * Demultiplexing using `select` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -171,10 +171,10 @@ descriptors in the process cannot be permitted to exceed `FD_SETSIZE`. Threads: * Demultiplexing using `select` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -193,10 +193,10 @@ descriptors in the process cannot be permitted to exceed `FD_SETSIZE`. Threads: * Demultiplexing using `select` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -214,10 +214,10 @@ Demultiplexing mechanism: Threads: * Demultiplexing using `select` is performed in one of the threads that calls -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -238,17 +238,17 @@ operations except for asynchronous connect. Threads: * Demultiplexing using I/O completion ports is performed in all threads that call -`io_service::run()`, `io_service::run_one()`, `io_service::poll()` or -`io_service::poll_one()`. +`io_context::run()`, `io_context::run_one()`, `io_context::poll()` or +`io_context::poll_one()`. -* An additional thread per `io_service` is used to trigger timers. This thread -is created on construction of the first `deadline_timer` or -`deadline_timer_service` objects. +* An additional thread per `io_context` is used to trigger timers. This thread +is created on construction of the first `basic_deadline_timer` or +`basic_waitable_timer` objects. -* An additional thread per `io_service` is used for the `select` +* An additional thread per `io_context` is used for the `select` demultiplexing. This thread is created on the first call to `async_connect()`. -* An additional thread per `io_service` is used to emulate asynchronous host +* An additional thread per `io_context` is used to emulate asynchronous host resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. @@ -265,7 +265,7 @@ Boost.Asio provides limited support for the Windows Runtime. It requires that th language extensions be enabled. Due to the restricted facilities exposed by the Windows Runtime API, the support comes with the following caveats: -* The core facilities such as the `io_service`, `strand`, buffers, composed +* The core facilities such as the `io_context`, `strand`, buffers, composed operations, timers, etc., should all work as normal. * For sockets, only client-side TCP is supported. @@ -292,9 +292,9 @@ Demultiplexing mechanism: Threads: * Event completions are delivered to the Windows thread pool and posted to the - `io_service` for the handler to be executed. + `io_context` for the handler to be executed. -* An additional thread per `io_service` is used to trigger timers. This thread +* An additional thread per `io_context` is used to trigger timers. This thread is created on construction of the first timer objects. Scatter-Gather: diff --git a/doc/overview/iostreams.qbk b/doc/overview/iostreams.qbk index 3e9b7f1430..2f0995a0d5 100644 --- a/doc/overview/iostreams.qbk +++ b/doc/overview/iostreams.qbk @@ -20,7 +20,7 @@ independence, etc. To create a connection one might simply write: The iostream class can also be used in conjunction with an acceptor to create simple servers. For example: - io_service ios; + io_context ioc; ip::tcp::endpoint endpoint(tcp::v4(), 80); ip::tcp::acceptor acceptor(ios, endpoint); @@ -28,7 +28,7 @@ simple servers. For example: for (;;) { ip::tcp::iostream stream; - acceptor.accept(*stream.rdbuf()); + acceptor.accept(stream.socket()); ... } diff --git a/doc/overview/other_protocols.qbk b/doc/overview/other_protocols.qbk index 42fec45d4a..aa69e564d8 100644 --- a/doc/overview/other_protocols.qbk +++ b/doc/overview/other_protocols.qbk @@ -22,7 +22,7 @@ These classes implement the [link boost_asio.reference.Protocol protocol type requirements], but allow the user to specify the address family (e.g. `AF_INET`) and protocol type (e.g. `IPPROTO_TCP`) at runtime. For example: - boost::asio::generic::stream_protocol::socket my_socket(my_io_service); + boost::asio::generic::stream_protocol::socket my_socket(my_io_context); my_socket.open(boost::asio::generic::stream_protocol(AF_INET, IPPROTO_TCP)); ... @@ -38,7 +38,7 @@ endpoint] type requirements: The conversion is implicit, so as to support the following use cases: - boost::asio::generic::stream_protocol::socket my_socket(my_io_service); + boost::asio::generic::stream_protocol::socket my_socket(my_io_context); boost::asio::ip::tcp::endpoint my_endpoint = ...; my_socket.connect(my_endpoint); @@ -53,14 +53,14 @@ type. If the protocol conversion is valid: then the corresponding socket conversion is allowed: - Protocol1::socket my_socket1(my_io_service); + Protocol1::socket my_socket1(my_io_context); ... Protocol2::socket my_socket2(std::move(my_socket1)); For example, one possible conversion is from a TCP socket to a generic stream-oriented socket: - boost::asio::ip::tcp::socket my_socket1(my_io_service); + boost::asio::ip::tcp::socket my_socket1(my_io_context); ... boost::asio::generic::stream_protocol::socket my_socket2(std::move(my_socket1)); @@ -78,9 +78,9 @@ corresponding protocol conversion is valid. For example, the following is supported because the protocol `boost::asio::ip::tcp` is convertible to `boost::asio::generic::stream_protocol`: - boost::asio::ip::tcp::acceptor my_acceptor(my_io_service); + boost::asio::ip::tcp::acceptor my_acceptor(my_io_context); ... - boost::asio::generic::stream_protocol::socket my_socket(my_io_service); + boost::asio::generic::stream_protocol::socket my_socket(my_io_context); my_acceptor.accept(my_socket); [heading See Also] diff --git a/doc/overview/posix.qbk b/doc/overview/posix.qbk index d7468ea8b4..8fba83bd96 100644 --- a/doc/overview/posix.qbk +++ b/doc/overview/posix.qbk @@ -19,15 +19,15 @@ Boost.Asio provides basic support UNIX domain sockets (also known as local socke The simplest use involves creating a pair of connected sockets. The following code: - local::stream_protocol::socket socket1(my_io_service); - local::stream_protocol::socket socket2(my_io_service); + local::stream_protocol::socket socket1(my_io_context); + local::stream_protocol::socket socket2(my_io_context); local::connect_pair(socket1, socket2); will create a pair of stream-oriented sockets. To do the same for datagram-oriented sockets, use: - local::datagram_protocol::socket socket1(my_io_service); - local::datagram_protocol::socket socket2(my_io_service); + local::datagram_protocol::socket socket1(my_io_context); + local::datagram_protocol::socket socket2(my_io_context); local::connect_pair(socket1, socket2); A UNIX domain socket server may be created by binding an acceptor to an @@ -35,14 +35,14 @@ endpoint, in much the same way as one does for a TCP server: ::unlink("/tmp/foobar"); // Remove previous binding. local::stream_protocol::endpoint ep("/tmp/foobar"); - local::stream_protocol::acceptor acceptor(my_io_service, ep); - local::stream_protocol::socket socket(my_io_service); + local::stream_protocol::acceptor acceptor(my_io_context, ep); + local::stream_protocol::socket socket(my_io_context); acceptor.accept(socket); A client that connects to this server might look like: local::stream_protocol::endpoint ep("/tmp/foobar"); - local::stream_protocol::socket socket(my_io_service); + local::stream_protocol::socket socket(my_io_context); socket.connect(ep); Transmission of file descriptors or credentials across UNIX domain sockets is @@ -88,8 +88,8 @@ performed immediately. Wait operations, and operations involving For example, to perform read and write operations on standard input and output, the following objects may be created: - posix::stream_descriptor in(my_io_service, ::dup(STDIN_FILENO)); - posix::stream_descriptor out(my_io_service, ::dup(STDOUT_FILENO)); + posix::stream_descriptor in(my_io_context, ::dup(STDIN_FILENO)); + posix::stream_descriptor out(my_io_context, ::dup(STDOUT_FILENO)); These are then used as synchronous or asynchronous read and write streams. This means the objects can be used with any of the [link boost_asio.reference.read @@ -101,8 +101,6 @@ boost_asio.reference.async_read_until async_read_until()] free functions. [heading See Also] [link boost_asio.reference.posix__stream_descriptor posix::stream_descriptor], -[link boost_asio.reference.posix__basic_stream_descriptor posix::basic_stream_descriptor], -[link boost_asio.reference.posix__stream_descriptor_service posix::stream_descriptor_service], [link boost_asio.examples.cpp03_examples.chat Chat example (C++03)], [link boost_asio.examples.cpp11_examples.chat Chat example (C++11)]. @@ -117,25 +115,25 @@ target operating system. A program may test for the macro [section:fork Fork] Boost.Asio supports programs that utilise the `fork()` system call. Provided the -program calls `io_service.notify_fork()` at the appropriate times, Boost.Asio will +program calls `io_context.notify_fork()` at the appropriate times, Boost.Asio will recreate any internal file descriptors (such as the "self-pipe trick" descriptor used for waking up a reactor). The notification is usually performed as follows: - io_service_.notify_fork(boost::asio::io_service::fork_prepare); + io_context_.notify_fork(boost::asio::io_context::fork_prepare); if (fork() == 0) { - io_service_.notify_fork(boost::asio::io_service::fork_child); + io_context_.notify_fork(boost::asio::io_context::fork_child); ... } else { - io_service_.notify_fork(boost::asio::io_service::fork_parent); + io_context_.notify_fork(boost::asio::io_context::fork_parent); ... } User-defined services can also be made fork-aware by overriding the -`io_service::service::fork_service()` virtual function. +`io_context::service::notify_fork()` virtual function. Note that any file descriptors accessible via Boost.Asio's public API (e.g. the descriptors underlying `basic_socket<>`, `posix::stream_descriptor`, etc.) are @@ -144,9 +142,9 @@ as required. [heading See Also] -[link boost_asio.reference.io_service.notify_fork io_service::notify_fork()], -[link boost_asio.reference.io_service.fork_event io_service::fork_event], -[link boost_asio.reference.io_service__service.fork_service io_service::service::fork_service()], +[link boost_asio.reference.io_context.notify_fork io_context::notify_fork()], +[link boost_asio.reference.io_context.fork_event io_context::fork_event], +[link boost_asio.reference.execution_context__service.notify_fork io_context::service::notify_fork()], [link boost_asio.examples.cpp03_examples.fork Fork examples]. [endsect] diff --git a/doc/overview/protocols.qbk b/doc/overview/protocols.qbk index 65895ff70e..6b0b61bf63 100644 --- a/doc/overview/protocols.qbk +++ b/doc/overview/protocols.qbk @@ -15,7 +15,7 @@ ICMP. Hostname resolution is performed using a resolver, where host and service names are looked up and converted into one or more endpoints: - ip::tcp::resolver resolver(my_io_service); + ip::tcp::resolver resolver(my_io_context); ip::tcp::resolver::query query("www.boost.org", "http"); ip::tcp::resolver::iterator iter = resolver.resolve(query); ip::tcp::resolver::iterator end; // End marker. @@ -35,7 +35,7 @@ connect()] and [link boost_asio.reference.async_connect async_connect()]. These operations try each endpoint in a list until the socket is successfully connected. For example, a single call: - ip::tcp::socket socket(my_io_service); + ip::tcp::socket socket(my_io_context); boost::asio::connect(socket, resolver.resolve(query)); will synchronously try all endpoints until one is successfully connected. @@ -61,7 +61,7 @@ Similarly, an asynchronous connect may be performed by writing: When a specific endpoint is available, a socket can be created and connected: - ip::tcp::socket socket(my_io_service); + ip::tcp::socket socket(my_io_context); socket.connect(endpoint); Data may be read from or written to a connected TCP socket using the [link @@ -79,9 +79,9 @@ boost_asio.reference.async_write async_write()]. A program uses an acceptor to accept incoming TCP connections: - ip::tcp::acceptor acceptor(my_io_service, my_endpoint); + ip::tcp::acceptor acceptor(my_io_context, my_endpoint); ... - ip::tcp::socket socket(my_io_service); + ip::tcp::socket socket(my_io_context); acceptor.accept(socket); After a socket has been successfully accepted, it may be read from or written @@ -91,7 +91,7 @@ to as illustrated for TCP clients above. UDP hostname resolution is also performed using a resolver: - ip::udp::resolver resolver(my_io_service); + ip::udp::resolver resolver(my_io_context); ip::udp::resolver::query query("localhost", "daytime"); ip::udp::resolver::iterator iter = resolver.resolve(query); ... @@ -101,7 +101,7 @@ create an IP version 4 UDP socket and bind it to the "any" address on port `12345`: ip::udp::endpoint endpoint(ip::udp::v4(), 12345); - ip::udp::socket socket(my_io_service, endpoint); + ip::udp::socket socket(my_io_context, endpoint); Data may be read from or written to an unconnected UDP socket using the [link boost_asio.reference.basic_datagram_socket.receive_from receive_from()], [link @@ -118,7 +118,7 @@ boost_asio.reference.basic_datagram_socket.async_send async_send()] member funct As with TCP and UDP, ICMP hostname resolution is performed using a resolver: - ip::icmp::resolver resolver(my_io_service); + ip::icmp::resolver resolver(my_io_context); ip::icmp::resolver::query query("localhost", ""); ip::icmp::resolver::iterator iter = resolver.resolve(query); ... @@ -127,7 +127,7 @@ An ICMP socket may be bound to a local endpoint. The following code will create an IP version 6 ICMP socket and bind it to the "any" address: ip::icmp::endpoint endpoint(ip::icmp::v6(), 0); - ip::icmp::socket socket(my_io_service, endpoint); + ip::icmp::socket socket(my_io_context, endpoint); The port number is not used for ICMP. diff --git a/doc/overview/reactor.qbk b/doc/overview/reactor.qbk index bc36a9c24a..ad405f688b 100644 --- a/doc/overview/reactor.qbk +++ b/doc/overview/reactor.qbk @@ -8,19 +8,18 @@ [section:reactor Reactor-Style Operations] Sometimes a program must be integrated with a third-party library that wants to -perform the I/O operations itself. To facilitate this, Boost.Asio includes a -`null_buffers` type that can be used with both read and write operations. A -`null_buffers` operation doesn't return until the I/O object is "ready" to -perform the operation. +perform the I/O operations itself. To facilitate this, Boost.Asio includes +synchronous and asynchronous operations that may be used to wait for a socket +to become ready to read, ready to write, or to have a pending error condition. -As an example, to perform a non-blocking read something like the -following may be used: +As an example, to perform a non-blocking read something like the following may +be used: - ip::tcp::socket socket(my_io_service); + ip::tcp::socket socket(my_io_context); ... socket.non_blocking(true); ... - socket.async_read_some(null_buffers(), read_handler); + socket.async_wait(ip::tcp::socket::wait_read, read_handler); ... void read_handler(boost::system::error_code ec) { @@ -36,7 +35,8 @@ stream-oriented descriptor classes. [heading See Also] -[link boost_asio.reference.null_buffers null_buffers], +[link boost_asio.reference.basic_socket.wait basic_socket::wait()], +[link boost_asio.reference.basic_socket.async_wait basic_socket::async_wait()], [link boost_asio.reference.basic_socket.non_blocking basic_socket::non_blocking()], [link boost_asio.reference.basic_socket.native_non_blocking basic_socket::native_non_blocking()], [link boost_asio.examples.cpp03_examples.nonblocking nonblocking example]. diff --git a/doc/overview/serial_ports.qbk b/doc/overview/serial_ports.qbk index 2a8bc07a08..e3edef37c1 100644 --- a/doc/overview/serial_ports.qbk +++ b/doc/overview/serial_ports.qbk @@ -10,7 +10,7 @@ Boost.Asio includes classes for creating and manipulating serial ports in a portable manner. For example, a serial port may be opened using: - serial_port port(my_io_service, name); + serial_port port(my_io_context, name); where name is something like `"COM1"` on Windows, and `"/dev/ttyS0"` on POSIX platforms. @@ -29,8 +29,6 @@ port's baud rate, flow control type, parity, stop bits and character size. [link boost_asio.reference.serial_port serial_port], [link boost_asio.reference.serial_port_base serial_port_base], -[link boost_asio.reference.basic_serial_port basic_serial_port], -[link boost_asio.reference.serial_port_service serial_port_service], [link boost_asio.reference.serial_port_base__baud_rate serial_port_base::baud_rate], [link boost_asio.reference.serial_port_base__flow_control serial_port_base::flow_control], [link boost_asio.reference.serial_port_base__parity serial_port_base::parity], diff --git a/doc/overview/signals.qbk b/doc/overview/signals.qbk index 1eb02f985e..8b83782a11 100644 --- a/doc/overview/signals.qbk +++ b/doc/overview/signals.qbk @@ -27,7 +27,7 @@ however the signal number must be used only with Boost.Asio. ... // Construct a signal set registered for process termination. - boost::asio::signal_set signals(io_service, SIGINT, SIGTERM); + boost::asio::signal_set signals(io_context, SIGINT, SIGTERM); // Start an asynchronous wait for one of the signals to occur. signals.async_wait(handler); diff --git a/doc/overview/spawn.qbk b/doc/overview/spawn.qbk index bea7b02820..03d917e5b9 100644 --- a/doc/overview/spawn.qbk +++ b/doc/overview/spawn.qbk @@ -38,8 +38,8 @@ synchronous manner, as shown in the following example: } The first argument to `spawn()` may be a -[link boost_asio.reference.io_service__strand `strand`], -[link boost_asio.reference.io_service `io_service`], or +[link boost_asio.reference.io_context__strand `strand`], +[link boost_asio.reference.io_context `io_context`], or [link boost_asio.reference.CompletionHandler completion handler]. This argument determines the context in which the coroutine is permitted to execute. For example, a server's per-client object may consist of multiple diff --git a/doc/overview/ssl.qbk b/doc/overview/ssl.qbk index 693a07908e..529af15db4 100644 --- a/doc/overview/ssl.qbk +++ b/doc/overview/ssl.qbk @@ -22,7 +22,7 @@ initialisation may look something like: To use SSL with a TCP socket, one may write: - ssl::stream ssl_sock(my_io_service, ctx); + ssl::stream ssl_sock(my_io_context, ctx); To perform socket-specific operations, such as establishing an outbound connection or accepting an incoming one, the underlying socket must first be @@ -36,7 +36,7 @@ In some use cases the underlying stream object will need to have a longer lifetime than the SSL stream, in which case the template parameter should be a reference to the stream type: - ip::tcp::socket sock(my_io_service); + ip::tcp::socket sock(my_io_context); ssl::stream ssl_sock(sock, ctx); SSL handshaking must be performed prior to transmitting or receiving data over @@ -82,9 +82,9 @@ according to the rules used by HTTPS: ctx.set_default_verify_paths(); // Open a socket and connect it to the remote host. - boost::asio::io_service io_service; - ssl_socket sock(io_service, ctx); - tcp::resolver resolver(io_service); + boost::asio::io_context io_context; + ssl_socket sock(io_context, ctx); + tcp::resolver resolver(io_context); tcp::resolver::query query("host.name", "https"); boost::asio::connect(sock.lowest_layer(), resolver.resolve(query)); sock.lowest_layer().set_option(tcp::no_delay(true)); diff --git a/doc/overview/strands.qbk b/doc/overview/strands.qbk index 7f9bd243d3..16bb04efb4 100644 --- a/doc/overview/strands.qbk +++ b/doc/overview/strands.qbk @@ -15,8 +15,8 @@ mutexes). Strands may be either implicit or explicit, as illustrated by the following alternative approaches: -* Calling io_service::run() from only one thread means all event handlers - execute in an implicit strand, due to the io_service's guarantee that handlers +* Calling io_context::run() from only one thread means all event handlers + execute in an implicit strand, due to the io_context's guarantee that handlers are only invoked from inside run(). * Where there is a single chain of asynchronous operations associated with a @@ -24,38 +24,61 @@ alternative approaches: no possibility of concurrent execution of the handlers. This is an implicit strand. -* An explicit strand is an instance of `io_service::strand`. All event handler - function objects need to be wrapped using `io_service::strand::wrap()` or - otherwise posted/dispatched through the `io_service::strand` object. +* An explicit strand is an instance of `strand<>` or `io_context::strand`. All + event handler function objects need to be bound to the strand using + `boost::asio::bind_executor()` or otherwise posted/dispatched through the strand + object. In the case of composed asynchronous operations, such as `async_read()` or `async_read_until()`, if a completion handler goes through a strand, then all intermediate handlers should also go through the same strand. This is needed to ensure thread safe access for any objects that are shared between the caller and the composed operation (in the case of `async_read()` it's the socket, -which the caller can close() to cancel the operation). This is done by having -hook functions for all intermediate handlers which forward the calls to the -customisable hook associated with the final handler: +which the caller can `close()` to cancel the operation). + +This is done by partially specialising the `boost::asio::ssociated_executor<>` trait +for all intermediate handlers. This trait forwards to the corresponding trait +specialisation for the final handler: struct my_handler { void operator()() { ... } }; - template - void asio_handler_invoke(F f, my_handler*) - { - // Do custom invocation here. - // Default implementation calls f(); - } + namespace boost { namespace asio { + + template + struct associated_executor + { + // Custom implementation of Executor type requirements. + typedef my_executor type; + + // Return a custom executor implementation. + static type get(const my_handler&, const Executor& = Executor()) + { + return my_executor(); + } + }; + + } } // namespace boost::asio + +The `boost::asio::bind_executor()` function is a helper to bind a specific executor +object, such as a strand, to a completion handler. This binding automatically +specialises the `associated_executor` trait as shown above. For example, to +bind a strand to a completion handler we would simply write: -The `io_service::strand::wrap()` function creates a new completion handler that -defines `asio_handler_invoke` so that the function object is executed through -the strand. + my_socket.async_read_some(my_buffer, + boost::asio::bind_executor(my_strand, + [](error_code ec, size_t length) + { + // ... + })); [heading See Also] -[link boost_asio.reference.io_service__strand io_service::strand], +[link boost_asio.reference.bind_executor bind_executor], +[link boost_asio.reference.strand strand], +[link boost_asio.reference.io_context__strand io_context::strand], [link boost_asio.tutorial.tuttimer5 tutorial Timer.5], [link boost_asio.examples.cpp03_examples.http_server_3 HTTP server 3 example]. diff --git a/doc/overview/threads.qbk b/doc/overview/threads.qbk index 23839a043d..7543676afc 100644 --- a/doc/overview/threads.qbk +++ b/doc/overview/threads.qbk @@ -10,19 +10,19 @@ [heading Thread Safety] In general, it is safe to make concurrent use of distinct objects, but unsafe -to make concurrent use of a single object. However, types such as `io_service` +to make concurrent use of a single object. However, types such as `io_context` provide a stronger guarantee that it is safe to use a single object concurrently. [heading Thread Pools] -Multiple threads may call `io_service::run()` to set up a pool of threads from +Multiple threads may call `io_context::run()` to set up a pool of threads from which completion handlers may be invoked. This approach may also be used with -`io_service::post()` to use a means to perform any computational tasks across a +`io_context::post()` to use a means to perform any computational tasks across a thread pool. -Note that all threads that have joined an `io_service`'s pool are considered -equivalent, and the `io_service` may distribute work across them in an +Note that all threads that have joined an `io_context`'s pool are considered +equivalent, and the `io_context` may distribute work across them in an arbitrary fashion. [heading Internal Threads] @@ -38,14 +38,14 @@ these threads must be invisible to the library user. In particular, the threads: This approach is complemented by the following guarantee: * Asynchronous completion handlers will only be called from threads that are - currently calling `io_service::run()`. + currently calling `io_context::run()`. Consequently, it is the library user's responsibility to create and manage all threads to which the notifications will be delivered. The reasons for this approach include: -* By only calling `io_service::run()` from a single thread, the user's code can +* By only calling `io_context::run()` from a single thread, the user's code can avoid the development complexity associated with synchronisation. For example, a library user can implement scalable servers that are single-threaded (from the user's point of view). @@ -61,6 +61,6 @@ The reasons for this approach include: [heading See Also] -[link boost_asio.reference.io_service io_service]. +[link boost_asio.reference.io_context io_context]. [endsect] diff --git a/doc/overview/timers.qbk b/doc/overview/timers.qbk index ec22a54dfa..50fd76d4d4 100644 --- a/doc/overview/timers.qbk +++ b/doc/overview/timers.qbk @@ -14,7 +14,7 @@ calculated relative to the current time. As a simple example, to perform a synchronous wait operation on a timer using a relative time one may write: - io_service i; + io_context i; ... deadline_timer t(i); t.expires_from_now(boost::posix_time::seconds(5)); @@ -25,7 +25,7 @@ timer: void handler(boost::system::error_code ec) { ... } ... - io_service i; + io_context i; ... deadline_timer t(i); t.expires_from_now(boost::posix_time::milliseconds(400)); @@ -47,7 +47,6 @@ or as an absolute time to allow composition of timers: [link boost_asio.reference.basic_deadline_timer basic_deadline_timer], [link boost_asio.reference.deadline_timer deadline_timer], -[link boost_asio.reference.deadline_timer_service deadline_timer_service], [link boost_asio.tutorial.tuttimer1 timer tutorials]. [endsect] diff --git a/doc/overview/windows.qbk b/doc/overview/windows.qbk index eba696fdd5..26c1111e03 100644 --- a/doc/overview/windows.qbk +++ b/doc/overview/windows.qbk @@ -22,7 +22,7 @@ For example, to perform asynchronous operations on a named pipe, the following object may be created: HANDLE handle = ::CreateFile(...); - windows::stream_handle pipe(my_io_service, handle); + windows::stream_handle pipe(my_io_context, handle); These are then used as synchronous or asynchronous read and write streams. This means the objects can be used with any of the [link boost_asio.reference.read @@ -37,9 +37,7 @@ pipes and console streams are not). [heading See Also] -[link boost_asio.reference.windows__stream_handle windows::stream_handle], -[link boost_asio.reference.windows__basic_stream_handle windows::basic_stream_handle], -[link boost_asio.reference.windows__stream_handle_service windows::stream_handle_service]. +[link boost_asio.reference.windows__stream_handle windows::stream_handle]. [heading Notes] @@ -61,7 +59,7 @@ For example, to perform asynchronous operations on a file the following object may be created: HANDLE handle = ::CreateFile(...); - windows::random_access_handle file(my_io_service, handle); + windows::random_access_handle file(my_io_context, handle); Data may be read from or written to the handle using one of the `read_some_at()`, `async_read_some_at()`, `write_some_at()` or @@ -76,9 +74,7 @@ all data has been transferred. [heading See Also] -[link boost_asio.reference.windows__random_access_handle windows::random_access_handle], -[link boost_asio.reference.windows__basic_random_access_handle windows::basic_random_access_handle], -[link boost_asio.reference.windows__random_access_handle_service windows::random_access_handle_service]. +[link boost_asio.reference.windows__random_access_handle windows::random_access_handle]. [heading Notes] @@ -110,16 +106,14 @@ For example, to perform asynchronous operations on an event, the following object may be created: HANDLE handle = ::CreateEvent(...); - windows::object_handle file(my_io_service, handle); + windows::object_handle file(my_io_context, handle); The `wait()` and `async_wait()` member functions may then be used to wait until the kernel object is signalled. [heading See Also] -[link boost_asio.reference.windows__object_handle windows::object_handle], -[link boost_asio.reference.windows__basic_object_handle windows::basic_object_handle], -[link boost_asio.reference.windows__object_handle_service windows::object_handle_service]. +[link boost_asio.reference.windows__object_handle windows::object_handle]. [heading Notes] diff --git a/doc/reference.xsl b/doc/reference.xsl index 557d2e5eeb..fcabb59379 100644 --- a/doc/reference.xsl +++ b/doc/reference.xsl @@ -37,57 +37,51 @@ [xinclude quickref.xml] [include requirements/asynchronous_operations.qbk] +[include requirements/read_write_operations.qbk] +[include requirements/synchronous_socket_operations.qbk] +[include requirements/asynchronous_socket_operations.qbk] +[include requirements/AcceptableProtocol.qbk] [include requirements/AcceptHandler.qbk] [include requirements/AsyncRandomAccessReadDevice.qbk] [include requirements/AsyncRandomAccessWriteDevice.qbk] [include requirements/AsyncReadStream.qbk] [include requirements/AsyncWriteStream.qbk] [include requirements/BufferedHandshakeHandler.qbk] +[include requirements/CompletionCondition.qbk] [include requirements/CompletionHandler.qbk] -[include requirements/ComposedConnectHandler.qbk] +[include requirements/ConnectCondition.qbk] [include requirements/ConnectHandler.qbk] [include requirements/ConstBufferSequence.qbk] -[include requirements/ConvertibleToConstBuffer.qbk] -[include requirements/ConvertibleToMutableBuffer.qbk] -[include requirements/DatagramSocketService.qbk] -[include requirements/DescriptorService.qbk] +[include requirements/DynamicBuffer.qbk] [include requirements/Endpoint.qbk] +[include requirements/EndpointSequence.qbk] +[include requirements/ExecutionContext.qbk] +[include requirements/Executor.qbk] [include requirements/GettableSerialPortOption.qbk] [include requirements/GettableSocketOption.qbk] [include requirements/Handler.qbk] -[include requirements/HandleService.qbk] [include requirements/HandshakeHandler.qbk] [include requirements/InternetProtocol.qbk] [include requirements/IoControlCommand.qbk] [include requirements/IoObjectService.qbk] +[include requirements/IteratorConnectHandler.qbk] +[include requirements/MoveAcceptHandler.qbk] [include requirements/MutableBufferSequence.qbk] -[include requirements/ObjectHandleService.qbk] +[include requirements/ProtoAllocator.qbk] [include requirements/Protocol.qbk] -[include requirements/RandomAccessHandleService.qbk] -[include requirements/RawSocketService.qbk] +[include requirements/RangeConnectHandler.qbk] [include requirements/ReadHandler.qbk] [include requirements/ResolveHandler.qbk] -[include requirements/ResolverService.qbk] -[include requirements/SeqPacketSocketService.qbk] -[include requirements/SerialPortService.qbk] [include requirements/Service.qbk] [include requirements/SettableSerialPortOption.qbk] [include requirements/SettableSocketOption.qbk] [include requirements/ShutdownHandler.qbk] [include requirements/SignalHandler.qbk] -[include requirements/SignalSetService.qbk] -[include requirements/SocketAcceptorService.qbk] -[include requirements/SocketService.qbk] -[include requirements/StreamDescriptorService.qbk] -[include requirements/StreamHandleService.qbk] -[include requirements/StreamSocketService.qbk] [include requirements/SyncRandomAccessReadDevice.qbk] [include requirements/SyncRandomAccessWriteDevice.qbk] [include requirements/SyncReadStream.qbk] [include requirements/SyncWriteStream.qbk] [include requirements/TimeTraits.qbk] -[include requirements/TimerService.qbk] -[include requirements/WaitableTimerService.qbk] [include requirements/WaitHandler.qbk] [include requirements/WaitTraits.qbk] [include requirements/WriteHandler.qbk] @@ -105,7 +99,9 @@ contains(compoundname, 'asio::') and not(contains(compoundname, '::detail')) and not(contains(compoundname, '::service::key')) and - not(contains(compoundname, '_handler'))"> + not(contains(compoundname, '_handler')) and + not(contains(compoundname, 'thread_function')) and + not(contains(compoundname, 'context_impl'))"> @@ -115,7 +111,8 @@ not(contains(ancestor::*/compoundname, '::service::key')) and not(contains(ancestor::*/compoundname, '_helper')) and not(contains(name, '_helper')) and - not(contains(name, 'io_service_impl'))"> + not(contains(name, 'thread_function')) and + not(contains(name, 'io_context_impl'))"> @@ -194,7 +191,7 @@ - ``[link boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` + ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` @@ -302,6 +299,18 @@ select="concat(substring-before($name, '~'), '_', substring-after($name, '~'))"/> + + + + + + + + + + + + + \.\.\. + + + + @@ -752,6 +768,9 @@ None + + None + None @@ -840,7 +859,7 @@ [[Name][Description]] + innerclass[@prot='public' and not(contains(., '_handler')) and not(contains(., 'thread_function'))]" mode="class-table"> [ @@ -977,7 +996,7 @@ ] - + [heading Private Member Functions] [table @@ -1166,7 +1185,7 @@ - + @@ -1191,6 +1210,11 @@ + + + + + @@ -1215,9 +1239,14 @@ ::] [indexterm2 +boost_asio.indexterm. + +. + +.. .. - + ] @@ -1272,9 +1301,14 @@ [indexterm2 + boost_asio.indexterm. + + . + + .. .. - + ] @@ -1293,6 +1327,7 @@ + @@ -1365,11 +1400,17 @@ + enum [indexterm2 + boost_asio.indexterm. + + . + + .. .. @@ -1431,24 +1472,30 @@ + + + - + - + - + + + + @@ -1461,6 +1508,12 @@ + + + + + + @@ -1476,9 +1529,18 @@ + + + + + + + + + @@ -1491,6 +1553,12 @@ + + + + + + @@ -1527,6 +1595,9 @@ + + + @@ -1602,6 +1673,9 @@ [section: ] [indexterm1 +boost_asio.indexterm. + +.. ] @@ -1655,6 +1729,9 @@ [indexterm1 + boost_asio.indexterm. + + .. ] @@ -1674,6 +1751,7 @@ + diff --git a/doc/requirements/AcceptHandler.qbk b/doc/requirements/AcceptHandler.qbk index b48f4c8519..14cddeb4a8 100644 --- a/doc/requirements/AcceptHandler.qbk +++ b/doc/requirements/AcceptHandler.qbk @@ -35,7 +35,29 @@ An accept handler function object: ... }; -A non-static class member function adapted to an accept handler using `bind()`: +A lambda as an accept handler: + + acceptor.async_accept(..., + [](const boost::system::error_code& ec) + { + ... + }); + +A non-static class member function adapted to an accept handler using +`std::bind()`: + + void my_class::accept_handler( + const boost::system::error_code& ec) + { + ... + } + ... + acceptor.async_accept(..., + std::bind(&my_class::accept_handler, + this, std::placeholders::_1)); + +A non-static class member function adapted to an accept handler using +`boost::bind()`: void my_class::accept_handler( const boost::system::error_code& ec) diff --git a/doc/requirements/AcceptableProtocol.qbk b/doc/requirements/AcceptableProtocol.qbk new file mode 100644 index 0000000000..50d575e3e3 --- /dev/null +++ b/doc/requirements/AcceptableProtocol.qbk @@ -0,0 +1,25 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:AcceptableProtocol Acceptable protocol requirements] + +A type `X` meets the `AcceptableProtocol` requirements if it satisfies the +requirements of [link boost_asio.reference.Protocol `Protocol`] as well as the +additional requirements listed below. + +[table AcceptableProtocol requirements + [[expression] [return type] [assertion/note\npre/post-conditions]] + [ + [`X::socket`] + [A type that satisfies the requirements of `Destructible` (C++Std + \[destructible\]) and `MoveConstructible` (C++Std \[moveconstructible\]), + and that is publicly and unambiguously derived from `basic_socket`.] + [] + ] +] + +[endsect] diff --git a/doc/requirements/AsyncRandomAccessReadDevice.qbk b/doc/requirements/AsyncRandomAccessReadDevice.qbk index e9e0ae5be3..0ef84f727f 100644 --- a/doc/requirements/AsyncRandomAccessReadDevice.qbk +++ b/doc/requirements/AsyncRandomAccessReadDevice.qbk @@ -17,10 +17,9 @@ boost_asio.reference.ReadHandler read handler] requirements. [table Buffer-oriented asynchronous random-access read device requirements [[operation] [type] [semantics, pre/post-conditions]] [ - [`a.get_io_service();`] - [`io_service&`] - [Returns the `io_service` object through which the `async_read_some_at` - handler `h` will be invoked.] + [`a.get_executor()`] + [A type satisfying the [link boost_asio.reference.Executor1 Executor requirements].] + [Returns the associated I/O executor.] ] [ [`a.async_read_some_at(o, mb, h);`] diff --git a/doc/requirements/AsyncRandomAccessWriteDevice.qbk b/doc/requirements/AsyncRandomAccessWriteDevice.qbk index d9ea1daf00..ca2e4c2a8b 100644 --- a/doc/requirements/AsyncRandomAccessWriteDevice.qbk +++ b/doc/requirements/AsyncRandomAccessWriteDevice.qbk @@ -17,10 +17,9 @@ boost_asio.reference.WriteHandler write handler] requirements. [table Buffer-oriented asynchronous random-access write device requirements [[operation] [type] [semantics, pre/post-conditions]] [ - [`a.get_io_service();`] - [`io_service&`] - [Returns the `io_service` object through which the `async_write_some_at` - handler `h` will be invoked.] + [`a.get_executor()`] + [A type satisfying the [link boost_asio.reference.Executor1 Executor requirements].] + [Returns the associated I/O executor.] ] [ [`a.async_write_some_at(o, cb, h);`] diff --git a/doc/requirements/AsyncReadStream.qbk b/doc/requirements/AsyncReadStream.qbk index a832aa15f7..873a6cb87c 100644 --- a/doc/requirements/AsyncReadStream.qbk +++ b/doc/requirements/AsyncReadStream.qbk @@ -7,48 +7,42 @@ [section:AsyncReadStream Buffer-oriented asynchronous read stream requirements] -In the table below, `a` denotes an asynchronous read stream object, `mb` -denotes an object satisfying [link -boost_asio.reference.MutableBufferSequence mutable buffer sequence] -requirements, and `h` denotes an object satisfying [link -boost_asio.reference.ReadHandler read handler] requirements. +A type `X` meets the `AsyncReadStream` requirements if it satisfies the +requirements listed below. -[table Buffer-oriented asynchronous read stream requirements +In the table below, `a` denotes a value of type `X`, `mb` denotes a (possibly +const) value satisfying the [link boost_asio.reference.MutableBufferSequence +`MutableBufferSequence`] requirements, and `t` is a completion token. + +[table AsyncReadStream requirements [[operation] [type] [semantics, pre/post-conditions]] [ - [`a.get_io_service();`] - [`io_service&`] - [Returns the `io_service` object through which the `async_read_some` - handler `h` will be invoked.] + [`a.get_executor()`] + [A type satisfying the [link boost_asio.reference.Executor1 Executor requirements].] + [Returns the associated I/O executor.] ] [ - [`a.async_read_some(mb, h);`] - [`void`] + [`a.async_read_some(mb,t)`] [ - Initiates an asynchronous operation to read one or more bytes of data - from the stream `a`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The `async_read_some` operation shall always fill a buffer in - the sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous read operation is invoked,\n + The return type is determined according to the requirements for an + [link boost_asio.reference.asynchronous_operations asynchronous operation]. + ] + [ + Meets the requirements for a [link boost_asio.reference.read_write_operations + read operation] and an [link boost_asio.reference.asynchronous_operations + asynchronous operation] with completion signature `void(error_code ec, + size_t n)`.\n \n - whichever comes first.\n + If `buffer_size(mb) > 0`, initiates an asynchronous operation to read one + or more bytes of data from the stream `a` into the buffer sequence `mb`. + If successful, `ec` is set such that `!ec` is `true`, and `n` is the + number of bytes read. If an error occurred, `ec` is set such that `!!ec` + is `true`, and `n` is 0. If all data has been read from the stream, and + the stream performed an orderly shutdown, `ec` is + `stream_errc::eof` and `n` is 0.\n \n - If the total size of all buffers in the sequence `mb` is `0`, the - asynchronous read operation shall complete immediately and pass `0` as - the argument to the handler that specifies the number of bytes read. + If `buffer_size(mb) == 0`, the operation completes immediately. `ec` is + set such that `!ec` is `true`, and `n` is 0. ] ] ] diff --git a/doc/requirements/AsyncWriteStream.qbk b/doc/requirements/AsyncWriteStream.qbk index 9430b85724..4aa3bdeb0d 100644 --- a/doc/requirements/AsyncWriteStream.qbk +++ b/doc/requirements/AsyncWriteStream.qbk @@ -7,47 +7,40 @@ [section:AsyncWriteStream Buffer-oriented asynchronous write stream requirements] -In the table below, `a` denotes an asynchronous write stream object, `cb` -denotes an object satisfying [link boost_asio.reference.ConstBufferSequence -constant buffer sequence] requirements, and `h` denotes an object satisfying -[link boost_asio.reference.WriteHandler write handler] requirements. +A type `X` meets the `AsyncWriteStream` requirements if it satisfies the +requirements listed below. -[table Buffer-oriented asynchronous write stream requirements +In the table below, `a` denotes a value of type `X`, `cb` denotes a (possibly +const) value satisfying the [link boost_asio.reference.ConstBufferSequence +`ConstBufferSequence`] requirements, and `t` is a completion token. + +[table AsyncWriteStream requirements [[operation] [type] [semantics, pre/post-conditions]] [ - [`a.get_io_service();`] - [`io_service&`] - [Returns the `io_service` object through which the `async_write_some` - handler `h` will be invoked.] + [`a.get_executor()`] + [A type satisfying the [link boost_asio.reference.Executor1 Executor requirements].] + [Returns the associated I/O executor.] ] [ - [`a.async_write_some(cb, h);`] - [`void`] + [`a.async_write_some(cb,t)`] [ - Initiates an asynchronous operation to write one or more bytes of data to - the stream `a`. The operation is performed via the `io_service` object - `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The `async_write_some` operation shall always write a - buffer in the sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous write operation is invoked,\n + The return type is determined according to the requirements for an + [link boost_asio.reference.asynchronous_operations asynchronous operation]. + ] + [ + Meets the requirements for a [link boost_asio.reference.read_write_operations + write operation] and an [link boost_asio.reference.asynchronous_operations + asynchronous operation] with completion signature `void(error_code ec, + size_t n)`.\n \n - whichever comes first.\n + If `buffer_size(cb) > 0`, initiates an asynchronous operation to write + one or more bytes of data to the stream `a` from the buffer sequence + `cb`. If successful, `ec` is set such that `!ec` is `true`, and `n` is + the number of bytes written. If an error occurred, `ec` is set such that + `!!ec` is `true`, and `n` is 0.\n \n - If the total size of all buffers in the sequence `cb` is `0`, the - asynchronous write operation shall complete immediately and pass `0` as - the argument to the handler that specifies the number of bytes written. + If `buffer_size(cb) == 0`, the operation completes immediately. `ec` is + set such that `!ec` is `true`, and `n` is 0. ] ] ] diff --git a/doc/requirements/BufferedHandshakeHandler.qbk b/doc/requirements/BufferedHandshakeHandler.qbk index bafb53d80d..e3f4a07c1a 100644 --- a/doc/requirements/BufferedHandshakeHandler.qbk +++ b/doc/requirements/BufferedHandshakeHandler.qbk @@ -37,7 +37,8 @@ A buffered handshake handler function object: ... }; -A non-static class member function adapted to a buffered handshake handler using `bind()`: +A non-static class member function adapted to a buffered handshake handler +using `boost::bind()`: void my_class::handshake_handler( const boost::system::error_code& ec, diff --git a/doc/requirements/CompletionCondition.qbk b/doc/requirements/CompletionCondition.qbk new file mode 100644 index 0000000000..3e40a09c87 --- /dev/null +++ b/doc/requirements/CompletionCondition.qbk @@ -0,0 +1,42 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:CompletionCondition Completion condition requirements] + +A ['completion condition] is a function object that is used with the algorithms +[link boost_asio.reference.read `read`], [link boost_asio.reference.async_read +`async_read`], [link boost_asio.reference.write `write`], and [link +boost_asio.reference.async_write `async_write`] to determine when the algorithm has +completed transferring data. + +A type `X` meets the `CompletionCondition` requirements if it satisfies the +requirements of `Destructible` (C++Std [destructible]) and +`CopyConstructible` (C++Std [copyconstructible]), as well as the additional +requirements listed below. + +In the table below, `x` denotes a value of type `X`, `ec` denotes a (possibly +const) value of type `error_code`, and `n` denotes a (possibly const) value of +type `size_t`. + +[table CompletionCondition requirements + [[expression] [return type] [assertion/note\npre/post-condition]] + [ + [`x(ec, n)`] + [`size_t`] + [ + Let `n` be the total number of bytes transferred by the read or write + algorithm so far.\n + \n + Returns the maximum number of bytes to be transferred on the next + `read_some`, `async_read_some`, `write_some`, or `async_write_some` + operation performed by the algorithm. Returns `0` to indicate that the + algorithm is complete. + ] + ] +] + +[endsect] diff --git a/doc/requirements/CompletionHandler.qbk b/doc/requirements/CompletionHandler.qbk index 349f08390e..b6b1d3d78f 100644 --- a/doc/requirements/CompletionHandler.qbk +++ b/doc/requirements/CompletionHandler.qbk @@ -32,8 +32,26 @@ A completion handler function object: ... }; +A lambda as a completion handler: + + my_io_service.post( + []() + { + ... + }); + +A non-static class member function adapted to a completion handler using +`std::bind()`: + + void my_class::completion_handler() + { + ... + } + ... + my_io_service.post(std::bind(&my_class::completion_handler, this)); + A non-static class member function adapted to a completion handler using -`bind()`: +`boost::bind()`: void my_class::completion_handler() { diff --git a/doc/requirements/ConnectCondition.qbk b/doc/requirements/ConnectCondition.qbk new file mode 100644 index 0000000000..fa68c76d0e --- /dev/null +++ b/doc/requirements/ConnectCondition.qbk @@ -0,0 +1,34 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:ConnectCondition Connect condition requirements] + +A type `X` meets the `ConnectCondition` requirements if it satisfies the +requirements of `Destructible` (C++Std [destructible]) and +`CopyConstructible` (C++Std [copyconstructible]), as well as the additional +requirements listed below. + +In the table below, `x` denotes a value of type `X`, `ec` denotes a (possibly +const) value of type `error_code`, and `ep` denotes a (possibly const) value of +some type satisfying the [link boost_asio.reference.Endpoint endpoint] requirements. + +[table ConnectCondition requirements + [[expression] [return type] [assertion/note\npre/post-condition]] + [ + [`x(ec, ep)`] + [`bool`] + [ + Returns `true` to indicate that the `connect` or `async_connect` + algorithm should attempt a connection to the endpoint `ep`. Otherwise, + returns `false` to indicate that the algorithm should not attempt + connection to the endpoint `ep`, and should instead skip to the next + endpoint in the sequence. + ] + ] +] + +[endsect] diff --git a/doc/requirements/ConnectHandler.qbk b/doc/requirements/ConnectHandler.qbk index bef8434ef4..1a29ca5ea4 100644 --- a/doc/requirements/ConnectHandler.qbk +++ b/doc/requirements/ConnectHandler.qbk @@ -35,7 +35,29 @@ A connect handler function object: ... }; -A non-static class member function adapted to a connect handler using `bind()`: +A lambda as a connect handler: + + socket.async_connect(..., + [](const boost::system::error_code& ec) + { + ... + }); + +A non-static class member function adapted to a connect handler using +`std::bind()`: + + void my_class::connect_handler( + const boost::system::error_code& ec) + { + ... + } + ... + socket.async_connect(..., + std::bind(&my_class::connect_handler, + this, std::placeholders::_1)); + +A non-static class member function adapted to a connect handler using +`boost::bind()`: void my_class::connect_handler( const boost::system::error_code& ec) diff --git a/doc/requirements/ConstBufferSequence.qbk b/doc/requirements/ConstBufferSequence.qbk index f708392abf..8c3306859f 100644 --- a/doc/requirements/ConstBufferSequence.qbk +++ b/doc/requirements/ConstBufferSequence.qbk @@ -7,96 +7,49 @@ [section:ConstBufferSequence Constant buffer sequence requirements] -In the table below, `X` denotes a class containing objects of type `T`, `a` -denotes a value of type `X` and `u` denotes an identifier. +A ['constant buffer sequence] represents a set of memory regions that may be +used as input to an operation, such as the `send` operation of a socket. + +A type `X` meets the `ConstBufferSequence` requirements if it satisfies the +requirements of `Destructible` (C++Std [destructible]) and +`CopyConstructible` (C++Std [copyconstructible]), as well as the additional +requirements listed below. + +In the table below, `x` denotes a (possibly const) value of type `X`, and `u` +denotes an identifier. [table ConstBufferSequence requirements [[expression] [return type] [assertion/note\npre/post-condition]] [ - [`X::value_type`] - [`T`] - [`T` meets the requirements for [link - boost_asio.reference.ConvertibleToConstBuffer - ConvertibleToConstBuffer].] - ] - [ - [`X::const_iterator`] - [iterator type pointing to `T`] - [`const_iterator` meets the requirements for bidirectional iterators - (C++ Std, 24.1.4).] - ] - [ - [`X(a);`] + [`boost::asio::buffer_sequence_begin(x)`\n + `boost::asio::buffer_sequence_end(x)`] + [An iterator type meeting the requirements for bidirectional iterators + (C++Std \[bidirectional.iterators\]) whose value type is convertible to + `const_buffer`.] [] - [post: `equal_const_buffer_seq(a, X(a))` where the binary predicate - `equal_const_buffer_seq` is defined as - `` - bool equal_const_buffer_seq( - const X& x1, const X& x2) - { - return - distance(x1.begin(), x1.end()) - == distance(x2.begin(), x2.end()) - && equal(x1.begin(), x1.end(), - x2.begin(), equal_buffer); - } - `` - and the binary predicate `equal_buffer` is defined as - `` - bool equal_buffer( - const X::value_type& v1, - const X::value_type& v2) - { - const_buffer b1(v1); - const_buffer b2(v2); - return - buffer_cast(b1) - == buffer_cast(b2) - && buffer_size(b1) == buffer_size(b2); - } - ``] ] [ - [`X u(a);`] + [`` + X u(x); + ``] [] - [post: + [post:\n `` - distance(a.begin(), a.end()) - == distance(u.begin(), u.end()) - && equal(a.begin(), a.end(), - u.begin(), equal_buffer) - `` - where the binary predicate `equal_buffer` is defined as - `` - bool equal_buffer( - const X::value_type& v1, - const X::value_type& v2) - { - const_buffer b1(v1); - const_buffer b2(v2); - return - buffer_cast(b1) - == buffer_cast(b2) - && buffer_size(b1) == buffer_size(b2); - } + equal( + boost::asio::buffer_sequence_begin(x), + boost::asio::buffer_sequence_end(x), + boost::asio::buffer_sequence_begin(u), + boost::asio::buffer_sequence_end(u), + [](const typename X::value_type& v1, + const typename X::value_type& v2) + { + const_buffer b1(v1); + const_buffer b2(v2); + return b1.data() == b2.data() + && b1.size() == b2.size(); + }) ``] ] - [ - [`(&a)->~X();`] - [`void`] - [note: the destructor is applied to every element of `a`; all the memory - is deallocated.] - ] - [ - [`a.begin();`] - [`const_iterator` or convertible to `const_iterator`] - [] - ] - [ - [`a.end();`] - [`const_iterator` or convertible to `const_iterator`] - [] - ] ] [endsect] diff --git a/doc/requirements/ConvertibleToConstBuffer.qbk b/doc/requirements/ConvertibleToConstBuffer.qbk deleted file mode 100644 index 269c4a7fdb..0000000000 --- a/doc/requirements/ConvertibleToConstBuffer.qbk +++ /dev/null @@ -1,96 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:ConvertibleToConstBuffer Convertible to const buffer requirements] - -A type that meets the requirements for convertibility to a const buffer must -meet the requirements of `CopyConstructible` types (C++ Std, 20.1.3), and the -requirements of `Assignable` types (C++ Std, 23.1). - -In the table below, `X` denotes a class meeting the requirements for -convertibility to a const buffer, `a` and `b` denote values of type `X`, and -`u`, `v` and `w` denote identifiers. - -[table ConvertibleToConstBuffer requirements - [[expression][postcondition]] - [ - [`` - const_buffer u(a); - const_buffer v(a); - ``] - [`` - buffer_cast(u) == buffer_cast(v) - && buffer_size(u) == buffer_size(v) - ``] - ] - [ - [`` - const_buffer u(a); - const_buffer v = a; - ``] - [`` - buffer_cast(u) == buffer_cast(v) - && buffer_size(u) == buffer_size(v) - ``] - ] - [ - [`` - const_buffer u(a); - const_buffer v; v = a; - ``] - [`` - buffer_cast(u) == buffer_cast(v) - && buffer_size(u) == buffer_size(v) - ``] - ] - [ - [`` - const_buffer u(a); - const X& v = a; - const_buffer w(v); - ``] - [`` - buffer_cast(u) == buffer_cast(w) - && buffer_size(u) == buffer_size(w) - ``] - ] - [ - [`` - const_buffer u(a); - X v(a); - const_buffer w(v); - ``] - [`` - buffer_cast(u) == buffer_cast(w) - && buffer_size(u) == buffer_size(w) - ``] - ] - [ - [`` - const_buffer u(a); - X v = a; - const_buffer w(v); - ``] - [`` - buffer_cast(u) == buffer_cast(w) - && buffer_size(u) == buffer_size(w) - ``] - ] - [ - [`` - const_buffer u(a); - X v(b); v = a; - const_buffer w(v); - ``] - [`` - buffer_cast(u) == buffer_cast(w) - && buffer_size(u) == buffer_size(w) - ``] - ] -] - -[endsect] diff --git a/doc/requirements/ConvertibleToMutableBuffer.qbk b/doc/requirements/ConvertibleToMutableBuffer.qbk deleted file mode 100644 index 75de88bdc1..0000000000 --- a/doc/requirements/ConvertibleToMutableBuffer.qbk +++ /dev/null @@ -1,96 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:ConvertibleToMutableBuffer Convertible to mutable buffer requirements] - -A type that meets the requirements for convertibility to a mutable buffer must -meet the requirements of `CopyConstructible` types (C++ Std, 20.1.3), and the -requirements of `Assignable` types (C++ Std, 23.1). - -In the table below, `X` denotes a class meeting the requirements for -convertibility to a mutable buffer, `a` and `b` denote values of type `X`, and -`u`, `v` and `w` denote identifiers. - -[table ConvertibleToMutableBuffer requirements - [[expression][postcondition]] - [ - [`` - mutable_buffer u(a); - mutable_buffer v(a); - ``] - [`` - buffer_cast(u) == buffer_cast(v) - && buffer_size(u) == buffer_size(v) - ``] - ] - [ - [`` - mutable_buffer u(a); - mutable_buffer v = a; - ``] - [`` - buffer_cast(u) == buffer_cast(v) - && buffer_size(u) == buffer_size(v) - ``] - ] - [ - [`` - mutable_buffer u(a); - mutable_buffer v; v = a; - ``] - [`` - buffer_cast(u) == buffer_cast(v) - && buffer_size(u) == buffer_size(v) - ``] - ] - [ - [`` - mutable_buffer u(a); - const X& v = a; - mutable_buffer w(v); - ``] - [`` - buffer_cast(u) == buffer_cast(w) - && buffer_size(u) == buffer_size(w) - ``] - ] - [ - [`` - mutable_buffer u(a); - X v(a); - mutable_buffer w(v); - ``] - [`` - buffer_cast(u) == buffer_cast(w) - && buffer_size(u) == buffer_size(w) - ``] - ] - [ - [`` - mutable_buffer u(a); - X v = a; - mutable_buffer w(v); - ``] - [`` - buffer_cast(u) == buffer_cast(w) - && buffer_size(u) == buffer_size(w) - ``] - ] - [ - [`` - mutable_buffer u(a); - X v(b); v = a; - mutable_buffer w(v); - ``] - [`` - buffer_cast(u) == buffer_cast(w) - && buffer_size(u) == buffer_size(w) - ``] - ] -] - -[endsect] diff --git a/doc/requirements/DatagramSocketService.qbk b/doc/requirements/DatagramSocketService.qbk deleted file mode 100644 index 7091006370..0000000000 --- a/doc/requirements/DatagramSocketService.qbk +++ /dev/null @@ -1,227 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:DatagramSocketService Datagram socket service requirements] - -A datagram socket service must meet the requirements for a [link -boost_asio.reference.SocketService socket service], as well as the -additional requirements listed below. - -In the table below, `X` denotes a datagram socket service class for protocol -[link boost_asio.reference.Protocol `Protocol`], `a` denotes a value of type -`X`, `b` denotes a value of type `X::implementation_type`, `e` denotes a value -of type `Protocol::endpoint`, `ec` denotes a value of type `error_code`, `f` -denotes a value of type `socket_base::message_flags`, `mb` denotes a value -satisfying [link boost_asio.reference.MutableBufferSequence mutable buffer -sequence] requirements, `rh` denotes a value meeting [link -boost_asio.reference.ReadHandler `ReadHandler`] requirements, `cb` denotes a -value satisfying [link boost_asio.reference.ConstBufferSequence constant -buffer sequence] requirements, and `wh` denotes a value meeting [link -boost_asio.reference.WriteHandler `WriteHandler`] requirements. - -[table DatagramSocketService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.receive(b, mb, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from a connected socket `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - ] - ] - [ - [`a.async_receive(b, mb, f, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from a connected socket `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.receive_from(b, mb, e, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from an unconnected socket `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - ] - ] - [ - [`a.async_receive_from(b, mb, e, f, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from an unconnected socket `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - The program must ensure the object `e` is valid until the handler - for the asynchronous operation is invoked.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.send(b, cb, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to a connected socket `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - ] - ] - [ - [`a.async_send(b, cb, f, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - a connected socket `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] - [ - [`` - const typename Protocol::endpoint& u = e; - a.send_to(b, cb, u, f, ec); - ``] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to an unconnected socket `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - ] - ] - [ - [`` - const typename Protocol::endpoint& u = e; - a.async_send(b, cb, u, f, wh); - ``] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - an unconnected socket `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/DescriptorService.qbk b/doc/requirements/DescriptorService.qbk deleted file mode 100644 index abb9343064..0000000000 --- a/doc/requirements/DescriptorService.qbk +++ /dev/null @@ -1,142 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:DescriptorService Descriptor service requirements] - -A descriptor service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service] with support for movability, -as well as the additional requirements listed below. - -In the table below, `X` denotes a descriptor service class, `a` and `ao` denote -values of type `X`, `b` and `c` denote values of type `X::implementation_type`, -`n` denotes a value of type `X::native_handle_type`, `ec` denotes a value of type -`error_code`, `i` denotes a value meeting [link boost_asio.reference.IoControlCommand -`IoControlCommand`] requirements, and `u` and `v` denote identifiers. - -[table DescriptorService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`X::native_handle_type`] - [] - [ - The implementation-defined native representation of a descriptor. Must - satisfy the requirements of `CopyConstructible` types (C++ Std, 20.1.3), - and the requirements of `Assignable` types (C++ Std, 23.1). - ] - ] - [ - [`a.construct(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly cancels asynchronous operations, as if by calling - `a.close(b, ec)`. - ] - ] - [ - [`` - a.move_construct(b, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - The underlying native representation is moved from `c` to `b`. - ] - ] - [ - [`` - a.move_assign(b, ao, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - Implicitly cancels asynchronous operations associated with `b`, as if by - calling `a.close(b, ec)`. Then the underlying native representation is - moved from `c` to `b`. - ] - ] - [ - [`` - a.assign(b, n, ec); - ``] - [`error_code`] - [ - pre: `!a.is_open(b)`.\n - post: `!!ec || a.is_open(b)`. - ] - ] - [ - [`` - a.is_open(b); - ``] - [`bool`] - [ - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.is_open(v); - ``] - [`bool`] - [ - ] - ] - [ - [`` - a.close(b, ec); - ``] - [`error_code`] - [ - If `a.is_open()` is true, causes any outstanding asynchronous operations - to complete as soon as possible. Handlers for cancelled operations shall - be passed the error code `error::operation_aborted`.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`` - a.native_handle(b); - ``] - [`X::native_handle_type`] - [ - ] - ] - [ - [`` - a.cancel(b, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`.\n - Causes any outstanding asynchronous operations to complete as soon as - possible. Handlers for cancelled operations shall be passed the error - code `error::operation_aborted`. - ] - ] - [ - [`` - a.io_control(b, i, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/DynamicBuffer.qbk b/doc/requirements/DynamicBuffer.qbk new file mode 100644 index 0000000000..594893aabb --- /dev/null +++ b/doc/requirements/DynamicBuffer.qbk @@ -0,0 +1,93 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:DynamicBuffer Dynamic buffer requirements] + +A dynamic buffer encapsulates memory storage that may be automatically resized +as required, where the memory is divided into an input sequence followed by an +output sequence. These memory regions are internal to the dynamic buffer +sequence, but direct access to the elements is provided to permit them to be +efficiently used with I/O operations, such as the `send` or `receive` +operations of a socket. Data written to the output sequence of a dynamic buffer +sequence object is appended to the input sequence of the same object. + +A dynamic buffer type `X` shall satisfy the requirements of `MoveConstructible` +(C++ Std, [moveconstructible]) types in addition to those listed below. + +In the table below, `X` denotes a dynamic buffer class, `x` denotes a +value of type `X&`, `x1` denotes values of type `const X&`, and `n` denotes a +value of type `size_t`, and `u` denotes an identifier. + +[table DynamicBuffer requirements + [[expression] [type] [assertion/note\npre/post-conditions]] + [ + [`X::const_buffers_type`] + [type meeting [link boost_asio.reference.ConstBufferSequence ConstBufferSequence] + requirements.] + [This type represents the memory associated with the input sequence.] + ] + [ + [`X::mutable_buffers_type`] + [type meeting [link boost_asio.reference.MutableBufferSequence MutableBufferSequence] + requirements.] + [This type represents the memory associated with the output sequence.] + ] + [ + [`x1.size()`] + [`size_t`] + [Returns the size, in bytes, of the input sequence.] + ] + [ + [`x1.max_size()`] + [`size_t`] + [Returns the permitted maximum of the sum of the sizes of the input + sequence and output sequence.] + ] + [ + [`x1.capacity()`] + [`size_t`] + [Returns the maximum sum of the sizes of the input sequence and output + sequence that the dynamic buffer can hold without requiring reallocation.] + ] + [ + [`x1.data()`] + [`X::const_buffers_type`] + [Returns a constant buffer sequence `u` that represents the memory + associated with the input sequence, and where `buffer_size(u) == size()`.] + ] + [ + [`x.prepare(n)`] + [`X::mutable_buffers_type`] + [Requires: `size() + n <= max_size()`.\n + \n + Returns a mutable buffer sequence `u` representing the output sequence, and + where `buffer_size(u) == n`. The dynamic buffer reallocates memory as + required. All constant or mutable buffer sequences previously obtained + using `data()` or `prepare()` are invalidated.\n + \n + Throws: `length_error` if `size() + n > max_size()`.] + ] + [ + [`x.commit(n)`] + [] + [Appends `n` bytes from the start of the output sequence to the end of the + input sequence. The remainder of the output sequence is discarded. If `n` + is greater than the size of the output sequence, the entire output sequence + is appended to the input sequence. All constant or mutable buffer sequences + previously obtained using `data()` or `prepare()` are invalidated.] + ] + [ + [`x.consume(n)`] + [] + [Removes `n` bytes from beginning of the input sequence. If `n` is greater + than the size of the input sequence, the entire input sequence is removed. + All constant or mutable buffer sequences previously obtained using `data()` + or `prepare()` are invalidated.] + ] +] + +[endsect] diff --git a/doc/requirements/Endpoint.qbk b/doc/requirements/Endpoint.qbk index 074bc01ff7..38ea74282a 100644 --- a/doc/requirements/Endpoint.qbk +++ b/doc/requirements/Endpoint.qbk @@ -7,84 +7,85 @@ [section:Endpoint Endpoint requirements] -An endpoint must meet the requirements of `CopyConstructible` types (C++ Std, -20.1.3), and the requirements of `Assignable` types (C++ Std, 23.1). +A type `X` meets the `Endpoint` requirements if it satisfies the requirements +of `Destructible` (C++Std [destructible]), `DefaultConstructible` (C++Std +[defaultconstructible]), `CopyConstructible` (C++Std [copyconstructible]), +and `CopyAssignable` (C++Std [copyassignable]), as well as the additional +requirements listed below. -In the table below, `X` denotes an endpoint class, `a` denotes a value of type -`X`, `s` denotes a size in bytes, and `u` denotes an identifier. +In the table below, `a` denotes a (possibly const) value of type `X`, and `u` +denotes an identifier. [table Endpoint requirements [[expression] [type] [assertion/note\npre/post-conditions]] [ [`X::protocol_type`] - [type meeting [link boost_asio.reference.Protocol protocol] requirements] + [type meeting [link boost_asio.reference.Protocol `Protocol`] requirements] [] ] [ - [`X u;`] - [] - [] - ] - [ - [`X();`] - [] - [] - ] - [ - [`a.protocol();`] + [`a.protocol()`] [`protocol_type`] [] ] +] + +In the table below, `a` denotes a (possibly const) value of type `X`, `b` +denotes a value of type `X`, and `s` denotes a (possibly const) value of a type +that is convertible to `size_t` and denotes a size in bytes. + +[table Endpoint requirements for extensible implementations + [[expression] [type] [assertion/note\npre/post-conditions]] [ - [`a.data();`] - [a pointer] + [`a.data()`] + [`const void*`] [ Returns a pointer suitable for passing as the /address/ argument to - __POSIX__ functions such as __accept__, __getpeername__, __getsockname__ - and __recvfrom__. The implementation shall perform a - `reinterpret_cast` on the pointer to convert it to `sockaddr*`. + functions such as __POSIX__ __connect__, or as the /dest_addr/ argument + to functions such as __POSIX__ __sendto__. The implementation shall + perform a `static_cast` on the pointer to convert it to `const + sockaddr*`. ] ] [ - [`const X& u = a; - u.data();`] - [a pointer] + [`b.data()`] + [`void*`] [ Returns a pointer suitable for passing as the /address/ argument to - __POSIX__ functions such as __connect__, or as the /dest_addr/ argument - to __POSIX__ functions such as __sendto__. The implementation shall - perform a `reinterpret_cast` on the pointer to convert it to `const - sockaddr*`. + functions such as __POSIX__ __accept__, __getpeername__, __getsockname__ + and __recvfrom__. The implementation shall perform a `static_cast` on the + pointer to convert it to `sockaddr*`. ] ] [ - [`a.size();`] + [`a.size()`] [`size_t`] [ Returns a value suitable for passing as the /address_len/ argument - to __POSIX__ functions such as __connect__, or as the /dest_len/ argument - to __POSIX__ functions such as __sendto__, after appropriate integer + to functions such as __POSIX__ __connect__, or as the /dest_len/ argument + to functions such as __POSIX__ __sendto__, after appropriate integer conversion has been performed. ] ] [ - [`a.resize(s);`] + [`b.resize(s)`] [] [ + pre: `s >= 0`\n post: `a.size() == s`\n - Passed the value contained in the /address_len/ argument to __POSIX__ - functions such as __accept__, __getpeername__, __getsockname__ and + Passed the value contained in the /address_len/ argument to functions + such as __POSIX__ __accept__, __getpeername__, __getsockname__ and __recvfrom__, after successful completion of the function. Permitted to - throw an exception if the protocol associated with the endpoint object `a` - does not support the specified size. + throw an exception if the protocol associated with the endpoint object + `a` does not support the specified size. ] ] [ - [`a.capacity();`] + [`a.capacity()`] [`size_t`] [ Returns a value suitable for passing as the /address_len/ argument to - __POSIX__ functions such as __accept__, __getpeername__, __getsockname__ + functions such as __POSIX__ __accept__, __getpeername__, __getsockname__ and __recvfrom__, after appropriate integer conversion has been performed. ] ] diff --git a/doc/requirements/EndpointSequence.qbk b/doc/requirements/EndpointSequence.qbk new file mode 100644 index 0000000000..031fd010e9 --- /dev/null +++ b/doc/requirements/EndpointSequence.qbk @@ -0,0 +1,30 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:EndpointSequence Endpoint sequence requirements] + +A type `X` meets the `EndpointSequence` requirements if it satisfies the +requirements of `Destructible` (C++Std [destructible]) and `CopyConstructible` +(C++Std [copyconstructible]), as well as the additional requirements listed +below. + +In the table below, `x` denotes a (possibly const) value of type `X`. + +[table EndpointSequence requirements + [[expression] [return type] [assertion/note\npre/post-condition]] + [ + [`x.begin()`\n + `x.end()`] + [A type meeting the requirements for forward iterators + (C++Std \[forward.iterators\]) whose value type is convertible to + a type satisfying the [link boost_asio.reference.Endpoint `Endpoint`] + requirements.] + [[half_open_range `x.begin()`,`x.end()`] is a valid range.] + ] +] + +[endsect] diff --git a/doc/requirements/ExecutionContext.qbk b/doc/requirements/ExecutionContext.qbk new file mode 100644 index 0000000000..9d4d87c90a --- /dev/null +++ b/doc/requirements/ExecutionContext.qbk @@ -0,0 +1,36 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:ExecutionContext Execution context requirements] + +A type `X` meets the `ExecutionContext` requirements if it is publicly and +unambiguously derived from `execution_context`, and satisfies the additional +requirements listed below. + +In the table below, `x` denotes a value of type `X`. + +[table ExecutionContext requirements + [[expression] [return type] [assertion/note\npre/post-condition]] + [ + [`X::executor_type`] + [type meeting [link boost_asio.reference.Executor1 `Executor`] requirements] + [] + ] + [ + [`x.~X()`] + [] + [Destroys all unexecuted function objects that were submitted via an + executor object that is associated with the execution context.] + ] + [ + [`x.get_executor()`] + [`X::executor_type`] + [Returns an executor object that is associated with the execution context.] + ] +] + +[endsect] diff --git a/doc/requirements/Executor.qbk b/doc/requirements/Executor.qbk new file mode 100644 index 0000000000..56e521a4e4 --- /dev/null +++ b/doc/requirements/Executor.qbk @@ -0,0 +1,141 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:Executor1 Executor requirements] + +The library describes a standard set of requirements for ['executors]. A type +meeting the `Executor` requirements embodies a set of rules for determining how +submitted function objects are to be executed. + +A type `X` meets the `Executor` requirements if it satisfies the requirements of +`CopyConstructible` (C++Std [copyconstructible]) and `Destructible` (C++Std +[destructible]), as well as the additional requirements listed below. + +No constructor, comparison operator, copy operation, move operation, swap +operation, or member functions `context`, `on_work_started`, and +`on_work_finished` on these types shall exit via an exception. + +The executor copy constructor, comparison operators, and other member functions +defined in these requirements shall not introduce data races as a result of +concurrent calls to those functions from different threads. + +Let `ctx` be the execution context returned by the executor's `context()` +member function. An executor becomes ['invalid] when the first call to +`ctx.shutdown()` returns. The effect of calling `on_work_started`, +`on_work_finished`, `dispatch`, `post`, or `defer` on an invalid executor is +undefined. [inline_note The copy constructor, comparison operators, and +`context()` member function continue to remain valid until `ctx` is destroyed.] + +In the table below, `x1` and `x2` denote (possibly const) values of type `X`, +`mx1` denotes an xvalue of type `X`, `f` denotes a `MoveConstructible` (C++Std +[moveconstructible]) function object callable with zero arguments, `a` denotes +a (possibly const) value of type `A` meeting the `Allocator` requirements +(C++Std [allocator.requirements]), and `u` denotes an identifier. + +[table Executor requirements + [[expression] [type] [assertion/note\npre/post-conditions]] + [ + [`X u(x1);`] + [] + [Shall not exit via an exception.\n + \n + post: `u == x1` and + `std::addressof(u.context()) == std::addressof(x1.context()).`] + ] + [ + [`X u(mx1);`] + [] + [Shall not exit via an exception.\n + \n + post: `u` equals the prior value of `mx1` and + `std::addressof(u.context())` equals the prior value of + `std::addressof(mx1.context())`.] + ] + [ + [`x1 == x2`] + [`bool`] + [ Returns `true` only if `x1` and `x2` can be interchanged with identical + effects in any of the expressions defined in these type requirements. + [inline_note Returning `false` does not necessarily imply that the effects + are not identical.]\n + \n + `operator==` shall be reflexive, symmetric, and transitive, and shall not + exit via an exception.] + ] + [ + [`x1 != x2`] + [`bool`] + [Same as `!(x1 == x2)`.] + ] + [ + [`x1.context()`] + [`execution_context&`, or `E&` where `E` is a type that satifisfies the + [link boost_asio.reference.ExecutionContext `ExecutionContext`] requirements.] + [Shall not exit via an exception.\n + \n + The comparison operators and member functions defined in these + requirements shall not alter the reference returned by this function.] + ] + [ + [`x1.on_work_started()`] + [] + [Shall not exit via an exception.] + ] + [ + [`x1.on_work_finished()`] + [] + [Shall not exit via an exception.\n + \n + Precondition: A preceding call `x2.on_work_started()` where `x1 == x2`.] + ] + [ + [`x1.dispatch(std::move(f),a)`] + [] + [Effects: Creates an object `f1` initialized with + [^['DECAY_COPY]]`(forward(f))` (C++Std \[thread.decaycopy\]) in the + current thread of execution . Calls `f1()` at most once. The executor may + block forward progress of the caller until `f1()` finishes execution.\n + \n + Executor implementations should use the supplied allocator to allocate any + memory required to store the function object. Prior to invoking the + function object, the executor shall deallocate any memory allocated. + [inline_note Executors defined in this Technical Specification always use + the supplied allocator unless otherwise specified.]\n + \n + Synchronization: The invocation of `dispatch` synchronizes with (C++Std + \[intro.multithread\]) the invocation of `f1`.] + ] + [ + [`x1.post(std::move(f),a)`\n + `x1.defer(std::move(f),a)`] + [] + [Effects: Creates an object `f1` initialized with + [^['DECAY_COPY]]`(forward(f))` in the current thread of execution. + Calls `f1()` at most once. The executor shall not block forward progress + of the caller pending completion of `f1()`.\n + \n + Executor implementations should use the supplied allocator to allocate any + memory required to store the function object. Prior to invoking the + function object, the executor shall deallocate any memory allocated. + [inline_note Executors defined in this Technical Specification always use + the supplied allocator unless otherwise specified.]\n + \n + Synchronization: The invocation of `post` or `defer` synchronizes with + (C++Std \[intro.multithread\]) the invocation of `f1`.\n + \n + [inline_note Although the requirements placed on `defer` are identical to + `post`, the use of `post` conveys a preference that the caller ['does not] + block the first step of [^f1]'s progress, whereas `defer` conveys a + preference that the caller ['does] block the first step of [^f1]. One use + of `defer` is to convey the intention of the caller that [^f1] is a + continuation of the current call context. The executor may use this + information to optimize or otherwise adjust the way in which `f1` is + invoked.]] + ] +] + +[endsect] diff --git a/doc/requirements/GettableSocketOption.qbk b/doc/requirements/GettableSocketOption.qbk index 79b92942e5..2211629a2c 100644 --- a/doc/requirements/GettableSocketOption.qbk +++ b/doc/requirements/GettableSocketOption.qbk @@ -7,14 +7,19 @@ [section:GettableSocketOption Gettable socket option requirements] -In the table below, `X` denotes a socket option class, `a` denotes a value of -`X`, `p` denotes a value that meets the [link boost_asio.reference.Protocol -protocol] requirements, and `u` denotes an identifier. +A type `X` meets the `GettableSocketOption` requirements if it satisfies the +requirements listed below. -[table GettableSocketOption requirements +In the table below, `a` denotes a (possibly const) value of type `X`, `b` +denotes a value of type `X`, `p` denotes a (possibly const) value that meets +the [link boost_asio.reference.Protocol `Protocol`] requirements, and `s` denotes a +(possibly const) value of a type that is convertible to `size_t` and denotes a +size in bytes. + +[table GettableSocketOption requirements for extensible implementations [[expression] [type] [assertion/note\npre/post-conditions]] [ - [`a.level(p);`] + [`a.level(p)`] [`int`] [ Returns a value suitable for passing as the /level/ argument to __POSIX__ @@ -22,7 +27,7 @@ protocol] requirements, and `u` denotes an identifier. ] ] [ - [`a.name(p);`] + [`a.name(p)`] [`int`] [ Returns a value suitable for passing as the /option_name/ argument to @@ -30,15 +35,15 @@ protocol] requirements, and `u` denotes an identifier. ] ] [ - [`a.data(p);`] - [a pointer, convertible to `void*`] + [`b.data(p)`] + [`void*`] [ Returns a pointer suitable for passing as the /option_value/ argument to __POSIX__ __getsockopt__ (or equivalent). ] ] [ - [`a.size(p);`] + [`a.size(p)`] [`size_t`] [ Returns a value suitable for passing as the /option_len/ argument to @@ -47,13 +52,13 @@ protocol] requirements, and `u` denotes an identifier. ] ] [ - [`a.resize(p, s);`] + [`b.resize(p,s)`] [] [ - post: `a.size(p) == s`.\n + post: `b.size(p) == s`.\n Passed the value contained in the /option_len/ argument to __POSIX__ __getsockopt__ (or equivalent) after successful completion of the - function. Permitted to throw an exception if the socket option object `a` + function. Permitted to throw an exception if the socket option object `b` does not support the specified size. ] ] diff --git a/doc/requirements/HandleService.qbk b/doc/requirements/HandleService.qbk deleted file mode 100644 index 74b1ebcbd5..0000000000 --- a/doc/requirements/HandleService.qbk +++ /dev/null @@ -1,132 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:HandleService Handle service requirements] - -A handle service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service] with support for movability, -as well as the additional requirements listed below. - -In the table below, `X` denotes a handle service class, `a` and `ao` denote -values of type `X`, `b` and `c` denote values of type `X::implementation_type`, -`n` denotes a value of type `X::native_handle_type`, `ec` denotes a value of -type `error_code`, and `u` and `v` denote identifiers. - -[table HandleService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`X::native_handle_type`] - [] - [ - The implementation-defined native representation of a handle. Must - satisfy the requirements of `CopyConstructible` types (C++ Std, 20.1.3), - and the requirements of `Assignable` types (C++ Std, 23.1). - ] - ] - [ - [`a.construct(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly cancels asynchronous operations, as if by calling - `a.close(b, ec)`. - ] - ] - [ - [`` - a.move_construct(b, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - The underlying native representation is moved from `c` to `b`. - ] - ] - [ - [`` - a.move_assign(b, ao, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - Implicitly cancels asynchronous operations associated with `b`, as if by - calling `a.close(b, ec)`. Then the underlying native representation is - moved from `c` to `b`. - ] - ] - [ - [`` - a.assign(b, n, ec); - ``] - [`error_code`] - [ - pre: `!a.is_open(b)`.\n - post: `!!ec || a.is_open(b)`. - ] - ] - [ - [`` - a.is_open(b); - ``] - [`bool`] - [ - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.is_open(v); - ``] - [`bool`] - [ - ] - ] - [ - [`` - a.close(b, ec); - ``] - [`error_code`] - [ - If `a.is_open()` is true, causes any outstanding asynchronous operations - to complete as soon as possible. Handlers for cancelled operations shall - be passed the error code `error::operation_aborted`.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`` - a.native_handle(b); - ``] - [`X::native_handle_type`] - [ - ] - ] - [ - [`` - a.cancel(b, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`.\n - Causes any outstanding asynchronous operations to complete as soon as - possible. Handlers for cancelled operations shall be passed the error - code `error::operation_aborted`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/HandshakeHandler.qbk b/doc/requirements/HandshakeHandler.qbk index 71ac4041cf..dbcc9685c6 100644 --- a/doc/requirements/HandshakeHandler.qbk +++ b/doc/requirements/HandshakeHandler.qbk @@ -35,7 +35,29 @@ A handshake handler function object: ... }; -A non-static class member function adapted to a handshake handler using `bind()`: +A lambda as a handshake handler: + + ssl_stream.async_handshake(..., + [](const boost::system::error_code& ec) + { + ... + }); + +A non-static class member function adapted to a handshake handler using +`std::bind()`: + + void my_class::handshake_handler( + const boost::system::error_code& ec) + { + ... + } + ... + ssl_stream.async_handshake(..., + std::bind(&my_class::handshake_handler, + this, std::placeholders::_1)); + +A non-static class member function adapted to a handshake handler using +`boost::bind()`: void my_class::handshake_handler( const boost::system::error_code& ec) diff --git a/doc/requirements/InternetProtocol.qbk b/doc/requirements/InternetProtocol.qbk index 98fb040a7e..106ffe909f 100644 --- a/doc/requirements/InternetProtocol.qbk +++ b/doc/requirements/InternetProtocol.qbk @@ -7,12 +7,12 @@ [section:InternetProtocol Internet protocol requirements] -An internet protocol must meet the requirements for a [link -boost_asio.reference.Protocol protocol] as well as the additional -requirements listed below. +A type `X` meets the `InternetProtocol` requirements if it satisfies the +requirements of [link boost_asio.reference.AcceptableProtocol `AcceptableProtocol`], +as well as the additional requirements listed below. -In the table below, `X` denotes an internet protocol class, `a` denotes a value -of type `X`, and `b` denotes a value of type `X`. +In the table below, `a` denotes a (possibly const) value of type `X`, and `b` +denotes a (possibly const) value of type `X`. [table InternetProtocol requirements [[expression] [return type] [assertion/note\npre/post-conditions]] @@ -34,7 +34,8 @@ of type `X`, and `b` denotes a value of type `X`. [ [`a == b`] [convertible to `bool`] - [Returns whether two protocol objects are equal.] + [Returns `true` if `a` and `b` represent the same IP protocol version, + otherwise `false`.] ] [ [`a != b`] diff --git a/doc/requirements/IoControlCommand.qbk b/doc/requirements/IoControlCommand.qbk index 5bc61e7310..3cd6bf5c24 100644 --- a/doc/requirements/IoControlCommand.qbk +++ b/doc/requirements/IoControlCommand.qbk @@ -7,13 +7,16 @@ [section:IoControlCommand I/O control command requirements] -In the table below, `X` denotes an I/O control command class, `a` denotes a -value of `X`, and `u` denotes an identifier. +A type `X` meets the `IoControlCommand` requirements if it satisfies the +requirements listed below. -[table IoControlCommand requirements +In the table below, `a` denotes a (possibly const) value of type `X`, and `b` +denotes a value of type `X`. + +[table IoControlCommand requirements for extensible implementations [[expression] [type] [assertion/note\npre/post-conditions]] [ - [`a.name();`] + [`a.name()`] [`int`] [ Returns a value suitable for passing as the /request/ argument to @@ -21,8 +24,8 @@ value of `X`, and `u` denotes an identifier. ] ] [ - [`a.data();`] - [a pointer, convertible to `void*`] + [`b.data()`] + [`void*`] [ ] ] diff --git a/doc/requirements/ComposedConnectHandler.qbk b/doc/requirements/IteratorConnectHandler.qbk similarity index 53% rename from doc/requirements/ComposedConnectHandler.qbk rename to doc/requirements/IteratorConnectHandler.qbk index 1df6a69f96..a9bc88a565 100644 --- a/doc/requirements/ComposedConnectHandler.qbk +++ b/doc/requirements/IteratorConnectHandler.qbk @@ -5,17 +5,17 @@ / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /] -[section:ComposedConnectHandler Composed connect handler requirements] +[section:IteratorConnectHandler Iterator connect handler requirements] -A composed connect handler must meet the requirements for a [link -boost_asio.reference.Handler handler]. A value `h` of a composed connect handler +An iterator connect handler must meet the requirements for a [link +boost_asio.reference.Handler handler]. A value `h` of an iterator connect handler class should work correctly in the expression `h(ec, i)`, where `ec` is an lvalue of type `const error_code` and `i` is an lvalue of the type `Iterator` used in the corresponding `connect()` or async_connect()` function. [heading Examples] -A free function as a composed connect handler: +A free function as an iterator connect handler: void connect_handler( const boost::system::error_code& ec, @@ -24,7 +24,7 @@ A free function as a composed connect handler: ... } -A composed connect handler function object: +An iterator connect handler function object: struct connect_handler { @@ -39,7 +39,32 @@ A composed connect handler function object: ... }; -A non-static class member function adapted to a composed connect handler using `bind()`: +A lambda as an iterator connect handler: + + boost::asio::async_connect(..., + [](const boost::system::error_code& ec, + boost::asio::ip::tcp::resolver::iterator iterator) + { + ... + }); + +A non-static class member function adapted to an iterator connect handler using +`std::bind()`: + + void my_class::connect_handler( + const boost::system::error_code& ec, + boost::asio::ip::tcp::resolver::iterator iterator) + { + ... + } + ... + boost::asio::async_connect(..., + std::bind(&my_class::connect_handler, + this, std::placeholders::_1, + std::placeholders::_2)); + +A non-static class member function adapted to an iterator connect handler using +`boost::bind()`: void my_class::connect_handler( const boost::system::error_code& ec, diff --git a/doc/requirements/MoveAcceptHandler.qbk b/doc/requirements/MoveAcceptHandler.qbk new file mode 100644 index 0000000000..2f26d566a8 --- /dev/null +++ b/doc/requirements/MoveAcceptHandler.qbk @@ -0,0 +1,61 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:MoveAcceptHandler Move accept handler requirements] + +A move accept handler must meet the requirements for a [link +boost_asio.reference.Handler handler]. A value `h` of a move accept handler class +should work correctly in the expression `h(ec, s)`, where `ec` is an lvalue of +type `const error_code` and `s` is an lvalue of the nested type +`Protocol::socket` for the type `Protocol` of the socket class template. + +[heading Examples] + +A free function as a move accept handler: + + void accept_handler( + const boost::system::error_code& ec, boost::asio::ip::tcp::socket s) + { + ... + } + +A move accept handler function object: + + struct accept_handler + { + ... + void operator()( + const boost::system::error_code& ec, boost::asio::ip::tcp::socket s) + { + ... + } + ... + }; + +A lambda as a move accept handler: + + acceptor.async_accept(..., + [](const boost::system::error_code& ec, boost::asio::ip::tcp::socket s) + { + ... + }); + +A non-static class member function adapted to a move accept handler using +`std::bind()`: + + void my_class::accept_handler( + const boost::system::error_code& ec, boost::asio::ip::tcp::socket socket) + { + ... + } + ... + boost::asio::async_accept(..., + std::bind(&my_class::accept_handler, + this, std::placeholders::_1, + std::placeholders::_2)); + +[endsect] diff --git a/doc/requirements/MutableBufferSequence.qbk b/doc/requirements/MutableBufferSequence.qbk index f87a3b4794..8e35d66ae6 100644 --- a/doc/requirements/MutableBufferSequence.qbk +++ b/doc/requirements/MutableBufferSequence.qbk @@ -7,96 +7,50 @@ [section:MutableBufferSequence Mutable buffer sequence requirements] -In the table below, `X` denotes a class containing objects of type `T`, `a` -denotes a value of type `X` and `u` denotes an identifier. +A ['mutable buffer sequence] represents a set of memory regions that may be +used to receive the output of an operation, such as the `receive` operation of +a socket. + +A type `X` meets the `MutableBufferSequence` requirements if it satisfies the +requirements of `Destructible` (C++Std [destructible]) and +`CopyConstructible` (C++Std [copyconstructible]), as well as the additional +requirements listed below. + +In the table below, `x` denotes a (possibly const) value of type `X`, and `u` +denotes an identifier. [table MutableBufferSequence requirements [[expression] [return type] [assertion/note\npre/post-condition]] [ - [`X::value_type`] - [`T`] - [`T` meets the requirements for [link - boost_asio.reference.ConvertibleToMutableBuffer - ConvertibleToMutableBuffer].] - ] - [ - [`X::const_iterator`] - [iterator type pointing to `T`] - [`const_iterator` meets the requirements for bidirectional iterators - (C++ Std, 24.1.4).] - ] - [ - [`X(a);`] + [`boost::asio::buffer_sequence_begin(x)`\n + `boost::asio::buffer_sequence_end(x)`] + [An iterator type meeting the requirements for bidirectional iterators + (C++Std \[bidirectional.iterators\]) whose value type is convertible to + `mutable_buffer`.] [] - [post: `equal_mutable_buffer_seq(a, X(a))` where the binary predicate - `equal_mutable_buffer_seq` is defined as - `` - bool equal_mutable_buffer_seq( - const X& x1, const X& x2) - { - return - distance(x1.begin(), x1.end()) - == distance(x2.begin(), x2.end()) - && equal(x1.begin(), x1.end(), - x2.begin(), equal_buffer); - } - `` - and the binary predicate `equal_buffer` is defined as - `` - bool equal_buffer( - const X::value_type& v1, - const X::value_type& v2) - { - mutable_buffer b1(v1); - mutable_buffer b2(v2); - return - buffer_cast(b1) - == buffer_cast(b2) - && buffer_size(b1) == buffer_size(b2); - } - ``] ] [ - [`X u(a);`] + [`` + X u(x); + ``] [] - [post: + [post:\n `` - distance(a.begin(), a.end()) - == distance(u.begin(), u.end()) - && equal(a.begin(), a.end(), - u.begin(), equal_buffer) - `` - where the binary predicate `equal_buffer` is defined as - `` - bool equal_buffer( - const X::value_type& v1, - const X::value_type& v2) - { - mutable_buffer b1(v1); - mutable_buffer b2(v2); - return - buffer_cast(b1) - == buffer_cast(b2) - && buffer_size(b1) == buffer_size(b2); - } + equal( + boost::asio::buffer_sequence_begin(x), + boost::asio::buffer_sequence_end(x), + boost::asio::buffer_sequence_begin(u), + boost::asio::buffer_sequence_end(u), + [](const typename X::value_type& v1, + const typename X::value_type& v2) + { + mutable_buffer b1(v1); + mutable_buffer b2(v2); + return b1.data() == b2.data() + && b1.size() == b2.size(); + }) ``] ] - [ - [`(&a)->~X();`] - [`void`] - [note: the destructor is applied to every element of `a`; all the memory - is deallocated.] - ] - [ - [`a.begin();`] - [`const_iterator` or convertible to `const_iterator`] - [] - ] - [ - [`a.end();`] - [`const_iterator` or convertible to `const_iterator`] - [] - ] ] [endsect] diff --git a/doc/requirements/ObjectHandleService.qbk b/doc/requirements/ObjectHandleService.qbk deleted file mode 100644 index f0491c74b5..0000000000 --- a/doc/requirements/ObjectHandleService.qbk +++ /dev/null @@ -1,46 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:ObjectHandleService Object handle service requirements] - -An object handle service must meet the requirements for a [link -boost_asio.reference.HandleService handle service], as well as the additional -requirements listed below. - -In the table below, `X` denotes an object handle service class, `a` denotes a -value of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` -denotes a value of type `error_code`, and `wh` denotes a value meeting [link -boost_asio.reference.WaitHandler `WaitHandler`] requirements. - -[table ObjectHandleService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.wait(b, ec);`] - [`error_code`] - [ - pre: `a.is_open(b)`.\n - \n - Synchronously waits for the object represented by handle `b` to become - signalled. - ] - ] - [ - [`a.async_wait(b, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to wait for the object represented by - handle `b` to become signalled. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements. - ] - ] -] - -[endsect] diff --git a/doc/requirements/ProtoAllocator.qbk b/doc/requirements/ProtoAllocator.qbk new file mode 100644 index 0000000000..f08fb2449f --- /dev/null +++ b/doc/requirements/ProtoAllocator.qbk @@ -0,0 +1,19 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:ProtoAllocator Proto-allocator requirements] + +A type `A` meets the proto-allocator requirements if `A` is `CopyConstructible` +(C++Std [copyconstructible]), `Destructible` (C++Std [destructible]), and +`allocator_traits::rebind_alloc` meets the allocator requirements (C++Std +[allocator.requirements]), where `U` is an object type. [inline_note For +example, `std::allocator` meets the proto-allocator requirements but not +the allocator requirements.] No constructor, comparison operator, copy +operation, move operation, or swap operation on these types shall exit via an +exception. + +[endsect] diff --git a/doc/requirements/Protocol.qbk b/doc/requirements/Protocol.qbk index 90ac26b3c3..0e7bb7bcf7 100644 --- a/doc/requirements/Protocol.qbk +++ b/doc/requirements/Protocol.qbk @@ -7,11 +7,10 @@ [section:Protocol Protocol requirements] -A protocol must meet the requirements of `CopyConstructible` types (C++ Std, -20.1.3), and the requirements of `Assignable` types (C++ Std, 23.1). - -In the table below, `X` denotes a protocol class, and `a` denotes a value of -`X`. +A type `X` meets the `Protocol` requirements if it satisfies the requirements +of `Destructible` (C++Std [destructible]), `CopyConstructible` (C++Std +[copyconstructible]), and `CopyAssignable` (C++Std [copyassignable]), as well +as the additional requirements listed below. [table Protocol requirements [[expression] [return type] [assertion/note\npre/post-conditions]] @@ -20,6 +19,12 @@ In the table below, `X` denotes a protocol class, and `a` denotes a value of [type meeting [link boost_asio.reference.Endpoint endpoint] requirements] [] ] +] + +In the table below, `a` denotes a (possibly const) value of type `X`. + +[table Protocol requirements for extensible implementations + [[expression] [return type] [assertion/note\npre/post-conditions]] [ [`a.family()`] [`int`] diff --git a/doc/requirements/RandomAccessHandleService.qbk b/doc/requirements/RandomAccessHandleService.qbk deleted file mode 100644 index 972a87a51c..0000000000 --- a/doc/requirements/RandomAccessHandleService.qbk +++ /dev/null @@ -1,133 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:RandomAccessHandleService Random access handle service requirements] - -A random access handle service must meet the requirements for a [link -boost_asio.reference.HandleService handle service], as well as the additional -requirements listed below. - -In the table below, `X` denotes a random access handle service class, `a` -denotes a value of type `X`, `b` denotes a value of type -`X::implementation_type`, `ec` denotes a value of type `error_code`, `o` -denotes an offset of type boost::uint64_t, `mb` denotes a value satisfying -[link boost_asio.reference.MutableBufferSequence mutable buffer sequence] -requirements, `rh` denotes a value meeting [link boost_asio.reference.ReadHandler -`ReadHandler`] requirements, `cb` denotes a value satisfying [link -boost_asio.reference.ConstBufferSequence constant buffer sequence] requirements, and -`wh` denotes a value meeting [link boost_asio.reference.WriteHandler `WriteHandler`] -requirements. - -[table RandomAccessHandleService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.read_some_at(b, o, mb, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from a handle `b` at offset `o`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - If the total size of all buffers in the sequence `mb` is `0`, the - function shall return `0` immediately. - ] - ] - [ - [`a.async_read_some_at(b, o, mb, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from a handle `b` at offset `o`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `mb` is `0`, the asynchronous read operation shall complete immediately - and pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.write_some_at(b, o, cb, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to a handle `b` at offset `o`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - If the total size of all buffers in the sequence `cb` is `0`, the - function shall return `0` immediately. - ] - ] - [ - [`a.async_write_some_at(b, o, cb, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - a handle `b` at offset `o`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `cb` is `0`, the asynchronous operation shall complete immediately and - pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/RangeConnectHandler.qbk b/doc/requirements/RangeConnectHandler.qbk new file mode 100644 index 0000000000..c986b8fc24 --- /dev/null +++ b/doc/requirements/RangeConnectHandler.qbk @@ -0,0 +1,82 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:RangeConnectHandler Range connect handler requirements] + +A range connect handler must meet the requirements for a [link +boost_asio.reference.Handler handler]. A value `h` of a range connect handler class +should work correctly in the expression `h(ec, ep)`, where `ec` is an lvalue of +type `const error_code` and `ep` is an lvalue of the type `Protocol::endpoint` +for the `Protocol` type in the corresponding `connect()` or async_connect()` +function. + +[heading Examples] + +A free function as a range connect handler: + + void connect_handler( + const boost::system::error_code& ec, + const boost::asio::ip::tcp::endpoint& endpoint) + { + ... + } + +A range connect handler function object: + + struct connect_handler + { + ... + template + void operator()( + const boost::system::error_code& ec, + const boost::asio::ip::tcp::endpoint& endpoint) + { + ... + } + ... + }; + +A lambda as a range connect handler: + + boost::asio::async_connect(..., + [](const boost::system::error_code& ec, + const boost::asio::ip::tcp::endpoint& endpoint) + { + ... + }); + +A non-static class member function adapted to a range connect handler using +`std::bind()`: + + void my_class::connect_handler( + const boost::system::error_code& ec, + const boost::asio::ip::tcp::endpoint& endpoint) + { + ... + } + ... + boost::asio::async_connect(..., + std::bind(&my_class::connect_handler, + this, std::placeholders::_1, + std::placeholders::_2)); + +A non-static class member function adapted to a range connect handler using +`boost::bind()`: + + void my_class::connect_handler( + const boost::system::error_code& ec, + const boost::asio::ip::tcp::endpoint& endpoint) + { + ... + } + ... + boost::asio::async_connect(..., + boost::bind(&my_class::connect_handler, + this, boost::asio::placeholders::error, + boost::asio::placeholders::endpoint)); + +[endsect] diff --git a/doc/requirements/RawSocketService.qbk b/doc/requirements/RawSocketService.qbk deleted file mode 100644 index 403c57e65d..0000000000 --- a/doc/requirements/RawSocketService.qbk +++ /dev/null @@ -1,227 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:RawSocketService Raw socket service requirements] - -A raw socket service must meet the requirements for a [link -boost_asio.reference.SocketService socket service], as well as the additional -requirements listed below. - -In the table below, `X` denotes a raw socket service class for protocol -[link boost_asio.reference.Protocol `Protocol`], `a` denotes a value of type -`X`, `b` denotes a value of type `X::implementation_type`, `e` denotes a value -of type `Protocol::endpoint`, `ec` denotes a value of type `error_code`, `f` -denotes a value of type `socket_base::message_flags`, `mb` denotes a value -satisfying [link boost_asio.reference.MutableBufferSequence mutable buffer -sequence] requirements, `rh` denotes a value meeting [link -boost_asio.reference.ReadHandler `ReadHandler`] requirements, `cb` denotes a -value satisfying [link boost_asio.reference.ConstBufferSequence constant -buffer sequence] requirements, and `wh` denotes a value meeting [link -boost_asio.reference.WriteHandler `WriteHandler`] requirements. - -[table RawSocketService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.receive(b, mb, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from a connected socket `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - ] - ] - [ - [`a.async_receive(b, mb, f, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from a connected socket `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.receive_from(b, mb, e, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from an unconnected socket `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - ] - ] - [ - [`a.async_receive_from(b, mb, e, f, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from an unconnected socket `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - The program must ensure the object `e` is valid until the handler - for the asynchronous operation is invoked.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.send(b, cb, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to a connected socket `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - ] - ] - [ - [`a.async_send(b, cb, f, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - a connected socket `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] - [ - [`` - const typename Protocol::endpoint& u = e; - a.send_to(b, cb, u, f, ec); - ``] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to an unconnected socket `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - ] - ] - [ - [`` - const typename Protocol::endpoint& u = e; - a.async_send(b, cb, u, f, wh); - ``] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - an unconnected socket `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/ReadHandler.qbk b/doc/requirements/ReadHandler.qbk index 09b58bcbce..f6bbac390e 100644 --- a/doc/requirements/ReadHandler.qbk +++ b/doc/requirements/ReadHandler.qbk @@ -37,7 +37,32 @@ A read handler function object: ... }; -A non-static class member function adapted to a read handler using `bind()`: +A lambda as a read handler: + + socket.async_read(... + [](const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + ... + }); + +A non-static class member function adapted to a read handler using +`std::bind()`: + + void my_class::read_handler( + const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + ... + } + ... + socket.async_read(..., + std::bind(&my_class::read_handler, + this, std::placeholders::_1, + std::placeholders::_2)); + +A non-static class member function adapted to a read handler using +`boost::bind()`: void my_class::read_handler( const boost::system::error_code& ec, diff --git a/doc/requirements/ResolveHandler.qbk b/doc/requirements/ResolveHandler.qbk index 14eea5ccc3..d622a9559b 100644 --- a/doc/requirements/ResolveHandler.qbk +++ b/doc/requirements/ResolveHandler.qbk @@ -7,13 +7,13 @@ [section:ResolveHandler Resolve handler requirements] -A resolve handler must meet the requirements for a [link -boost_asio.reference.Handler handler]. A value `h` of a resolve handler -class should work correctly in the expression `h(ec, i)`, where `ec` is an -lvalue of type `const error_code` and `i` is an lvalue of type `const -ip::basic_resolver_iterator`. `InternetProtocol` is the -template parameter of the [link boost_asio.reference.ip__resolver_service -`resolver_service`] which is used to initiate the asynchronous operation. +A resolve handler must meet the requirements for a [link boost_asio.reference.Handler +handler]. A value `h` of a resolve handler class should work correctly in the +expression `h(ec, r)`, where `ec` is an lvalue of type `const error_code` and +`r` is an lvalue of type `const ip::basic_resolver_results`. +`InternetProtocol` is the template parameter of the [link +boost_asio.reference.ip__basic_resolver `ip::basic_resolver<>`] which is used to +initiate the asynchronous operation. [heading Examples] @@ -21,7 +21,7 @@ A free function as a resolve handler: void resolve_handler( const boost::system::error_code& ec, - boost::asio::ip::tcp::resolver::iterator iterator) + boost::asio::ip::tcp::resolver::results_type results) { ... } @@ -33,18 +33,43 @@ A resolve handler function object: ... void operator()( const boost::system::error_code& ec, - boost::asio::ip::tcp::resolver::iterator iterator) + boost::asio::ip::tcp::resolver::results_type results) { ... } ... }; -A non-static class member function adapted to a resolve handler using `bind()`: +A lambda as a resolve handler: + + resolver.async_resolve(..., + [](const boost::system::error_code& ec, + boost::asio::ip::tcp::resolver::results_type results) + { + ... + }); + +A non-static class member function adapted to a resolve handler using +`std::bind()`: + + void my_class::resolve_handler( + const boost::system::error_code& ec, + boost::asio::ip::tcp::resolver::results_type results) + { + ... + } + ... + resolver.async_resolve(..., + std::bind(&my_class::resolve_handler, + this, std::placeholders::_1, + std::placeholders::_2)); + +A non-static class member function adapted to a resolve handler using +`boost::bind()`: void my_class::resolve_handler( const boost::system::error_code& ec, - boost::asio::ip::tcp::resolver::iterator iterator) + boost::asio::ip::tcp::resolver::results_type results) { ... } @@ -52,6 +77,6 @@ A non-static class member function adapted to a resolve handler using `bind()`: resolver.async_resolve(..., boost::bind(&my_class::resolve_handler, this, boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); + boost::asio::placeholders::results)); [endsect] diff --git a/doc/requirements/ResolverService.qbk b/doc/requirements/ResolverService.qbk deleted file mode 100644 index cfe69fef73..0000000000 --- a/doc/requirements/ResolverService.qbk +++ /dev/null @@ -1,108 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:ResolverService Resolver service requirements] - -A resolver service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service], as well as the -additional requirements listed below. - -In the table below, `X` denotes a resolver service class for protocol -`InternetProtocol`, `a` denotes a value of type `X`, `b` denotes a value of -type `X::implementation_type`, `q` denotes a value of type -`ip::basic_resolver_query`, `e` denotes a value of type -`ip::basic_endpoint`, `ec` denotes a value of type -`error_code`, and `h` denotes a value meeting [link -boost_asio.reference.ResolveHandler `ResolveHandler`] requirements. - -[table ResolverService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly cancels asynchronous resolve operations, as if by - calling `a.cancel(b, ec)`. - ] - ] - [ - [`` - a.cancel(b, ec); - ``] - [`error_code`] - [ - Causes any outstanding asynchronous resolve operations to complete as - soon as possible. Handlers for cancelled operations shall be passed the - error code `error::operation_aborted`. - ] - ] - [ - [`` - a.resolve(b, q, ec); - ``] - [`` - ip::basic_resolver_iterator< - InternetProtocol> - ``] - [ - On success, returns an iterator `i` such that `i != - ip::basic_resolver_iterator()`. Otherwise returns - `ip::basic_resolver_iterator()`. - ] - ] - [ - [`` - a.async_resolve(b, q, h); - ``] - [] - [ - Initiates an asynchronous resolve operation that is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - If the operation completes successfully, the `ResolveHandler` object `h` - shall be invoked with an iterator object `i` such that the condition `i - != ip::basic_resolver_iterator()` holds. Otherwise it - is invoked with `ip::basic_resolver_iterator()`. - ] - ] - [ - [`` - a.resolve(b, e, ec); - ``] - [`` - ip::basic_resolver_iterator< - InternetProtocol> - ``] - [ - On success, returns an iterator `i` such that `i != - ip::basic_resolver_iterator()`. Otherwise returns - `ip::basic_resolver_iterator()`. - ] - ] - [ - [`` - a.async_resolve(b, e, h); - ``] - [] - [ - Initiates an asynchronous resolve operation that is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - If the operation completes successfully, the `ResolveHandler` object `h` - shall be invoked with an iterator object `i` such that the condition `i - != ip::basic_resolver_iterator()` holds. Otherwise it - is invoked with `ip::basic_resolver_iterator()`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/SeqPacketSocketService.qbk b/doc/requirements/SeqPacketSocketService.qbk deleted file mode 100644 index 5844b4e8e0..0000000000 --- a/doc/requirements/SeqPacketSocketService.qbk +++ /dev/null @@ -1,127 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:SeqPacketSocketService Sequenced packet socket service requirements] - -A sequenced packet socket service must meet the requirements for a [link -boost_asio.reference.SocketService socket service], as well as the additional -requirements listed below. - -In the table below, `X` denotes a stream socket service class, `a` denotes a -value of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` -denotes a value of type `error_code`, `f` denotes a value of type -`socket_base::message_flags`, `g` denotes an lvalue of type -`socket_base::message_flags`, `mb` denotes a value satisfying [link -boost_asio.reference.MutableBufferSequence mutable buffer sequence] requirements, -`rh` denotes a value meeting [link boost_asio.reference.ReadHandler `ReadHandler`] -requirements, `cb` denotes a value satisfying [link -boost_asio.reference.ConstBufferSequence constant buffer sequence] requirements, and -`wh` denotes a value meeting [link boost_asio.reference.WriteHandler `WriteHandler`] -requirements. - -[table StreamSocketService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.receive(b, mb, f, g, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from a connected socket `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, sets `g` to the flags associated with the received data, - and returns the number of bytes read. Otherwise, sets `g` to `0` and - returns `0`. - ] - ] - [ - [`a.async_receive(b, mb, f, g, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from a connected socket `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - If the operation completes successfully, sets `g` to the flags associated - with the received data, then invokes the `ReadHandler` object `rh` with - the number of bytes transferred. Otherwise, sets `g` to `0` and invokes - `rh` with `0` bytes transferred. - ] - ] - [ - [`a.send(b, cb, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to a connected socket `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - ] - ] - [ - [`a.async_send(b, cb, f, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - a connected socket `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/SerialPortService.qbk b/doc/requirements/SerialPortService.qbk deleted file mode 100644 index 4cff7c1b03..0000000000 --- a/doc/requirements/SerialPortService.qbk +++ /dev/null @@ -1,301 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:SerialPortService Serial port service requirements] - -A serial port service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service] with support for movability, -as well as the additional requirements listed below. - -In the table below, `X` denotes a serial port service class, `a` and `ao` denote -values of type `X`, `d` denotes a serial port device name of type `std::string`, -`b` and `c` denote values of type `X::implementation_type`, `n` denotes a value -of type `X::native_handle_type`, `ec` denotes a value of type `error_code`, `s` -denotes a value meeting [link boost_asio.reference.SettableSerialPortOption -`SettableSerialPortOption`] requirements, `g` denotes a value meeting [link -boost_asio.reference.GettableSerialPortOption `GettableSerialPortOption`] -requirements, `mb` denotes a value satisfying [link -boost_asio.reference.MutableBufferSequence mutable buffer sequence] requirements, -`rh` denotes a value meeting [link boost_asio.reference.ReadHandler `ReadHandler`] -requirements, `cb` denotes a value satisfying [link -boost_asio.reference.ConstBufferSequence constant buffer sequence] requirements, and -`wh` denotes a value meeting [link boost_asio.reference.WriteHandler `WriteHandler`] -requirements. and `u` and `v` denote identifiers. - -[table SerialPortService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`X::native_handle_type`] - [] - [ - The implementation-defined native representation of a serial port. Must - satisfy the requirements of `CopyConstructible` types (C++ Std, 20.1.3), - and the requirements of `Assignable` types (C++ Std, 23.1). - ] - ] - [ - [`a.construct(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly cancels asynchronous operations, as if by calling - `a.close(b, ec)`. - ] - ] - [ - [`` - a.move_construct(b, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - The underlying native representation is moved from `c` to `b`. - ] - ] - [ - [`` - a.move_assign(b, ao, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - Implicitly cancels asynchronous operations associated with `b`, as if by - calling `a.close(b, ec)`. Then the underlying native representation is - moved from `c` to `b`. - ] - ] - [ - [`` - const std::string& u = d; - a.open(b, u, ec); - ``] - [`error_code`] - [ - pre: `!a.is_open(b)`.\n - post: `!!ec || a.is_open(b)`. - ] - ] - [ - [`` - a.assign(b, n, ec); - ``] - [`error_code`] - [ - pre: `!a.is_open(b)`.\n - post: `!!ec || a.is_open(b)`. - ] - ] - [ - [`` - a.is_open(b); - ``] - [`bool`] - [ - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.is_open(v); - ``] - [`bool`] - [ - ] - ] - [ - [`` - a.close(b, ec); - ``] - [`error_code`] - [ - If `a.is_open()` is true, causes any outstanding asynchronous operations - to complete as soon as possible. Handlers for cancelled operations shall - be passed the error code `error::operation_aborted`.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`` - a.native_handle(b); - ``] - [`X::native_handle_type`] - [ - ] - ] - [ - [`` - a.cancel(b, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`.\n - Causes any outstanding asynchronous operations to complete as soon as - possible. Handlers for cancelled operations shall be passed the error - code `error::operation_aborted`. - ] - ] - [ - [`` - a.set_option(b, s, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.get_option(b, g, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.get_option(v, g, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.send_break(b, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`a.read_some(b, mb, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from a serial port `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - If the total size of all buffers in the sequence `mb` is `0`, the - function shall return `0` immediately.\n - \n - If the operation completes due to graceful connection closure by the - peer, the operation shall fail with `error::eof`. - ] - ] - [ - [`a.async_read_some(b, mb, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from a serial port `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `mb` is `0`, the asynchronous read operation shall complete immediately - and pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes due to graceful connection closure by the - peer, the operation shall fail with `error::eof`.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.write_some(b, cb, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to a serial port `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - If the total size of all buffers in the sequence `cb` is `0`, the - function shall return `0` immediately. - ] - ] - [ - [`a.async_write_some(b, cb, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - a serial port `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `cb` is `0`, the asynchronous operation shall complete immediately and - pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/Service.qbk b/doc/requirements/Service.qbk index c27fbdaf9d..ceda250a39 100644 --- a/doc/requirements/Service.qbk +++ b/doc/requirements/Service.qbk @@ -7,27 +7,34 @@ [section:Service Service requirements] -A class is a service if it is publicly derived from another service, or if it -is a class derived from `io_service::service` and contains a -publicly-accessible declaration as follows: +A class is a ['service] if it is publicly and unambiguously derived from +`execution_context::service`, or if it is publicly and unambiguously derived +from another service. For a service `S`, `S::key_type` shall be valid and +denote a type (C++Std [temp.deduct]), `is_base_of_v` +shall be `true`, and `S` shall satisfy the `Destructible` requirements (C++Std +[destructible]). - static io_service::id id; +The first parameter of all service constructors shall be an lvalue reference to +`execution_context`. This parameter denotes the `execution_context` object that +represents a set of services, of which the service object will be a member. +[inline_note These constructors may be called by the `make_service` function.] -All services define a one-argument constructor that takes a reference to the -`io_service` object that owns the service. This constructor is /explicit/, -preventing its participation in automatic conversions. For example: +A service shall provide an explicit constructor with a single parameter of +lvalue reference to `execution_context`. [inline_note This constructor may be +called by the `use_service` function.] - class my_service : public io_service::service + class my_service : public execution_context::service { public: - static io_service::id id; - explicit my_service(io_service& ios); + typedef my_service key_type; + explicit my_service(execution_context& ctx); + my_service(execution_context& ctx, int some_value); private: - virtual void shutdown_service(); + virtual void shutdown() noexcept override; ... }; -A service's `shutdown_service` member function must cause all copies of -user-defined handler objects that are held by the service to be destroyed. +A service's `shutdown` member function shall destroy all copies of user-defined +function objects that are held by the service. [endsect] diff --git a/doc/requirements/SettableSocketOption.qbk b/doc/requirements/SettableSocketOption.qbk index 5fdae14a8f..5dec280e4d 100644 --- a/doc/requirements/SettableSocketOption.qbk +++ b/doc/requirements/SettableSocketOption.qbk @@ -7,14 +7,17 @@ [section:SettableSocketOption Settable socket option requirements] -In the table below, `X` denotes a socket option class, `a` denotes a value of -`X`, `p` denotes a value that meets the [link boost_asio.reference.Protocol -protocol] requirements, and `u` denotes an identifier. +A type `X` meets the `SettableSocketOption` requirements if it satisfies the +requirements listed below. -[table SettableSocketOption requirements +In the table below, `a` denotes a (possibly const) value of type `X`, `p` +denotes a (possibly const) value that meets the [link boost_asio.reference.Protocol +`Protocol`] requirements, and `u` denotes an identifier. + +[table SettableSocketOption requirements for extensible implementations [[expression] [type] [assertion/note\npre/post-conditions]] [ - [`a.level(p);`] + [`a.level(p)`] [`int`] [ Returns a value suitable for passing as the /level/ argument to __POSIX__ @@ -22,7 +25,7 @@ protocol] requirements, and `u` denotes an identifier. ] ] [ - [`a.name(p);`] + [`a.name(p)`] [`int`] [ Returns a value suitable for passing as the /option_name/ argument to @@ -30,16 +33,15 @@ protocol] requirements, and `u` denotes an identifier. ] ] [ - [`const X& u = a; - u.data(p);`] - [a pointer, convertible to `const void*`] + [`a.data(p)`] + [`const void*`] [ Returns a pointer suitable for passing as the /option_value/ argument to __POSIX__ __setsockopt__ (or equivalent). ] ] [ - [`a.size(p);`] + [`a.size(p)`] [`size_t`] [ Returns a value suitable for passing as the /option_len/ argument to diff --git a/doc/requirements/ShutdownHandler.qbk b/doc/requirements/ShutdownHandler.qbk index 1e37b9cfae..f773ed1409 100644 --- a/doc/requirements/ShutdownHandler.qbk +++ b/doc/requirements/ShutdownHandler.qbk @@ -35,7 +35,29 @@ A shutdown handler function object: ... }; -A non-static class member function adapted to a shutdown handler using `bind()`: +A lambda as a shutdown handler: + + ssl_stream.async_shutdown(..., + [](const boost::system::error_code& ec) + { + ... + }); + +A non-static class member function adapted to a shutdown handler using +`std::bind()`: + + void my_class::shutdown_handler( + const boost::system::error_code& ec) + { + ... + } + ... + ssl_stream.async_shutdown( + std::bind(&my_class::shutdown_handler, + this, std::placeholders::_1)); + +A non-static class member function adapted to a shutdown handler using +`boost::bind()`: void my_class::shutdown_handler( const boost::system::error_code& ec) diff --git a/doc/requirements/SignalHandler.qbk b/doc/requirements/SignalHandler.qbk index 74d8b850fd..74b67645c5 100644 --- a/doc/requirements/SignalHandler.qbk +++ b/doc/requirements/SignalHandler.qbk @@ -37,7 +37,32 @@ A signal handler function object: ... }; -A non-static class member function adapted to a signal handler using `bind()`: +A lambda as a signal handler: + + my_signal_set.async_wait( + [](const boost::system::error_code& ec, + int signal_number) + { + ... + }); + +A non-static class member function adapted to a signal handler using +`std::bind()`: + + void my_class::signal_handler( + const boost::system::error_code& ec, + int signal_number) + { + ... + } + ... + my_signal_set.async_wait( + std::bind(&my_class::signal_handler, + this, std::placeholders::_1, + std::placeholders::_2)); + +A non-static class member function adapted to a signal handler using +`boost::bind()`: void my_class::signal_handler( const boost::system::error_code& ec, diff --git a/doc/requirements/SignalSetService.qbk b/doc/requirements/SignalSetService.qbk deleted file mode 100644 index f649accec8..0000000000 --- a/doc/requirements/SignalSetService.qbk +++ /dev/null @@ -1,91 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:SignalSetService Signal set service requirements] - -A signal set service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service], as well as the -additional requirements listed below. - -In the table below, `X` denotes a signal set service class, `a` denotes a value -of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` denotes -a value of type `error_code`, `n` denotes a value of type `int`, and `sh` -denotes a value meeting [link boost_asio.reference.SignalHandler `SignalHandler`] -requirements. - -[table SignalSetService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.construct(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements.\n - ] - ] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly clears the registered signals as if by calling - `a.clear(b, ec)`, then implicitly cancels outstanding asynchronous - operations as if by calling `a.cancel(b, ec)`. - ] - ] - [ - [`` - a.add(b, n, ec); - ``] - [`error_code`] - [ - ] - ] - [ - [`` - a.remove(b, n, ec); - ``] - [`error_code`] - [ - ] - ] - [ - [`` - a.clear(b, ec); - ``] - [`error_code`] - [ - ] - ] - [ - [`` - a.cancel(b, ec); - ``] - [`error_code`] - [ - ] - ] - [ - [`a.async_wait(b, sh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to wait for the delivery of one of the - signals registered for the signal set `b`. The operation is performed via - the `io_service` object `a.get_io_service()` and behaves according to - [link boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - If the operation completes successfully, the `SignalHandler` object - `sh` is invoked with the number identifying the delivered signal. Otherwise - it is invoked with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/SocketAcceptorService.qbk b/doc/requirements/SocketAcceptorService.qbk deleted file mode 100644 index 3ba995cf93..0000000000 --- a/doc/requirements/SocketAcceptorService.qbk +++ /dev/null @@ -1,270 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:SocketAcceptorService Socket acceptor service requirements] - -A socket acceptor service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service], as well as the -additional requirements listed below. - -In the table below, `X` denotes a socket acceptor service class for protocol -[link boost_asio.reference.Protocol `Protocol`], `a` and `ao` denote values of type -`X`, `b` and `c` denote values of type `X::implementation_type`, `p` denotes a -value of type `Protocol`, `n` denotes a value of type `X::native_handle_type`, -`e` denotes a value of type `Protocol::endpoint`, `ec` denotes a value of type -`error_code`, `s` denotes a value meeting [link -boost_asio.reference.SettableSocketOption `SettableSocketOption`] requirements, `g` -denotes a value meeting [link boost_asio.reference.GettableSocketOption -`GettableSocketOption`] requirements, `i` denotes a value meeting [link -boost_asio.reference.IoControlCommand `IoControlCommand`] requirements, `k` denotes a -value of type `basic_socket` where `SocketService` is -a type meeting [link boost_asio.reference.SocketService socket service] requirements, -`ah` denotes a value meeting [link boost_asio.reference.AcceptHandler -`AcceptHandler`] requirements, and `u` and `v` denote identifiers. - -[table SocketAcceptorService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`X::native_handle_type`] - [] - [ - The implementation-defined native representation of a socket acceptor. - Must satisfy the requirements of `CopyConstructible` types (C++ Std, - 20.1.3), and the requirements of `Assignable` types (C++ Std, 23.1). - ] - ] - [ - [`a.construct(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly cancels asynchronous operations, as if by calling - `a.close(b, ec)`. - ] - ] - [ - [`` - a.move_construct(b, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - The underlying native representation is moved from `c` to `b`. - ] - ] - [ - [`` - a.move_assign(b, ao, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - Implicitly cancels asynchronous operations associated with `b`, as if by - calling `a.close(b, ec)`. Then the underlying native representation is - moved from `c` to `b`. - ] - ] - [ - [`` - a.open(b, p, ec); - ``] - [`error_code`] - [ - pre: `!a.is_open(b)`.\n - post: `!!ec || a.is_open(b)`. - ] - ] - [ - [`` - a.assign(b, p, n, ec); - ``] - [`error_code`] - [ - pre: `!a.is_open(b)`.\n - post: `!!ec || a.is_open(b)`. - ] - ] - [ - [`` - a.is_open(b); - ``] - [`bool`] - [ - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.is_open(v); - ``] - [`bool`] - [ - ] - ] - [ - [`` - a.close(b, ec); - ``] - [`error_code`] - [ - If `a.is_open()` is true, causes any outstanding asynchronous operations - to complete as soon as possible. Handlers for cancelled operations shall - be passed the error code `error::operation_aborted`.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`` - a.native_handle(b); - ``] - [`X::native_handle_type`] - [ - ] - ] - [ - [`` - a.cancel(b, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`.\n - Causes any outstanding asynchronous operations to complete as soon as - possible. Handlers for cancelled operations shall be passed the error - code `error::operation_aborted`. - ] - ] - [ - [`` - a.set_option(b, s, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.get_option(b, g, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.get_option(v, g, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.io_control(b, i, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const typename Protocol::endpoint& u = e; - a.bind(b, u, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.local_endpoint(b, ec); - ``] - [`Protocol::endpoint`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.local_endpoint(v, ec); - ``] - [`Protocol::endpoint`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.accept(b, k, &e, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b) && !k.is_open()`.\n - post: `k.is_open()` - ] - ] - [ - [`` - a.accept(b, k, 0, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b) && !k.is_open()`.\n - post: `k.is_open()` - ] - ] - [ - [`` - a.async_accept(b, k, &e, ah); - ``] - [] - [ - pre: `a.is_open(b) && !k.is_open()`.\n - Initiates an asynchronous accept operation that is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n\n - The program must ensure the objects `k` and `e` are valid until the - handler for the asynchronous operation is invoked. - ] - ] - [ - [`` - a.async_accept(b, k, 0, ah); - ``] - [] - [ - pre: `a.is_open(b) && !k.is_open()`.\n - Initiates an asynchronous accept operation that is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n\n - The program must ensure the object `k` is valid until the handler for the - asynchronous operation is invoked. - ] - ] -] - -[endsect] diff --git a/doc/requirements/SocketService.qbk b/doc/requirements/SocketService.qbk deleted file mode 100644 index f5d8255a45..0000000000 --- a/doc/requirements/SocketService.qbk +++ /dev/null @@ -1,312 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:SocketService Socket service requirements] - -A socket service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service] with support for movability, -as well as the additional requirements listed below. - -In the table below, `X` denotes a socket service class for protocol [link -boost_asio.reference.Protocol `Protocol`], `a` and `ao` denote values of type `X`, -`b` and `c` denote values of type `X::implementation_type`, `p` denotes a value -of type `Protocol`, `n` denotes a value of type `X::native_handle_type`, `e` -denotes a value of type `Protocol::endpoint`, `ec` denotes a value of type -`error_code`, `s` denotes a value meeting [link -boost_asio.reference.SettableSocketOption `SettableSocketOption`] requirements, `g` -denotes a value meeting [link boost_asio.reference.GettableSocketOption -`GettableSocketOption`] requirements, `i` denotes a value meeting [link -boost_asio.reference.IoControlCommand `IoControlCommand`] requirements, `h` -denotes a value of type `socket_base::shutdown_type`, `ch` denotes a value -meeting [link boost_asio.reference.ConnectHandler `ConnectHandler`] -requirements, and `u` and `v` denote identifiers. - -[table SocketService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`X::native_handle_type`] - [] - [ - The implementation-defined native representation of a socket. Must - satisfy the requirements of `CopyConstructible` types (C++ Std, 20.1.3), - and the requirements of `Assignable` types (C++ Std, 23.1). - ] - ] - [ - [`a.construct(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly cancels asynchronous operations, as if by calling - `a.close(b, ec)`. - ] - ] - [ - [`` - a.move_construct(b, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - The underlying native representation is moved from `c` to `b`. - ] - ] - [ - [`` - a.move_assign(b, ao, c); - ``] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] requirements. - Implicitly cancels asynchronous operations associated with `b`, as if by - calling `a.close(b, ec)`. Then the underlying native representation is - moved from `c` to `b`. - ] - ] - [ - [`` - a.open(b, p, ec); - ``] - [`error_code`] - [ - pre: `!a.is_open(b)`.\n - post: `!!ec || a.is_open(b)`. - ] - ] - [ - [`` - a.assign(b, p, n, ec); - ``] - [`error_code`] - [ - pre: `!a.is_open(b)`.\n - post: `!!ec || a.is_open(b)`. - ] - ] - [ - [`` - a.is_open(b); - ``] - [`bool`] - [ - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.is_open(v); - ``] - [`bool`] - [ - ] - ] - [ - [`` - a.close(b, ec); - ``] - [`error_code`] - [ - If `a.is_open()` is true, causes any outstanding asynchronous operations - to complete as soon as possible. Handlers for cancelled operations shall - be passed the error code `error::operation_aborted`.\n - post: `!a.is_open(b)`. - ] - ] - [ - [`` - a.native_handle(b); - ``] - [`X::native_handle_type`] - [ - ] - ] - [ - [`` - a.cancel(b, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`.\n - Causes any outstanding asynchronous operations to complete as soon as - possible. Handlers for cancelled operations shall be passed the error - code `error::operation_aborted`. - ] - ] - [ - [`` - a.set_option(b, s, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.get_option(b, g, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.get_option(v, g, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.io_control(b, i, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.at_mark(b, ec); - ``] - [`bool`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.at_mark(v, ec); - ``] - [`bool`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.available(b, ec); - ``] - [`size_t`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.available(v, ec); - ``] - [`size_t`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const typename Protocol::endpoint& u = e; - a.bind(b, u, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.shutdown(b, h, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.local_endpoint(b, ec); - ``] - [`Protocol::endpoint`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.local_endpoint(v, ec); - ``] - [`Protocol::endpoint`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - a.remote_endpoint(b, ec); - ``] - [`Protocol::endpoint`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const X& u = a; - const X::implementation_type& v = b; - u.remote_endpoint(v, ec); - ``] - [`Protocol::endpoint`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const typename Protocol::endpoint& u = e; - a.connect(b, u, ec); - ``] - [`error_code`] - [ - pre: `a.is_open(b)`. - ] - ] - [ - [`` - const typename Protocol::endpoint& u = e; - a.async_connect(b, u, ch); - ``] - [] - [ - pre: `a.is_open(b)`.\n - Initiates an asynchronous connect operation that is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements. - ] - ] -] - -[endsect] diff --git a/doc/requirements/StreamDescriptorService.qbk b/doc/requirements/StreamDescriptorService.qbk deleted file mode 100644 index 2a9803473f..0000000000 --- a/doc/requirements/StreamDescriptorService.qbk +++ /dev/null @@ -1,138 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:StreamDescriptorService Stream descriptor service requirements] - -A stream descriptor service must meet the requirements for a [link -boost_asio.reference.DescriptorService descriptor service], as well as the additional -requirements listed below. - -In the table below, `X` denotes a stream descriptor service class, `a` denotes -a value of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` -denotes a value of type `error_code`, `mb` denotes a value satisfying [link -boost_asio.reference.MutableBufferSequence mutable buffer sequence] requirements, -`rh` denotes a value meeting [link boost_asio.reference.ReadHandler `ReadHandler`] -requirements, `cb` denotes a value satisfying [link -boost_asio.reference.ConstBufferSequence constant buffer sequence] requirements, and -`wh` denotes a value meeting [link boost_asio.reference.WriteHandler `WriteHandler`] -requirements. - -[table StreamDescriptorService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.read_some(b, mb, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from a descriptor `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - If the total size of all buffers in the sequence `mb` is `0`, the - function shall return `0` immediately.\n - \n - If the operation completes due to graceful connection closure by the - peer, the operation shall fail with `error::eof`. - ] - ] - [ - [`a.async_read_some(b, mb, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from a descriptor `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `mb` is `0`, the asynchronous read operation shall complete immediately - and pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes due to graceful connection closure by the - peer, the operation shall fail with `error::eof`.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.write_some(b, cb, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to a descriptor `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - If the total size of all buffers in the sequence `cb` is `0`, the - function shall return `0` immediately. - ] - ] - [ - [`a.async_write_some(b, cb, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - a descriptor `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `cb` is `0`, the asynchronous operation shall complete immediately and - pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/StreamHandleService.qbk b/doc/requirements/StreamHandleService.qbk deleted file mode 100644 index 3ad72abc90..0000000000 --- a/doc/requirements/StreamHandleService.qbk +++ /dev/null @@ -1,138 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:StreamHandleService Stream handle service requirements] - -A stream handle service must meet the requirements for a [link -boost_asio.reference.HandleService handle service], as well as the additional -requirements listed below. - -In the table below, `X` denotes a stream handle service class, `a` denotes -a value of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` -denotes a value of type `error_code`, `mb` denotes a value satisfying [link -boost_asio.reference.MutableBufferSequence mutable buffer sequence] requirements, -`rh` denotes a value meeting [link boost_asio.reference.ReadHandler `ReadHandler`] -requirements, `cb` denotes a value satisfying [link -boost_asio.reference.ConstBufferSequence constant buffer sequence] requirements, and -`wh` denotes a value meeting [link boost_asio.reference.WriteHandler `WriteHandler`] -requirements. - -[table StreamHandleService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.read_some(b, mb, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from a handle `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - If the total size of all buffers in the sequence `mb` is `0`, the - function shall return `0` immediately.\n - \n - If the operation completes due to graceful connection closure by the - peer, the operation shall fail with `error::eof`. - ] - ] - [ - [`a.async_read_some(b, mb, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from a handle `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `mb` is `0`, the asynchronous read operation shall complete immediately - and pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes due to graceful connection closure by the - peer, the operation shall fail with `error::eof`.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.write_some(b, cb, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to a handle `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - If the total size of all buffers in the sequence `cb` is `0`, the - function shall return `0` immediately. - ] - ] - [ - [`a.async_write_some(b, cb, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - a handle `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `cb` is `0`, the asynchronous operation shall complete immediately and - pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/StreamSocketService.qbk b/doc/requirements/StreamSocketService.qbk deleted file mode 100644 index 4f9efc64f8..0000000000 --- a/doc/requirements/StreamSocketService.qbk +++ /dev/null @@ -1,139 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:StreamSocketService Stream socket service requirements] - -A stream socket service must meet the requirements for a [link -boost_asio.reference.SocketService socket service], as well as the additional -requirements listed below. - -In the table below, `X` denotes a stream socket service class, `a` denotes a -value of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` -denotes a value of type `error_code`, `f` denotes a value of type -`socket_base::message_flags`, `mb` denotes a value satisfying [link -boost_asio.reference.MutableBufferSequence mutable buffer sequence] -requirements, `rh` denotes a value meeting [link -boost_asio.reference.ReadHandler `ReadHandler`] requirements, `cb` denotes a -value satisfying [link boost_asio.reference.ConstBufferSequence constant -buffer sequence] requirements, and `wh` denotes a value meeting [link -boost_asio.reference.WriteHandler `WriteHandler`] requirements. - -[table StreamSocketService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.receive(b, mb, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Reads one or more bytes of data from a connected socket `b`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - If successful, returns the number of bytes read. Otherwise returns `0`. - If the total size of all buffers in the sequence `mb` is `0`, the - function shall return `0` immediately.\n - \n - If the operation completes due to graceful connection closure by the - peer, the operation shall fail with `error::eof`. - ] - ] - [ - [`a.async_receive(b, mb, f, rh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to read one or more bytes of data - from a connected socket `b`. The operation is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The operation shall always fill a buffer in the sequence - completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `mb` until such - time as the read operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `mb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `mb` is `0`, the asynchronous read operation shall complete immediately - and pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes due to graceful connection closure by the - peer, the operation shall fail with `error::eof`.\n - \n - If the operation completes successfully, the `ReadHandler` object - `rh` is invoked with the number of bytes transferred. Otherwise it is - invoked with `0`. - ] - ] - [ - [`a.send(b, cb, f, ec);`] - [`size_t`] - [ - pre: `a.is_open(b)`.\n - \n - Writes one or more bytes of data to a connected socket `b`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - If successful, returns the number of bytes written. Otherwise returns `0`. - If the total size of all buffers in the sequence `cb` is `0`, the - function shall return `0` immediately. - ] - ] - [ - [`a.async_send(b, cb, f, wh);`] - [`void`] - [ - pre: `a.is_open(b)`.\n - \n - Initiates an asynchronous operation to write one or more bytes of data to - a connected socket `b`. The operation is performed via the `io_service` - object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The operation shall always write a buffer in the - sequence completely before proceeding to the next.\n - \n - The implementation shall maintain one or more copies of `cb` until such - time as the write operation no longer requires access to the memory - specified by the buffers in the sequence. The program must ensure the - memory is valid until:\n - \n - [mdash] the last copy of `cb` is destroyed, or\n - \n - [mdash] the handler for the asynchronous operation is invoked,\n - \n - whichever comes first. If the total size of all buffers in the sequence - `cb` is `0`, the asynchronous operation shall complete immediately and - pass `0` as the argument to the handler that specifies the number of - bytes read.\n - \n - If the operation completes successfully, the `WriteHandler` object `wh` - is invoked with the number of bytes transferred. Otherwise it is invoked - with `0`. - ] - ] -] - -[endsect] diff --git a/doc/requirements/SyncReadStream.qbk b/doc/requirements/SyncReadStream.qbk index ad99b462ed..3b11b8a505 100644 --- a/doc/requirements/SyncReadStream.qbk +++ b/doc/requirements/SyncReadStream.qbk @@ -7,40 +7,33 @@ [section:SyncReadStream Buffer-oriented synchronous read stream requirements] -In the table below, `a` denotes a synchronous read stream object, `mb` denotes -an object satisfying [link boost_asio.reference.MutableBufferSequence -mutable buffer sequence] requirements, and `ec` denotes an object of type +A type `X` meets the `SyncReadStream` requirements if it satisfies the +requirements listed below. + +In the table below, `a` denotes a value of type `X`, `mb` denotes a (possibly +const) value satisfying the [link boost_asio.reference.MutableBufferSequence +`MutableBufferSequence`] requirements, and `ec` denotes an object of type `error_code`. -[table Buffer-oriented synchronous read stream requirements +[table SyncReadStream requirements [[operation] [type] [semantics, pre/post-conditions]] [ - [`a.read_some(mb);`] - [`size_t`] - [Equivalent to: - `` - error_code ec; - size_t s = a.read_some(mb, ec); - if (ec) throw system_error(ec); - return s; - ``] - ] - [ - [`a.read_some(mb, ec);`] + [`a.read_some(mb)`\n + `a.read_some(mb,ec)`] [`size_t`] [ - Reads one or more bytes of data from the stream `a`.\n - \n - The mutable buffer sequence `mb` specifies memory where the data should - be placed. The `read_some` operation shall always fill a buffer in the - sequence completely before proceeding to the next.\n + Meets the requirements for a [link boost_asio.reference.read_write_operations + read operation].\n \n - If successful, returns the number of bytes read and sets `ec` such that - `!ec` is true. If an error occurred, returns `0` and sets `ec` such that - `!!ec` is true.\n + If `buffer_size(mb) > 0`, reads one or more bytes of data from the stream + `a` into the buffer sequence `mb`. If successful, sets `ec` such that + `!ec` is `true`, and returns the number of bytes read. If an error + occurred, sets `ec` such that `!!ec` is `true`, and returns 0. If all + data has been read from the stream, and the stream performed an orderly + shutdown, sets `ec` to `stream_errc::eof` and returns 0.\n \n - If the total size of all buffers in the sequence `mb` is `0`, the - function shall return `0` immediately. + If `buffer_size(mb) == 0`, the operation shall not block. Sets `ec` such + that `!ec` is `true`, and returns 0. ] ] ] diff --git a/doc/requirements/SyncWriteStream.qbk b/doc/requirements/SyncWriteStream.qbk index 5c30d255e2..18478ab23d 100644 --- a/doc/requirements/SyncWriteStream.qbk +++ b/doc/requirements/SyncWriteStream.qbk @@ -7,39 +7,31 @@ [section:SyncWriteStream Buffer-oriented synchronous write stream requirements] -In the table below, `a` denotes a synchronous write stream object, `cb` denotes -an object satisfying [link boost_asio.reference.ConstBufferSequence constant -buffer sequence] requirements, and `ec` denotes an object of type `error_code`. +A type `X` meets the `SyncWriteStream` requirements if it satisfies the +requirements listed below. -[table Buffer-oriented synchronous write stream requirements +In the table below, `a` denotes a value of type `X`, `cb` denotes a (possibly +const) value satisfying the [link boost_asio.reference.ConstBufferSequence +`ConstBufferSequence`] requirements, and `ec` denotes an object of type +`error_code`. + +[table SyncWriteStream requirements [[operation] [type] [semantics, pre/post-conditions]] [ - [`a.write_some(cb);`] - [`size_t`] - [Equivalent to: - `` - error_code ec; - size_t s = a.write_some(cb, ec); - if (ec) throw system_error(ec); - return s; - ``] - ] - [ - [`a.write_some(cb, ec);`] + [`a.write_some(cb)`\n + `a.write_some(cb,ec)`] [`size_t`] [ - Writes one or more bytes of data to the stream `a`.\n - \n - The constant buffer sequence `cb` specifies memory where the data to be - written is located. The `write_some` operation shall always write a - buffer in the sequence completely before proceeding to the next.\n + Meets the requirements for a [link boost_asio.reference.read_write_operations + write operation].\n \n - If successful, returns the number of bytes written and sets `ec` such - that `!ec` is true. If an error occurred, returns `0` and sets `ec` such - that `!!ec` is true.\n + If `buffer_size(cb) > 0`, writes one or more bytes of data to the stream + `a` from the buffer sequence `cb`. If successful, sets `ec` such that + `!ec` is `true`, and returns the number of bytes written. If an error + occurred, sets `ec` such that `!!ec` is `true`, and returns 0.\n \n - If the total size of all buffers in the sequence `cb` is `0`, the - function shall return `0` immediately. + If `buffer_size(cb) == 0`, the operation shall not block. Sets `ec` such + that `!ec` is `true`, and returns 0. ] ] ] diff --git a/doc/requirements/TimerService.qbk b/doc/requirements/TimerService.qbk deleted file mode 100644 index 47f8e16259..0000000000 --- a/doc/requirements/TimerService.qbk +++ /dev/null @@ -1,105 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:TimerService Timer service requirements] - -A timer service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service], as well as the -additional requirements listed below. - -In the table below, `X` denotes a timer service class for time type `Time` and -traits type `TimeTraits`, `a` denotes a value of type `X`, `b` denotes a value -of type `X::implementation_type`, `t` denotes a value of type `Time`, `d` -denotes a value of type `TimeTraits::duration_type`, `e` denotes a value of -type `error_code`, and `h` denotes a value meeting [link -boost_asio.reference.WaitHandler `WaitHandler`] requirements. - -[table TimerService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly cancels asynchronous wait operations, as if by - calling `a.cancel(b, e)`. - ] - ] - [ - [`` - a.cancel(b, e); - ``] - [`size_t`] - [ - Causes any outstanding asynchronous wait operations to complete as soon - as possible. Handlers for cancelled operations shall be passed the error - code `error::operation_aborted`. Sets `e` to indicate success or failure. - Returns the number of operations that were cancelled. - ] - ] - [ - [`a.expires_at(b);`] - [`Time`] - [] - ] - [ - [`` - a.expires_at(b, t, e); - ``] - [`size_t`] - [ - Implicitly cancels asynchronous wait operations, as if by calling - `a.cancel(b, e)`. Returns the number of operations that were cancelled.\n - post: `a.expires_at(b) == t`. - ] - ] - [ - [`a.expires_from_now(b);`] - [`TimeTraits::duration_type`] - [ - Returns a value equivalent to `TimeTraits::subtract(a.expires_at(b), - TimeTraits::now())`. - ] - ] - [ - [`` - a.expires_from_now(b, d, e); - ``] - [`size_t`] - [ - Equivalent to `a.expires_at(b, TimeTraits::add(TimeTraits::now(), d), e)`. - ] - ] - [ - [`` - a.wait(b, e); - ``] - [`error_code`] - [ - Sets `e` to indicate success or failure. Returns `e`.\n - post: `!!e || !TimeTraits::lt(TimeTraits::now(), a.expires_at(b))`. - ] - ] - [ - [`` - a.async_wait(b, h); - ``] - [] - [ - Initiates an asynchronous wait operation that is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The handler shall be posted for execution only if the condition - `!!ec || !TimeTraits::lt(TimeTraits::now(), a.expires_at(b))` - holds, where `ec` is the error code to be passed to the handler. - ] - ] -] - -[endsect] diff --git a/doc/requirements/WaitHandler.qbk b/doc/requirements/WaitHandler.qbk index 9bbf31f5c9..e8cfd37451 100644 --- a/doc/requirements/WaitHandler.qbk +++ b/doc/requirements/WaitHandler.qbk @@ -35,7 +35,29 @@ A wait handler function object: ... }; -A non-static class member function adapted to a wait handler using `bind()`: +A lambda as a wait handler: + + socket.async_wait(..., + [](const boost::system::error_code& ec) + { + ... + }); + +A non-static class member function adapted to a wait handler using +`std::bind()`: + + void my_class::wait_handler( + const boost::system::error_code& ec) + { + ... + } + ... + socket.async_wait(..., + std::bind(&my_class::wait_handler, + this, std::placeholders::_1)); + +A non-static class member function adapted to a wait handler using +`boost::bind()`: void my_class::wait_handler( const boost::system::error_code& ec) diff --git a/doc/requirements/WaitTraits.qbk b/doc/requirements/WaitTraits.qbk index c5cbad89c9..11e93d1f61 100644 --- a/doc/requirements/WaitTraits.qbk +++ b/doc/requirements/WaitTraits.qbk @@ -7,18 +7,44 @@ [section:WaitTraits Wait traits requirements] -In the table below, `X` denotes a wait traits class for clock type `Clock`, -where `Clock` meets the C++11 type requirements for a clock, and `d` denotes -a value of type `Clock::duration`. +The `basic_waitable_timer` template uses wait traits to allow programs to +customize `wait` and `async_wait` behavior. +[inline_note Possible uses of wait traits include:\n +[mdash] To enable timers based on non-realtime clocks.\n +[mdash] Determining how quickly wallclock-based timers respond to system time +changes.\n +[mdash] Correcting for errors or rounding timeouts to boundaries.\n +[mdash] Preventing duration overflow. That is, a program may set a timer's +expiry `e` to be `Clock::max()` (meaning never reached) or `Clock::min()` +(meaning always in the past). As a result, computing the duration until timer +expiry as `e - Clock::now()` may cause overflow.] + +For a type `Clock` meeting the `Clock` requirements (C++Std +[time.clock.req]), a type `X` meets the `WaitTraits` requirements if it +satisfies the requirements listed below. + +In the table below, `t` denotes a (possibly const) value of type +`Clock::time_point`; and `d` denotes a (possibly const) value of type +`Clock::duration`. [table WaitTraits requirements [[expression] [return type] [assertion/note\npre/post-condition]] [ - [`X::to_wait_duration(d);`] + [`X::to_wait_duration(d)`] + [`Clock::duration`] + [ + Returns a `Clock::duration` value to be used in a `wait` or `async_wait` + operation. [inline_note The return value is typically representative of + the duration `d`.] + ] + ] + [ + [`X::to_wait_duration(t)`] [`Clock::duration`] [ - Returns the maximum duration to be used for an individual, - implementation-defined wait operation. + Returns a `Clock::duration` value to be used in a `wait` or `async_wait` + operation. [inline_note The return value is typically representative of + the duration from `Clock::now()` until the time point `t`.] ] ] ] diff --git a/doc/requirements/WaitableTimerService.qbk b/doc/requirements/WaitableTimerService.qbk deleted file mode 100644 index 4df7af562e..0000000000 --- a/doc/requirements/WaitableTimerService.qbk +++ /dev/null @@ -1,104 +0,0 @@ -[/ - / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) - / - / Distributed under the Boost Software License, Version 1.0. (See accompanying - / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - /] - -[section:WaitableTimerService Waitable timer service requirements] - -A waitable timer service must meet the requirements for an [link -boost_asio.reference.IoObjectService I/O object service], as well as the -additional requirements listed below. - -In the table below, `X` denotes a waitable timer service class for clock type -`Clock`, where `Clock` meets the C++11 clock type requirements, `a` denotes a -value of type `X`, `b` denotes a value of type `X::implementation_type`, `t` -denotes a value of type `Clock::time_point`, `d` denotes a value of type -`Clock::duration`, `e` denotes a value of type `error_code`, and `h` denotes a -value meeting [link boost_asio.reference.WaitHandler `WaitHandler`] requirements. - -[table WaitableTimerService requirements - [[expression] [return type] [assertion/note\npre/post-condition]] - [ - [`a.destroy(b);`] - [] - [ - From [link boost_asio.reference.IoObjectService IoObjectService] - requirements. Implicitly cancels asynchronous wait operations, as if by - calling `a.cancel(b, e)`. - ] - ] - [ - [`` - a.cancel(b, e); - ``] - [`size_t`] - [ - Causes any outstanding asynchronous wait operations to complete as soon - as possible. Handlers for cancelled operations shall be passed the error - code `error::operation_aborted`. Sets `e` to indicate success or failure. - Returns the number of operations that were cancelled. - ] - ] - [ - [`a.expires_at(b);`] - [`Clock::time_point`] - [] - ] - [ - [`` - a.expires_at(b, t, e); - ``] - [`size_t`] - [ - Implicitly cancels asynchronous wait operations, as if by calling - `a.cancel(b, e)`. Returns the number of operations that were cancelled.\n - post: `a.expires_at(b) == t`. - ] - ] - [ - [`a.expires_from_now(b);`] - [`Clock::duration`] - [ - Returns a value equivalent to `a.expires_at(b) - Clock::now()`. - ] - ] - [ - [`` - a.expires_from_now(b, d, e); - ``] - [`size_t`] - [ - Equivalent to `a.expires_at(b, Clock::now() + d, e)`. - ] - ] - [ - [`` - a.wait(b, e); - ``] - [`error_code`] - [ - Sets `e` to indicate success or failure. Returns `e`.\n - post: `!!e || !(Clock::now() < a.expires_at(b))`. - ] - ] - [ - [`` - a.async_wait(b, h); - ``] - [] - [ - Initiates an asynchronous wait operation that is performed via the - `io_service` object `a.get_io_service()` and behaves according to [link - boost_asio.reference.asynchronous_operations asynchronous operation] - requirements.\n - \n - The handler shall be posted for execution only if the condition - `!!ec || !(Clock::now() < a.expires_at(b))` - holds, where `ec` is the error code to be passed to the handler. - ] - ] -] - -[endsect] diff --git a/doc/requirements/WriteHandler.qbk b/doc/requirements/WriteHandler.qbk index f5701fa8de..0f444065c4 100644 --- a/doc/requirements/WriteHandler.qbk +++ b/doc/requirements/WriteHandler.qbk @@ -37,7 +37,32 @@ A write handler function object: ... }; -A non-static class member function adapted to a write handler using `bind()`: +A lambda as a write handler: + + socket.async_write(... + [](const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + ... + }); + +A non-static class member function adapted to a write handler using +`std::bind()`: + + void my_class::write_handler( + const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + ... + } + ... + socket.async_write(..., + std::bind(&my_class::write_handler, + this, std::placeholders::_1, + std::placeholders::_2)); + +A non-static class member function adapted to a write handler using +`boost::bind()`: void my_class::write_handler( const boost::system::error_code& ec, diff --git a/doc/requirements/asynchronous_operations.qbk b/doc/requirements/asynchronous_operations.qbk index 0d82016008..23866688da 100644 --- a/doc/requirements/asynchronous_operations.qbk +++ b/doc/requirements/asynchronous_operations.qbk @@ -7,211 +7,275 @@ [section:asynchronous_operations Requirements on asynchronous operations] -In Boost.Asio, an asynchronous operation is initiated by a function that is -named with the prefix `async_`. These functions will be referred to as -['initiating functions]. - -All initiating functions in Boost.Asio take a function object meeting [link -boost_asio.reference.Handler handler] requirements as the final parameter. -These handlers accept as their first parameter an lvalue of type `const -error_code`. - -Implementations of asynchronous operations in Boost.Asio may call the -application programming interface (API) provided by the operating system. If -such an operating system API call results in an error, the handler will be -invoked with a `const error_code` lvalue that evaluates to true. Otherwise the -handler will be invoked with a `const error_code` lvalue that evaluates to -false. - -Unless otherwise noted, when the behaviour of an asynchronous operation is -defined "as if" implemented by a __POSIX__ function, the handler will be -invoked with a value of type `error_code` that corresponds to the failure -condition described by __POSIX__ for that function, if any. Otherwise the -handler will be invoked with an implementation-defined `error_code` value that -reflects the operating system error. - -Asynchronous operations will not fail with an error condition that indicates -interruption by a signal (__POSIX__ `EINTR`). Asynchronous operations will not -fail with any error condition associated with non-blocking operations -(__POSIX__ `EWOULDBLOCK`, `EAGAIN` or `EINPROGRESS`; __Windows__ -`WSAEWOULDBLOCK` or `WSAEINPROGRESS`). - -All asynchronous operations have an associated `io_service` object. Where the -initiating function is a member function, the associated `io_service` is that -returned by the `get_io_service()` member function on the same object. Where the -initiating function is not a member function, the associated `io_service` is -that returned by the `get_io_service()` member function of the first argument to -the initiating function. - -Arguments to initiating functions will be treated as follows: - -[mdash] If the parameter is declared as a const reference or by-value, the -program is not required to guarantee the validity of the argument after the -initiating function completes. The implementation may make copies of the -argument, and all copies will be destroyed no later than immediately after -invocation of the handler. - -[mdash] If the parameter is declared as a non-const reference, const pointer or -non-const pointer, the program must guarantee the validity of the argument -until the handler is invoked. - -The library implementation is only permitted to make calls to an initiating -function's arguments' copy constructors or destructors from a thread that -satisfies one of the following conditions: - -[mdash] The thread is executing any member function of the associated -`io_service` object. - -[mdash] The thread is executing the destructor of the associated `io_service` -object. +This section uses the names `Alloc1`, `Alloc2`, `alloc1`, `alloc2`, `Args`, +`CompletionHandler`, `completion_handler`, `Executor1`, `Executor2`, `ex1`, +`ex2`, `f`, [^['i]], [^['N]], `Signature`, `token`, [^T[sub ['i]]], [^t[sub +['i]]], `work1`, and `work2` as placeholders for specifying the requirements +below. -[mdash] The thread is executing one of the `io_service` service access -functions `use_service`, `add_service` or `has_service`, where the first -argument is the associated `io_service` object. - -[mdash] The thread is executing any member function, constructor or destructor -of an object of a class defined in this clause, where the object's -`get_io_service()` member function returns the associated `io_service` object. - -[mdash] The thread is executing any function defined in this clause, where any -argument to the function has an `get_io_service()` member function that returns -the associated `io_service` object. - -[blurb Boost.Asio may use one or more hidden threads to emulate asynchronous -functionality. The above requirements are intended to prevent these hidden -threads from making calls to program code. This means that a program can, for -example, use thread-unsafe reference counting in handler objects, provided the -program ensures that all calls to an `io_service` and related objects occur -from the one thread.] - -The `io_service` object associated with an asynchronous operation will have -unfinished work, as if by maintaining the existence of one or more objects of -class `io_service::work` constructed using the `io_service`, until immediately -after the handler for the asynchronous operation has been invoked. - -When an asynchronous operation is complete, the handler for the operation will -be invoked as if by: - -# Constructing a bound completion handler `bch` for the handler, as described - below. - -# Calling `ios.post(bch)` to schedule the handler for deferred invocation, - where `ios` is the associated `io_service`. - -This implies that the handler must not be called directly from within -the initiating function, even if the asynchronous operation completes -immediately. - -A bound completion handler is a handler object that contains a copy of a -user-supplied handler, where the user-supplied handler accepts one or more -arguments. The bound completion handler does not accept any arguments, and -contains values to be passed as arguments to the user-supplied handler. The -bound completion handler forwards the `asio_handler_allocate()`, -`asio_handler_deallocate()`, and `asio_handler_invoke()` calls to the -corresponding functions for the user-supplied handler. A bound completion -handler meets the requirements for a [link -boost_asio.reference.CompletionHandler completion handler]. - -For example, a bound completion handler for a `ReadHandler` may be implemented -as follows: - - template - struct bound_read_handler - { - bound_read_handler(ReadHandler handler, const error_code& ec, size_t s) - : handler_(handler), ec_(ec), s_(s) - { - } - - void operator()() - { - handler_(ec_, s_); - } - - ReadHandler handler_; - const error_code ec_; - const size_t s_; - }; - - template - void* asio_handler_allocate(size_t size, - bound_read_handler* this_handler) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate(size, &this_handler->handler_); - } +[section General asynchronous operation concepts] + +An ['initiating function] is a function which may be called to start an +asynchronous operation. A ['completion handler] is a function object that will +be invoked, at most once, with the result of the asynchronous operation. + +The lifecycle of an asynchronous operation is comprised of the following events +and phases: + +[mdash] Event 1: The asynchronous operation is started by a call to the +initiating function. + +[mdash] Phase 1: The asynchronous operation is now ['outstanding]. + +[mdash] Event 2: The externally observable side effects of the asynchronous +operation, if any, are fully established. The completion handler is submitted +to an executor. + +[mdash] Phase 2: The asynchronous operation is now ['completed]. + +[mdash] Event 3: The completion handler is called with the result of the +asynchronous operation. + +In this library, all functions with the prefix `async_` are initiating +functions. + +[endsect] + +[section:completion_token Completion tokens and handlers] + +Initiating functions: + +[mdash] are function templates with template parameter `CompletionToken`; + +[mdash] accept, as the final parameter, a ['completion token] object `token` +of type `CompletionToken`; + +[mdash] specify a ['completion signature], which is a call signature (C++Std +[func.def]) `Signature` that determines the arguments to the completion +handler. + +An initiating function determines the type `CompletionHandler` of its +completion handler function object by performing `typename +async_result, Signature>::completion_handler_type`. +The completion handler object `completion_handler` is initialized with +`forward(token)`. [inline_note No other requirements are +placed on the type `CompletionToken`.] - template - void asio_handler_deallocate(void* pointer, std::size_t size, - bound_read_handler* this_handler) +The type `CompletionHandler` must satisfy the requirements of `Destructible` +(C++Std [destructible]) and `MoveConstructible` (C++Std +[moveconstructible]), and be callable with the specified call signature. + +In this library, all initiating functions specify a ['Completion signature] +element that defines the call signature `Signature`. The ['Completion +signature] elements in this Technical Specification have named parameters, and +the results of an asynchronous operation are specified in terms of these names. + +[endsect] + +[section Automatic deduction of initiating function return type] + +The return type of an initiating function is `typename +async_result, Signature>::return_type`. + +For the sake of exposition, this library sometimes annotates functions with a +return type ['[^DEDUCED]]. For every function declaration that returns +['[^DEDUCED]], the meaning is equivalent to specifying the return type as +`typename async_result, Signature>::return_type`. + +[endsect] + +[section Production of initiating function return value] + +An initiating function produces its return type as follows: + +[mdash] constructing an object `result` of type +`async_result, Signature>`, initialized as +`result(completion_handler)`; and + +[mdash] using `result.get()` as the operand of the return statement. + +\[['Example:] Given an asynchronous operation with ['Completion signature] +`void(R1 r1, R2 r2)`, an initiating function meeting these requirements may be +implemented as follows: + + template + auto async_xyz(T1 t1, T2 t2, CompletionToken&& token) { - using boost::asio::asio_handler_deallocate; - asio_handler_deallocate(pointer, size, &this_handler->handler_); + typename async_result, void(R1, R2)>::completion_handler_type + completion_handler(forward(token)); + + async_result, void(R1, R2)> result(completion_handler); + + // initiate the operation and cause completion_handler to be invoked with + // the result + + return result.get(); } - template - void asio_handler_invoke(const F& f, - bound_read_handler* this_handler) +For convenience, initiating functions may be implemented using the +`async_completion` template: + + template + auto async_xyz(T1 t1, T2 t2, CompletionToken&& token) { - using boost::asio::asio_handler_invoke; - asio_handler_invoke(f, &this_handler->handler_); + async_completion init(token); + + // initiate the operation and cause init.completion_handler to be invoked + // with the result + + return init.result.get(); } -If the thread that initiates an asynchronous operation terminates before the -associated handler is invoked, the behaviour is implementation-defined. -Specifically, on __Windows__ versions prior to Vista, unfinished operations are -cancelled when the initiating thread exits. - -The handler argument to an initiating function defines a handler identity. That -is, the original handler argument and any copies of the handler argument will -be considered equivalent. If the implementation needs to allocate storage for -an asynchronous operation, the implementation will perform -`asio_handler_allocate(size, &h)`, where `size` is the required size in bytes, -and `h` is the handler. The implementation will perform -`asio_handler_deallocate(p, size, &h)`, where `p` is a pointer to the storage, -to deallocate the storage prior to the invocation of the handler via -`asio_handler_invoke`. Multiple storage blocks may be allocated for a single -asynchronous operation. +'''—'''['end example]\] -[heading Return type of an initiating function] +[endsect] + +[section Lifetime of initiating function arguments] + +Unless otherwise specified, the lifetime of arguments to initiating functions +shall be treated as follows: + +[mdash] If the parameter has a pointer type or has a type of lvalue reference +to non-const, the implementation may assume the validity of the pointee or +referent, respectively, until the completion handler is invoked. [inline_note +In other words, the program must guarantee the validity of the argument until +the completion handler is invoked.] + +[mdash] Otherwise, the implementation must not assume the validity of the +argument after the initiating function completes. [inline_note In other words, +the program is not required to guarantee the validity of the argument after the +initiating function completes.] The implementation may make copies of the +argument, and all copies shall be destroyed no later than immediately after +invocation of the completion handler. + +[endsect] + +[section Non-blocking requirements on initiating functions] + +An initiating function shall not block (C++Std [defns.block]) the calling +thread pending completion of the outstanding operation. + +[std_note Initiating functions may still block the calling thread for other +reasons. For example, an initiating function may lock a mutex in order to +synchronize access to shared data.] + +[endsect] + +[section Associated executor] + +Certain objects that participate in asynchronous operations have an +['associated executor]. These are obtained as specified below. + +[endsect] + +[section I/O executor] + +An asynchronous operation has an associated executor satisfying the [link +boost_asio.reference.Executor1 `Executor`] requirements. If not otherwise specified by +the asynchronous operation, this associated executor is an object of type +`system_executor`. + +All asynchronous operations in this library have an associated executor object +that is determined as follows: + +[mdash] If the initiating function is a member function, the associated +executor is that returned by the `get_executor` member function on the same +object. -By default, initiating functions return `void`. This is always the case when -the handler is a function pointer, C++11 lambda, or a function object produced -by `boost::bind` or `std::bind`. +[mdash] If the initiating function is not a member function, the associated +executor is that returned by the `get_executor` member function of the first +argument to the initiating function. -For other types, the return type may be customised via a two-step process: +Let `Executor1` be the type of the associated executor. Let `ex1` be a value of +type `Executor1`, representing the associated executor object obtained as +described above. -# A specialisation of the [link boost_asio.reference.handler_type `handler_type`] -template, which is used to determine the true handler type based on the -asynchronous operation's handler's signature. +[endsect] + +[section Completion handler executor] + +A completion handler object of type `CompletionHandler` has an associated +executor of type `Executor2` satisfying the [link boost_asio.reference.Executor1 +Executor requirements]. The type `Executor2` is +`associated_executor_t`. Let `ex2` be a value of +type `Executor2` obtained by performing +`get_associated_executor(completion_handler, ex1)`. -# A specialisation of the [link boost_asio.reference.async_result `async_result`] -template, which is used both to determine the return type and to extract the -return value from the handler. +[endsect] + +[section Outstanding work] -These two templates have been specialised to provide support for [link -boost_asio.overview.core.spawn stackful coroutines] and the C++11 `std::future` -class. +Until the asynchronous operation has completed, the asynchronous operation +shall maintain: -As an example, consider what happens when enabling `std::future` support by -using the `boost::asio::use_future` special value, as in: +[mdash] an object `work1` of type `executor_work_guard`, initialized +as `work1(ex1)`, and where `work1.owns_work() == true`; and - std::future length = - my_socket.async_read_some(my_buffer, boost::asio::use_future); +[mdash] an object `work2` of type `executor_work_guard`, initialized +as `work2(ex2)`, and where `work2.owns_work() == true`. -When a handler signature has the form: +[endsect] - void handler(error_code ec, result_type result); +[section Allocation of intermediate storage] -the initiating function returns a `std::future` templated on `result_type`. In -the above `async_read_some` example, this is `std::size_t`. If the asynchronous -operation fails, the `error_code` is converted into a `system_error` exception -and passed back to the caller through the future. +Asynchronous operations may allocate memory. [inline_note Such as a data +structure to store copies of the `completion_handler` object and the initiating +function's arguments.] -Where a handler signature has the form: +Let `Alloc1` be a type, satisfying the [link boost_asio.reference.ProtoAllocator +`ProtoAllocator`] requirements, that represents the asynchronous operation's +default allocation strategy. [inline_note Typically `std::allocator`.] +Let `alloc1` be a value of type `Alloc1`. - void handler(error_code ec); +A completion handler object of type `CompletionHandler` has an associated +allocator object `alloc2` of type `Alloc2` satisfying the [link +boost_asio.reference.ProtoAllocator `ProtoAllocator`] requirements. The type `Alloc2` +is `associated_allocator_t`. Let `alloc2` be a value +of type `Alloc2` obtained by performing +`get_associated_allocator(completion_handler, alloc1)`. -the initiating function instead returns `std::future`. +The asynchronous operations defined in this library: + +[mdash] If required, allocate memory using only the completion handler's +associated allocator. + +[mdash] Prior to completion handler execution, deallocate any memory allocated +using the completion handler's associated allocator. + +[std_note The implementation may perform operating system or underlying API +calls that perform memory allocations not using the associated allocator. +Invocations of the allocator functions may not introduce data races (See C++Std +\[res.on.data.races\]).] + +[endsect] + +[section Execution of completion handler on completion of asynchronous operation] + +Let `Args...` be the argument types of the completion signature `Signature` and +let [^['N]] be `sizeof...(Args)`. Let [^['i]] be in the range [half_open_range +`0`,[^['N]]]. Let [^T[sub ['i]]] be the [^['i]]th type in `Args...` and let +[^t[sub ['i]]] be the [^['i]]th completion handler argument associated with +[^T[sub ['i]]]. + +Let `f` be a function object, callable as `f()`, that invokes +`completion_handler` as if by [^completion_handler(forward(t[sub +['0]]), ..., forward(t[sub ['N-1]]))]. + +If an asynchonous operation completes immediately (that is, within the thread +of execution calling the initiating function, and before the initiating +function returns), the completion handler shall be submitted for execution as +if by performing `ex2.post(std::move(f), alloc2)`. Otherwise, the completion +handler shall be submitted for execution as if by performing +`ex2.dispatch(std::move(f), alloc2)`. + +[endsect] + +[section Completion handlers and exceptions] + +Completion handlers are permitted to throw exceptions. The effect of any +exception propagated from the execution of a completion handler is determined +by the executor which is executing the completion handler. + +[endsect] [endsect] diff --git a/doc/requirements/asynchronous_socket_operations.qbk b/doc/requirements/asynchronous_socket_operations.qbk new file mode 100644 index 0000000000..a1963e4b73 --- /dev/null +++ b/doc/requirements/asynchronous_socket_operations.qbk @@ -0,0 +1,39 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:asynchronous_socket_operations Requirements on asynchronous socket operations] + +In this library, ['asynchronous socket operations] are those member functions +having prefix `async_`. + +For an object `s`, a program may initiate asynchronous socket operations such +that there are multiple simultaneously outstanding asynchronous operations. + +When there are multiple outstanding asynchronous [link +boost_asio.reference.read_write_operations read operations] on `s`: + +[mdash] having no argument `flags` of type `socket_base::message_flags`, or + +[mdash] having an argument `flags` of type `socket_base::message_flags` but +where `(flags & socket_base::message_out_of_band) == 0` + +then the `buffers` are filled in the order in which these operations were +issued. The order of invocation of the completion handlers for these operations +is unspecified. + +When there are multiple outstanding asynchronous [link +boost_asio.reference.read_write_operations read operations] on `s` having an argument +`flags` of type `socket_base::message_flags` where `(flags & +socket_base::message_out_of_band) != 0` then the `buffers` are filled in the +order in which these operations were issued. + +When there are multiple outstanding asynchronous [link +boost_asio.reference.read_write_operations write operations] on `s`, the `buffers` +are transmitted in the order in which these operations were issued. The order +of invocation of the completion handlers for these operations is unspecified. + +[endsect] diff --git a/doc/requirements/read_write_operations.qbk b/doc/requirements/read_write_operations.qbk new file mode 100644 index 0000000000..250136c56d --- /dev/null +++ b/doc/requirements/read_write_operations.qbk @@ -0,0 +1,34 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:read_write_operations Requirements on read and write operations] + +A ['read operation] is an operation that reads data into a mutable buffer +sequence argument of a type meeting [link boost_asio.reference.MutableBufferSequence +`MutableBufferSequence`] requirements. The mutable buffer sequence specifies +memory where the data should be placed. A read operation shall always fill a +buffer in the sequence completely before proceeding to the next. + +A ['write operation] is an operation that writes data from a constant buffer +sequence argument of a type meeting [link boost_asio.reference.ConstBufferSequence +`ConstBufferSequence`] requirements. The constant buffer sequence specifies +memory where the data to be written is located. A write operation shall always +write a buffer in the sequence completely before proceeding to the next. + +If a read or write operation is also an [link +boost_asio.reference.asynchronous_operations asynchronous operation], the operation +shall maintain one or more copies of the buffer sequence until such time as the +operation no longer requires access to the memory specified by the buffers in +the sequence. The program shall ensure the memory remains valid until: + +[mdash] the last copy of the buffer sequence is destroyed, or + +[mdash] the completion handler for the asynchronous operation is invoked, + +whichever comes first. + +[endsect] diff --git a/doc/requirements/synchronous_socket_operations.qbk b/doc/requirements/synchronous_socket_operations.qbk new file mode 100644 index 0000000000..ac2ca6b444 --- /dev/null +++ b/doc/requirements/synchronous_socket_operations.qbk @@ -0,0 +1,37 @@ +[/ + / Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:synchronous_socket_operations Requirements on synchronous socket operations] + +In this section, ['synchronous socket operations] are those member functions +specified as two overloads, with and without an argument of type `error_code&`: + + ``[*['R f]]``(``['[*A1]]`` a1, ``['[*A2]]`` a2, ..., ``['[*AN]]`` aN); + ``[*['R f]]``(``['[*A1]]`` a1, ``['[*A2]]`` a2, ..., ``['[*AN]]`` aN, error_code& ec); + +For an object `s`, the conditions under which its synchronous socket operations +may block the calling thread (C++Std [defns.block]) are determined as follows. + +If: + +[mdash] `s.non_blocking() == true`, + +[mdash] the synchronous socket operation is specified in terms of a __POSIX__ +function other than `__poll__`, + +[mdash] that __POSIX__ function lists `EWOULDBLOCK` or `EAGAIN` +in its failure conditions, and + +[mdash] the effects of the operation cannot be established immediately + +then the synchronous socket operation shall not block the calling thread. +[inline_note And the effects of the operation are not established.] + +Otherwise, the synchronous socket operation shall block the calling thread +until the effects are established. + +[endsect] diff --git a/example/cpp03/allocation/server.cpp b/example/cpp03/allocation/server.cpp index 40bd91736f..15454df702 100644 --- a/example/cpp03/allocation/server.cpp +++ b/example/cpp03/allocation/server.cpp @@ -120,8 +120,8 @@ class session : public boost::enable_shared_from_this { public: - session(boost::asio::io_service& io_service) - : socket_(io_service) + session(boost::asio::io_context& io_context) + : socket_(io_context) { } @@ -183,11 +183,11 @@ typedef boost::shared_ptr session_ptr; class server { public: - server(boost::asio::io_service& io_service, short port) - : io_service_(io_service), - acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) + server(boost::asio::io_context& io_context, short port) + : io_context_(io_context), + acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { - session_ptr new_session(new session(io_service_)); + session_ptr new_session(new session(io_context_)); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); @@ -201,14 +201,14 @@ class server new_session->start(); } - new_session.reset(new session(io_service_)); + new_session.reset(new session(io_context_)); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; tcp::acceptor acceptor_; }; @@ -222,12 +222,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); + server s(io_context, atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/buffers/reference_counted.cpp b/example/cpp03/buffers/reference_counted.cpp index 504662cd2b..81128f5986 100644 --- a/example/cpp03/buffers/reference_counted.cpp +++ b/example/cpp03/buffers/reference_counted.cpp @@ -43,8 +43,8 @@ class session : public boost::enable_shared_from_this { public: - session(boost::asio::io_service& io_service) - : socket_(io_service) + session(boost::asio::io_context& io_context) + : socket_(io_context) { } @@ -76,11 +76,11 @@ typedef boost::shared_ptr session_ptr; class server { public: - server(boost::asio::io_service& io_service, short port) - : io_service_(io_service), - acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) + server(boost::asio::io_context& io_context, short port) + : io_context_(io_context), + acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { - session_ptr new_session(new session(io_service_)); + session_ptr new_session(new session(io_context_)); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); @@ -94,14 +94,14 @@ class server new_session->start(); } - new_session.reset(new session(io_service_)); + new_session.reset(new session(io_context_)); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; tcp::acceptor acceptor_; }; @@ -115,12 +115,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); + server s(io_context, atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/chat/chat_client.cpp b/example/cpp03/chat/chat_client.cpp index 71bd50d6d2..e37dfe4b57 100644 --- a/example/cpp03/chat/chat_client.cpp +++ b/example/cpp03/chat/chat_client.cpp @@ -23,24 +23,26 @@ typedef std::deque chat_message_queue; class chat_client { public: - chat_client(boost::asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) - : io_service_(io_service), - socket_(io_service) + chat_client(boost::asio::io_context& io_context, + const tcp::resolver::results_type& endpoints) + : io_context_(io_context), + socket_(io_context) { - boost::asio::async_connect(socket_, endpoint_iterator, + boost::asio::async_connect(socket_, endpoints, boost::bind(&chat_client::handle_connect, this, boost::asio::placeholders::error)); } void write(const chat_message& msg) { - io_service_.post(boost::bind(&chat_client::do_write, this, msg)); + boost::asio::post(io_context_, + boost::bind(&chat_client::do_write, this, msg)); } void close() { - io_service_.post(boost::bind(&chat_client::do_close, this)); + boost::asio::post(io_context_, + boost::bind(&chat_client::do_close, this)); } private: @@ -128,7 +130,7 @@ class chat_client } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; tcp::socket socket_; chat_message read_msg_; chat_message_queue write_msgs_; @@ -144,15 +146,14 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - tcp::resolver resolver(io_service); - tcp::resolver::query query(argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = resolver.resolve(argv[1], argv[2]); - chat_client c(io_service, iterator); + chat_client c(io_context, endpoints); - boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service)); + boost::thread t(boost::bind(&boost::asio::io_context::run, &io_context)); char line[chat_message::max_body_length + 1]; while (std::cin.getline(line, chat_message::max_body_length + 1)) diff --git a/example/cpp03/chat/chat_server.cpp b/example/cpp03/chat/chat_server.cpp index 611db89243..903b568bce 100644 --- a/example/cpp03/chat/chat_server.cpp +++ b/example/cpp03/chat/chat_server.cpp @@ -77,8 +77,8 @@ class chat_session public boost::enable_shared_from_this { public: - chat_session(boost::asio::io_service& io_service, chat_room& room) - : socket_(io_service), + chat_session(boost::asio::io_context& io_context, chat_room& room) + : socket_(io_context), room_(room) { } @@ -177,17 +177,17 @@ typedef boost::shared_ptr chat_session_ptr; class chat_server { public: - chat_server(boost::asio::io_service& io_service, + chat_server(boost::asio::io_context& io_context, const tcp::endpoint& endpoint) - : io_service_(io_service), - acceptor_(io_service, endpoint) + : io_context_(io_context), + acceptor_(io_context, endpoint) { start_accept(); } void start_accept() { - chat_session_ptr new_session(new chat_session(io_service_, room_)); + chat_session_ptr new_session(new chat_session(io_context_, room_)); acceptor_.async_accept(new_session->socket(), boost::bind(&chat_server::handle_accept, this, new_session, boost::asio::placeholders::error)); @@ -205,7 +205,7 @@ class chat_server } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; tcp::acceptor acceptor_; chat_room room_; }; @@ -225,18 +225,18 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; chat_server_list servers; for (int i = 1; i < argc; ++i) { using namespace std; // For atoi. tcp::endpoint endpoint(tcp::v4(), atoi(argv[i])); - chat_server_ptr server(new chat_server(io_service, endpoint)); + chat_server_ptr server(new chat_server(io_context, endpoint)); servers.push_back(server); } - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/chat/posix_chat_client.cpp b/example/cpp03/chat/posix_chat_client.cpp index 434f9f5916..40844c94e4 100644 --- a/example/cpp03/chat/posix_chat_client.cpp +++ b/example/cpp03/chat/posix_chat_client.cpp @@ -24,14 +24,14 @@ namespace posix = boost::asio::posix; class posix_chat_client { public: - posix_chat_client(boost::asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) - : socket_(io_service), - input_(io_service, ::dup(STDIN_FILENO)), - output_(io_service, ::dup(STDOUT_FILENO)), + posix_chat_client(boost::asio::io_context& io_context, + const tcp::resolver::results_type& endpoints) + : socket_(io_context), + input_(io_context, ::dup(STDIN_FILENO)), + output_(io_context, ::dup(STDOUT_FILENO)), input_buffer_(chat_message::max_body_length) { - boost::asio::async_connect(socket_, endpoint_iterator, + boost::asio::async_connect(socket_, endpoints, boost::bind(&posix_chat_client::handle_connect, this, boost::asio::placeholders::error)); } @@ -182,15 +182,14 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - tcp::resolver resolver(io_service); - tcp::resolver::query query(argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = resolver.resolve(argv[1], argv[2]); - posix_chat_client c(io_service, iterator); + posix_chat_client c(io_context, endpoints); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/echo/async_tcp_echo_server.cpp b/example/cpp03/echo/async_tcp_echo_server.cpp index 2aa2e6c65e..f0a672dde6 100644 --- a/example/cpp03/echo/async_tcp_echo_server.cpp +++ b/example/cpp03/echo/async_tcp_echo_server.cpp @@ -18,8 +18,8 @@ using boost::asio::ip::tcp; class session { public: - session(boost::asio::io_service& io_service) - : socket_(io_service) + session(boost::asio::io_context& io_context) + : socket_(io_context) { } @@ -76,9 +76,9 @@ class session class server { public: - server(boost::asio::io_service& io_service, short port) - : io_service_(io_service), - acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) + server(boost::asio::io_context& io_context, short port) + : io_context_(io_context), + acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { start_accept(); } @@ -86,7 +86,7 @@ class server private: void start_accept() { - session* new_session = new session(io_service_); + session* new_session = new session(io_context_); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); @@ -107,7 +107,7 @@ class server start_accept(); } - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; tcp::acceptor acceptor_; }; @@ -121,12 +121,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); + server s(io_context, atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/echo/async_udp_echo_server.cpp b/example/cpp03/echo/async_udp_echo_server.cpp index 97049c9dd8..bdcd4f785b 100644 --- a/example/cpp03/echo/async_udp_echo_server.cpp +++ b/example/cpp03/echo/async_udp_echo_server.cpp @@ -18,8 +18,8 @@ using boost::asio::ip::udp; class server { public: - server(boost::asio::io_service& io_service, short port) - : socket_(io_service, udp::endpoint(udp::v4(), port)) + server(boost::asio::io_context& io_context, short port) + : socket_(io_context, udp::endpoint(udp::v4(), port)) { socket_.async_receive_from( boost::asio::buffer(data_, max_length), sender_endpoint_, @@ -76,12 +76,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); + server s(io_context, atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/echo/blocking_tcp_echo_client.cpp b/example/cpp03/echo/blocking_tcp_echo_client.cpp index 77792af005..1def9d0bc0 100644 --- a/example/cpp03/echo/blocking_tcp_echo_client.cpp +++ b/example/cpp03/echo/blocking_tcp_echo_client.cpp @@ -27,14 +27,14 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - tcp::resolver resolver(io_service); - tcp::resolver::query query(tcp::v4(), argv[1], argv[2]); - tcp::resolver::iterator iterator = resolver.resolve(query); + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = + resolver.resolve(tcp::v4(), argv[1], argv[2]); - tcp::socket s(io_service); - boost::asio::connect(s, iterator); + tcp::socket s(io_context); + boost::asio::connect(s, endpoints); using namespace std; // For strlen. std::cout << "Enter message: "; diff --git a/example/cpp03/echo/blocking_tcp_echo_server.cpp b/example/cpp03/echo/blocking_tcp_echo_server.cpp index 0c4529b4cc..c4acbe4e15 100644 --- a/example/cpp03/echo/blocking_tcp_echo_server.cpp +++ b/example/cpp03/echo/blocking_tcp_echo_server.cpp @@ -45,12 +45,12 @@ void session(socket_ptr sock) } } -void server(boost::asio::io_service& io_service, unsigned short port) +void server(boost::asio::io_context& io_context, unsigned short port) { - tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port)); + tcp::acceptor a(io_context, tcp::endpoint(tcp::v4(), port)); for (;;) { - socket_ptr sock(new tcp::socket(io_service)); + socket_ptr sock(new tcp::socket(io_context)); a.accept(*sock); boost::thread t(boost::bind(session, sock)); } @@ -66,10 +66,10 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server(io_service, atoi(argv[1])); + server(io_context, atoi(argv[1])); } catch (std::exception& e) { diff --git a/example/cpp03/echo/blocking_udp_echo_client.cpp b/example/cpp03/echo/blocking_udp_echo_client.cpp index 4f29e69b5e..3b1067a03e 100644 --- a/example/cpp03/echo/blocking_udp_echo_client.cpp +++ b/example/cpp03/echo/blocking_udp_echo_client.cpp @@ -27,20 +27,20 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - udp::socket s(io_service, udp::endpoint(udp::v4(), 0)); + udp::socket s(io_context, udp::endpoint(udp::v4(), 0)); - udp::resolver resolver(io_service); - udp::resolver::query query(udp::v4(), argv[1], argv[2]); - udp::resolver::iterator iterator = resolver.resolve(query); + udp::resolver resolver(io_context); + udp::resolver::results_type endpoints = + resolver.resolve(udp::v4(), argv[1], argv[2]); using namespace std; // For strlen. std::cout << "Enter message: "; char request[max_length]; std::cin.getline(request, max_length); size_t request_length = strlen(request); - s.send_to(boost::asio::buffer(request, request_length), *iterator); + s.send_to(boost::asio::buffer(request, request_length), *endpoints.begin()); char reply[max_length]; udp::endpoint sender_endpoint; diff --git a/example/cpp03/echo/blocking_udp_echo_server.cpp b/example/cpp03/echo/blocking_udp_echo_server.cpp index 31c9cd8b22..5e70a6e44f 100644 --- a/example/cpp03/echo/blocking_udp_echo_server.cpp +++ b/example/cpp03/echo/blocking_udp_echo_server.cpp @@ -16,9 +16,9 @@ using boost::asio::ip::udp; enum { max_length = 1024 }; -void server(boost::asio::io_service& io_service, unsigned short port) +void server(boost::asio::io_context& io_context, unsigned short port) { - udp::socket sock(io_service, udp::endpoint(udp::v4(), port)); + udp::socket sock(io_context, udp::endpoint(udp::v4(), port)); for (;;) { char data[max_length]; @@ -39,10 +39,10 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server(io_service, atoi(argv[1])); + server(io_context, atoi(argv[1])); } catch (std::exception& e) { diff --git a/example/cpp03/fork/daemon.cpp b/example/cpp03/fork/daemon.cpp index f16f7cf8c9..494e8d1bfa 100644 --- a/example/cpp03/fork/daemon.cpp +++ b/example/cpp03/fork/daemon.cpp @@ -8,7 +8,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include +#include #include #include #include @@ -23,8 +23,8 @@ using boost::asio::ip::udp; class udp_daytime_server { public: - udp_daytime_server(boost::asio::io_service& io_service) - : socket_(io_service, udp::endpoint(udp::v4(), 13)) + udp_daytime_server(boost::asio::io_context& io_context) + : socket_(io_context, udp::endpoint(udp::v4(), 13)) { start_receive(); } @@ -62,24 +62,24 @@ int main() { try { - boost::asio::io_service io_service; + boost::asio::io_context io_context; // Initialise the server before becoming a daemon. If the process is // started from a shell, this means any errors will be reported back to the // user. - udp_daytime_server server(io_service); + udp_daytime_server server(io_context); // Register signal handlers so that the daemon may be shut down. You may // also want to register for other signals, such as SIGHUP to trigger a // re-read of a configuration file. - boost::asio::signal_set signals(io_service, SIGINT, SIGTERM); + boost::asio::signal_set signals(io_context, SIGINT, SIGTERM); signals.async_wait( - boost::bind(&boost::asio::io_service::stop, &io_service)); + boost::bind(&boost::asio::io_context::stop, &io_context)); - // Inform the io_service that we are about to become a daemon. The - // io_service cleans up any internal resources, such as threads, that may + // Inform the io_context that we are about to become a daemon. The + // io_context cleans up any internal resources, such as threads, that may // interfere with forking. - io_service.notify_fork(boost::asio::io_service::fork_prepare); + io_context.notify_fork(boost::asio::io_context::fork_prepare); // Fork the process and have the parent exit. If the process was started // from a shell, this returns control to the user. Forking a new process is @@ -92,15 +92,15 @@ int main() // // When the exit() function is used, the program terminates without // invoking local variables' destructors. Only global variables are - // destroyed. As the io_service object is a local variable, this means + // destroyed. As the io_context object is a local variable, this means // we do not have to call: // - // io_service.notify_fork(boost::asio::io_service::fork_parent); + // io_context.notify_fork(boost::asio::io_context::fork_parent); // // However, this line should be added before each call to exit() if - // using a global io_service object. An additional call: + // using a global io_context object. An additional call: // - // io_service.notify_fork(boost::asio::io_service::fork_prepare); + // io_context.notify_fork(boost::asio::io_context::fork_prepare); // // should also precede the second fork(). exit(0); @@ -171,14 +171,14 @@ int main() return 1; } - // Inform the io_service that we have finished becoming a daemon. The - // io_service uses this opportunity to create any internal file descriptors + // Inform the io_context that we have finished becoming a daemon. The + // io_context uses this opportunity to create any internal file descriptors // that need to be private to the new process. - io_service.notify_fork(boost::asio::io_service::fork_child); + io_context.notify_fork(boost::asio::io_context::fork_child); - // The io_service can now be used normally. + // The io_context can now be used normally. syslog(LOG_INFO | LOG_USER, "Daemon started"); - io_service.run(); + io_context.run(); syslog(LOG_INFO | LOG_USER, "Daemon stopped"); } catch (std::exception& e) diff --git a/example/cpp03/fork/process_per_connection.cpp b/example/cpp03/fork/process_per_connection.cpp index 70faa02d57..305cdc2d23 100644 --- a/example/cpp03/fork/process_per_connection.cpp +++ b/example/cpp03/fork/process_per_connection.cpp @@ -8,7 +8,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include +#include #include #include #include @@ -25,11 +25,11 @@ using boost::asio::ip::tcp; class server { public: - server(boost::asio::io_service& io_service, unsigned short port) - : io_service_(io_service), - signal_(io_service, SIGCHLD), - acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) + server(boost::asio::io_context& io_context, unsigned short port) + : io_context_(io_context), + signal_(io_context, SIGCHLD), + acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), + socket_(io_context) { start_signal_wait(); start_accept(); @@ -65,17 +65,17 @@ class server { if (!ec) { - // Inform the io_service that we are about to fork. The io_service cleans + // Inform the io_context that we are about to fork. The io_context cleans // up any internal resources, such as threads, that may interfere with // forking. - io_service_.notify_fork(boost::asio::io_service::fork_prepare); + io_context_.notify_fork(boost::asio::io_context::fork_prepare); if (fork() == 0) { - // Inform the io_service that the fork is finished and that this is the - // child process. The io_service uses this opportunity to create any + // Inform the io_context that the fork is finished and that this is the + // child process. The io_context uses this opportunity to create any // internal file descriptors that must be private to the new process. - io_service_.notify_fork(boost::asio::io_service::fork_child); + io_context_.notify_fork(boost::asio::io_context::fork_child); // The child won't be accepting new connections, so we can close the // acceptor. It remains open in the parent. @@ -88,11 +88,11 @@ class server } else { - // Inform the io_service that the fork is finished (or failed) and that - // this is the parent process. The io_service uses this opportunity to + // Inform the io_context that the fork is finished (or failed) and that + // this is the parent process. The io_context uses this opportunity to // recreate any internal resources that were cleaned up during // preparation for the fork. - io_service_.notify_fork(boost::asio::io_service::fork_parent); + io_context_.notify_fork(boost::asio::io_context::fork_parent); socket_.close(); start_accept(); @@ -129,7 +129,7 @@ class server start_read(); } - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; boost::asio::signal_set signal_; tcp::acceptor acceptor_; tcp::socket socket_; @@ -146,12 +146,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); + server s(io_context, atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/http/client/async_client.cpp b/example/cpp03/http/client/async_client.cpp index c240ad6642..61832aa34f 100644 --- a/example/cpp03/http/client/async_client.cpp +++ b/example/cpp03/http/client/async_client.cpp @@ -20,10 +20,10 @@ using boost::asio::ip::tcp; class client { public: - client(boost::asio::io_service& io_service, + client(boost::asio::io_context& io_context, const std::string& server, const std::string& path) - : resolver_(io_service), - socket_(io_service) + : resolver_(io_context), + socket_(io_context) { // Form the request. We specify the "Connection: close" header so that the // server will close the socket after transmitting the response. This will @@ -36,22 +36,21 @@ class client // Start an asynchronous resolve to translate the server and service names // into a list of endpoints. - tcp::resolver::query query(server, "http"); - resolver_.async_resolve(query, + resolver_.async_resolve(server, "http", boost::bind(&client::handle_resolve, this, boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); + boost::asio::placeholders::results)); } private: void handle_resolve(const boost::system::error_code& err, - tcp::resolver::iterator endpoint_iterator) + const tcp::resolver::results_type& endpoints) { if (!err) { // Attempt a connection to each endpoint in the list until we // successfully establish a connection. - boost::asio::async_connect(socket_, endpoint_iterator, + boost::asio::async_connect(socket_, endpoints, boost::bind(&client::handle_connect, this, boost::asio::placeholders::error)); } @@ -192,9 +191,9 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; - client c(io_service, argv[1], argv[2]); - io_service.run(); + boost::asio::io_context io_context; + client c(io_context, argv[1], argv[2]); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/http/client/sync_client.cpp b/example/cpp03/http/client/sync_client.cpp index 2eea356ca5..6813e053f5 100644 --- a/example/cpp03/http/client/sync_client.cpp +++ b/example/cpp03/http/client/sync_client.cpp @@ -28,16 +28,15 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; // Get a list of endpoints corresponding to the server name. - tcp::resolver resolver(io_service); - tcp::resolver::query query(argv[1], "http"); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = resolver.resolve(argv[1], "http"); // Try each endpoint until we successfully establish a connection. - tcp::socket socket(io_service); - boost::asio::connect(socket, endpoint_iterator); + tcp::socket socket(io_context); + boost::asio::connect(socket, endpoints); // Form the request. We specify the "Connection: close" header so that the // server will close the socket after transmitting the response. This will diff --git a/example/cpp03/http/server/connection.cpp b/example/cpp03/http/server/connection.cpp index a9b04f401c..c922257697 100644 --- a/example/cpp03/http/server/connection.cpp +++ b/example/cpp03/http/server/connection.cpp @@ -17,9 +17,9 @@ namespace http { namespace server { -connection::connection(boost::asio::io_service& io_service, +connection::connection(boost::asio::io_context& io_context, connection_manager& manager, request_handler& handler) - : socket_(io_service), + : socket_(io_context), connection_manager_(manager), request_handler_(handler) { diff --git a/example/cpp03/http/server/connection.hpp b/example/cpp03/http/server/connection.hpp index e38b43a881..80bf20df5e 100644 --- a/example/cpp03/http/server/connection.hpp +++ b/example/cpp03/http/server/connection.hpp @@ -32,8 +32,8 @@ class connection private boost::noncopyable { public: - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, + /// Construct a connection with the given io_context. + explicit connection(boost::asio::io_context& io_context, connection_manager& manager, request_handler& handler); /// Get the socket associated with the connection. diff --git a/example/cpp03/http/server/server.cpp b/example/cpp03/http/server/server.cpp index 8ee0523a6d..1ebddad8d2 100644 --- a/example/cpp03/http/server/server.cpp +++ b/example/cpp03/http/server/server.cpp @@ -17,9 +17,9 @@ namespace server { server::server(const std::string& address, const std::string& port, const std::string& doc_root) - : io_service_(), - signals_(io_service_), - acceptor_(io_service_), + : io_context_(), + signals_(io_context_), + acceptor_(io_context_), connection_manager_(), new_connection_(), request_handler_(doc_root) @@ -35,9 +35,9 @@ 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(io_service_); - boost::asio::ip::tcp::resolver::query query(address, port); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); + boost::asio::ip::tcp::resolver resolver(io_context_); + boost::asio::ip::tcp::endpoint endpoint = + *resolver.resolve(address, port).begin(); acceptor_.open(endpoint.protocol()); acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.bind(endpoint); @@ -48,16 +48,16 @@ server::server(const std::string& address, const std::string& port, void server::run() { - // The io_service::run() call will block until all asynchronous operations + // The io_context::run() call will block until all asynchronous operations // have finished. While the server is running, there is always at least one // asynchronous operation outstanding: the asynchronous accept call waiting // for new incoming connections. - io_service_.run(); + io_context_.run(); } void server::start_accept() { - new_connection_.reset(new connection(io_service_, + new_connection_.reset(new connection(io_context_, connection_manager_, request_handler_)); acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, @@ -84,7 +84,7 @@ void server::handle_accept(const boost::system::error_code& e) void server::handle_stop() { // The server is stopped by cancelling all outstanding asynchronous - // operations. Once all operations have finished the io_service::run() call + // operations. Once all operations have finished the io_context::run() call // will exit. acceptor_.close(); connection_manager_.stop_all(); diff --git a/example/cpp03/http/server/server.hpp b/example/cpp03/http/server/server.hpp index 6662e3c2f4..8702dce85b 100644 --- a/example/cpp03/http/server/server.hpp +++ b/example/cpp03/http/server/server.hpp @@ -31,7 +31,7 @@ class server explicit server(const std::string& address, const std::string& port, const std::string& doc_root); - /// Run the server's io_service loop. + /// Run the server's io_context loop. void run(); private: @@ -44,8 +44,8 @@ class server /// Handle a request to stop the server. void handle_stop(); - /// The io_service used to perform asynchronous operations. - boost::asio::io_service io_service_; + /// The io_context used to perform asynchronous operations. + boost::asio::io_context io_context_; /// The signal_set is used to register for process termination notifications. boost::asio::signal_set signals_; diff --git a/example/cpp03/http/server2/Jamfile b/example/cpp03/http/server2/Jamfile index ae62b82d0b..40487e02c1 100644 --- a/example/cpp03/http/server2/Jamfile +++ b/example/cpp03/http/server2/Jamfile @@ -24,7 +24,7 @@ exe http_server : @boost/libs/thread/build/boost_thread @boost/libs/system/build/boost_system connection.cpp - io_service_pool.cpp + io_context_pool.cpp main.cpp mime_types.cpp reply.cpp diff --git a/example/cpp03/http/server2/Jamfile.v2 b/example/cpp03/http/server2/Jamfile.v2 index 41c1b05db9..2bad75f1c8 100644 --- a/example/cpp03/http/server2/Jamfile.v2 +++ b/example/cpp03/http/server2/Jamfile.v2 @@ -28,7 +28,7 @@ else if [ os.name ] = HAIKU exe server : connection.cpp - io_service_pool.cpp + io_context_pool.cpp main.cpp mime_types.cpp reply.cpp diff --git a/example/cpp03/http/server2/connection.cpp b/example/cpp03/http/server2/connection.cpp index e2700c6001..328e4a9fff 100644 --- a/example/cpp03/http/server2/connection.cpp +++ b/example/cpp03/http/server2/connection.cpp @@ -16,9 +16,9 @@ namespace http { namespace server2 { -connection::connection(boost::asio::io_service& io_service, +connection::connection(boost::asio::io_context& io_context, request_handler& handler) - : socket_(io_service), + : socket_(io_context), request_handler_(handler) { } diff --git a/example/cpp03/http/server2/connection.hpp b/example/cpp03/http/server2/connection.hpp index 7dff608277..b9ba677f56 100644 --- a/example/cpp03/http/server2/connection.hpp +++ b/example/cpp03/http/server2/connection.hpp @@ -30,8 +30,8 @@ class connection private boost::noncopyable { public: - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, + /// Construct a connection with the given io_context. + explicit connection(boost::asio::io_context& io_context, request_handler& handler); /// Get the socket associated with the connection. diff --git a/example/cpp03/http/server2/io_context_pool.cpp b/example/cpp03/http/server2/io_context_pool.cpp new file mode 100644 index 0000000000..ed47b75569 --- /dev/null +++ b/example/cpp03/http/server2/io_context_pool.cpp @@ -0,0 +1,70 @@ +// +// io_context_pool.cpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 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) +// + +#include "server.hpp" +#include +#include +#include +#include + +namespace http { +namespace server2 { + +io_context_pool::io_context_pool(std::size_t pool_size) + : next_io_context_(0) +{ + if (pool_size == 0) + throw std::runtime_error("io_context_pool size is 0"); + + // Give all the io_contexts work to do so that their run() functions will not + // exit until they are explicitly stopped. + for (std::size_t i = 0; i < pool_size; ++i) + { + io_context_ptr io_context(new boost::asio::io_context); + io_contexts_.push_back(io_context); + work_.push_back(boost::asio::make_work_guard(*io_context)); + } +} + +void io_context_pool::run() +{ + // Create a pool of threads to run all of the io_contexts. + std::vector > threads; + for (std::size_t i = 0; i < io_contexts_.size(); ++i) + { + boost::shared_ptr thread(new boost::thread( + boost::bind(&boost::asio::io_context::run, io_contexts_[i]))); + threads.push_back(thread); + } + + // Wait for all threads in the pool to exit. + for (std::size_t i = 0; i < threads.size(); ++i) + threads[i]->join(); +} + +void io_context_pool::stop() +{ + // Explicitly stop all io_contexts. + for (std::size_t i = 0; i < io_contexts_.size(); ++i) + io_contexts_[i]->stop(); +} + +boost::asio::io_context& io_context_pool::get_io_context() +{ + // Use a round-robin scheme to choose the next io_context to use. + boost::asio::io_context& io_context = *io_contexts_[next_io_context_]; + ++next_io_context_; + if (next_io_context_ == io_contexts_.size()) + next_io_context_ = 0; + return io_context; +} + +} // namespace server2 +} // namespace http diff --git a/example/cpp03/http/server2/io_context_pool.hpp b/example/cpp03/http/server2/io_context_pool.hpp new file mode 100644 index 0000000000..7af524a077 --- /dev/null +++ b/example/cpp03/http/server2/io_context_pool.hpp @@ -0,0 +1,58 @@ +// +// io_context_pool.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 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 HTTP_SERVER2_IO_SERVICE_POOL_HPP +#define HTTP_SERVER2_IO_SERVICE_POOL_HPP + +#include +#include +#include +#include +#include + +namespace http { +namespace server2 { + +/// A pool of io_context objects. +class io_context_pool + : private boost::noncopyable +{ +public: + /// Construct the io_context pool. + explicit io_context_pool(std::size_t pool_size); + + /// Run all io_context objects in the pool. + void run(); + + /// Stop all io_context objects in the pool. + void stop(); + + /// Get an io_context to use. + boost::asio::io_context& get_io_context(); + +private: + typedef boost::shared_ptr io_context_ptr; + typedef boost::asio::executor_work_guard< + boost::asio::io_context::executor_type> io_context_work; + + /// The pool of io_contexts. + std::vector io_contexts_; + + /// The work that keeps the io_contexts running. + std::list work_; + + /// The next io_context to use for a connection. + std::size_t next_io_context_; +}; + +} // namespace server2 +} // namespace http + +#endif // HTTP_SERVER2_IO_SERVICE_POOL_HPP diff --git a/example/cpp03/http/server2/io_service_pool.cpp b/example/cpp03/http/server2/io_service_pool.cpp deleted file mode 100644 index 9b948b8ddb..0000000000 --- a/example/cpp03/http/server2/io_service_pool.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// io_service_pool.cpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2017 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) -// - -#include "server.hpp" -#include -#include -#include -#include - -namespace http { -namespace server2 { - -io_service_pool::io_service_pool(std::size_t pool_size) - : next_io_service_(0) -{ - if (pool_size == 0) - throw std::runtime_error("io_service_pool size is 0"); - - // Give all the io_services work to do so that their run() functions will not - // exit until they are explicitly stopped. - for (std::size_t i = 0; i < pool_size; ++i) - { - io_service_ptr io_service(new boost::asio::io_service); - work_ptr work(new boost::asio::io_service::work(*io_service)); - io_services_.push_back(io_service); - work_.push_back(work); - } -} - -void io_service_pool::run() -{ - // Create a pool of threads to run all of the io_services. - std::vector > threads; - for (std::size_t i = 0; i < io_services_.size(); ++i) - { - boost::shared_ptr thread(new boost::thread( - boost::bind(&boost::asio::io_service::run, io_services_[i]))); - threads.push_back(thread); - } - - // Wait for all threads in the pool to exit. - for (std::size_t i = 0; i < threads.size(); ++i) - threads[i]->join(); -} - -void io_service_pool::stop() -{ - // Explicitly stop all io_services. - for (std::size_t i = 0; i < io_services_.size(); ++i) - io_services_[i]->stop(); -} - -boost::asio::io_service& io_service_pool::get_io_service() -{ - // Use a round-robin scheme to choose the next io_service to use. - boost::asio::io_service& io_service = *io_services_[next_io_service_]; - ++next_io_service_; - if (next_io_service_ == io_services_.size()) - next_io_service_ = 0; - return io_service; -} - -} // namespace server2 -} // namespace http diff --git a/example/cpp03/http/server2/io_service_pool.hpp b/example/cpp03/http/server2/io_service_pool.hpp deleted file mode 100644 index a0031388dc..0000000000 --- a/example/cpp03/http/server2/io_service_pool.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// io_service_pool.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2017 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 HTTP_SERVER2_IO_SERVICE_POOL_HPP -#define HTTP_SERVER2_IO_SERVICE_POOL_HPP - -#include -#include -#include -#include - -namespace http { -namespace server2 { - -/// A pool of io_service objects. -class io_service_pool - : private boost::noncopyable -{ -public: - /// Construct the io_service pool. - explicit io_service_pool(std::size_t pool_size); - - /// Run all io_service objects in the pool. - void run(); - - /// Stop all io_service objects in the pool. - void stop(); - - /// Get an io_service to use. - boost::asio::io_service& get_io_service(); - -private: - typedef boost::shared_ptr io_service_ptr; - typedef boost::shared_ptr work_ptr; - - /// The pool of io_services. - std::vector io_services_; - - /// The work that keeps the io_services running. - std::vector work_; - - /// The next io_service to use for a connection. - std::size_t next_io_service_; -}; - -} // namespace server2 -} // namespace http - -#endif // HTTP_SERVER2_IO_SERVICE_POOL_HPP diff --git a/example/cpp03/http/server2/server.cpp b/example/cpp03/http/server2/server.cpp index c3504d2764..d3bfa58ea7 100644 --- a/example/cpp03/http/server2/server.cpp +++ b/example/cpp03/http/server2/server.cpp @@ -15,10 +15,10 @@ namespace http { namespace server2 { server::server(const std::string& address, const std::string& port, - const std::string& doc_root, std::size_t io_service_pool_size) - : io_service_pool_(io_service_pool_size), - signals_(io_service_pool_.get_io_service()), - acceptor_(io_service_pool_.get_io_service()), + const std::string& doc_root, std::size_t io_context_pool_size) + : io_context_pool_(io_context_pool_size), + signals_(io_context_pool_.get_io_context()), + acceptor_(io_context_pool_.get_io_context()), new_connection_(), request_handler_(doc_root) { @@ -33,9 +33,9 @@ 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_io_service()); - boost::asio::ip::tcp::resolver::query query(address, port); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); + boost::asio::ip::tcp::resolver resolver(acceptor_.get_executor().context()); + boost::asio::ip::tcp::endpoint endpoint = + *resolver.resolve(address, port).begin(); acceptor_.open(endpoint.protocol()); acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.bind(endpoint); @@ -46,13 +46,13 @@ server::server(const std::string& address, const std::string& port, void server::run() { - io_service_pool_.run(); + io_context_pool_.run(); } void server::start_accept() { new_connection_.reset(new connection( - io_service_pool_.get_io_service(), request_handler_)); + io_context_pool_.get_io_context(), request_handler_)); acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); @@ -70,7 +70,7 @@ void server::handle_accept(const boost::system::error_code& e) void server::handle_stop() { - io_service_pool_.stop(); + io_context_pool_.stop(); } } // namespace server2 diff --git a/example/cpp03/http/server2/server.hpp b/example/cpp03/http/server2/server.hpp index 412a00cee1..a35415b5e0 100644 --- a/example/cpp03/http/server2/server.hpp +++ b/example/cpp03/http/server2/server.hpp @@ -17,7 +17,7 @@ #include #include #include "connection.hpp" -#include "io_service_pool.hpp" +#include "io_context_pool.hpp" #include "request_handler.hpp" namespace http { @@ -31,9 +31,9 @@ class server /// Construct the server to listen on the specified TCP address and port, and /// serve up files from the given directory. explicit server(const std::string& address, const std::string& port, - const std::string& doc_root, std::size_t io_service_pool_size); + const std::string& doc_root, std::size_t io_context_pool_size); - /// Run the server's io_service loop. + /// Run the server's io_context loop. void run(); private: @@ -46,8 +46,8 @@ class server /// Handle a request to stop the server. void handle_stop(); - /// The pool of io_service objects used to perform asynchronous operations. - io_service_pool io_service_pool_; + /// The pool of io_context objects used to perform asynchronous operations. + io_context_pool io_context_pool_; /// The signal_set is used to register for process termination notifications. boost::asio::signal_set signals_; diff --git a/example/cpp03/http/server3/connection.cpp b/example/cpp03/http/server3/connection.cpp index 5f77f03752..37890b570d 100644 --- a/example/cpp03/http/server3/connection.cpp +++ b/example/cpp03/http/server3/connection.cpp @@ -16,10 +16,10 @@ namespace http { namespace server3 { -connection::connection(boost::asio::io_service& io_service, +connection::connection(boost::asio::io_context& io_context, request_handler& handler) - : strand_(io_service), - socket_(io_service), + : strand_(io_context), + socket_(io_context), request_handler_(handler) { } @@ -32,7 +32,7 @@ boost::asio::ip::tcp::socket& connection::socket() void connection::start() { socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( + boost::asio::bind_executor(strand_, boost::bind(&connection::handle_read, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); @@ -51,7 +51,7 @@ void connection::handle_read(const boost::system::error_code& e, { request_handler_.handle_request(request_, reply_); boost::asio::async_write(socket_, reply_.to_buffers(), - strand_.wrap( + boost::asio::bind_executor(strand_, boost::bind(&connection::handle_write, shared_from_this(), boost::asio::placeholders::error))); } @@ -59,14 +59,14 @@ void connection::handle_read(const boost::system::error_code& e, { reply_ = reply::stock_reply(reply::bad_request); boost::asio::async_write(socket_, reply_.to_buffers(), - strand_.wrap( + boost::asio::bind_executor(strand_, boost::bind(&connection::handle_write, shared_from_this(), boost::asio::placeholders::error))); } else { socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( + boost::asio::bind_executor(strand_, boost::bind(&connection::handle_read, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); diff --git a/example/cpp03/http/server3/connection.hpp b/example/cpp03/http/server3/connection.hpp index e552c4a38c..420dd0e743 100644 --- a/example/cpp03/http/server3/connection.hpp +++ b/example/cpp03/http/server3/connection.hpp @@ -30,8 +30,8 @@ class connection private boost::noncopyable { public: - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, + /// Construct a connection with the given io_context. + explicit connection(boost::asio::io_context& io_context, request_handler& handler); /// Get the socket associated with the connection. @@ -49,7 +49,7 @@ class connection void handle_write(const boost::system::error_code& e); /// Strand to ensure the connection's handlers are not called concurrently. - boost::asio::io_service::strand strand_; + boost::asio::io_context::strand strand_; /// Socket for the connection. boost::asio::ip::tcp::socket socket_; diff --git a/example/cpp03/http/server3/server.cpp b/example/cpp03/http/server3/server.cpp index 3ce54d736c..fc1c651686 100644 --- a/example/cpp03/http/server3/server.cpp +++ b/example/cpp03/http/server3/server.cpp @@ -20,8 +20,8 @@ namespace server3 { server::server(const std::string& address, const std::string& port, const std::string& doc_root, std::size_t thread_pool_size) : thread_pool_size_(thread_pool_size), - signals_(io_service_), - acceptor_(io_service_), + signals_(io_context_), + acceptor_(io_context_), new_connection_(), request_handler_(doc_root) { @@ -36,9 +36,9 @@ 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(io_service_); - boost::asio::ip::tcp::resolver::query query(address, port); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); + boost::asio::ip::tcp::resolver resolver(io_context_); + boost::asio::ip::tcp::endpoint endpoint = + *resolver.resolve(address, port).begin(); acceptor_.open(endpoint.protocol()); acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.bind(endpoint); @@ -49,12 +49,12 @@ server::server(const std::string& address, const std::string& port, void server::run() { - // Create a pool of threads to run all of the io_services. + // Create a pool of threads to run all of the io_contexts. std::vector > threads; for (std::size_t i = 0; i < thread_pool_size_; ++i) { boost::shared_ptr thread(new boost::thread( - boost::bind(&boost::asio::io_service::run, &io_service_))); + boost::bind(&boost::asio::io_context::run, &io_context_))); threads.push_back(thread); } @@ -65,7 +65,7 @@ void server::run() void server::start_accept() { - new_connection_.reset(new connection(io_service_, request_handler_)); + new_connection_.reset(new connection(io_context_, request_handler_)); acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); @@ -83,7 +83,7 @@ void server::handle_accept(const boost::system::error_code& e) void server::handle_stop() { - io_service_.stop(); + io_context_.stop(); } } // namespace server3 diff --git a/example/cpp03/http/server3/server.hpp b/example/cpp03/http/server3/server.hpp index 5ff6bf3c4f..8f1b1c20af 100644 --- a/example/cpp03/http/server3/server.hpp +++ b/example/cpp03/http/server3/server.hpp @@ -32,7 +32,7 @@ class server explicit server(const std::string& address, const std::string& port, const std::string& doc_root, std::size_t thread_pool_size); - /// Run the server's io_service loop. + /// Run the server's io_context loop. void run(); private: @@ -45,11 +45,11 @@ class server /// Handle a request to stop the server. void handle_stop(); - /// The number of threads that will call io_service::run(). + /// The number of threads that will call io_context::run(). std::size_t thread_pool_size_; - /// The io_service used to perform asynchronous operations. - boost::asio::io_service io_service_; + /// The io_context used to perform asynchronous operations. + boost::asio::io_context io_context_; /// The signal_set is used to register for process termination notifications. boost::asio::signal_set signals_; diff --git a/example/cpp03/http/server4/main.cpp b/example/cpp03/http/server4/main.cpp index 48c3ec516c..449ffa3a3e 100644 --- a/example/cpp03/http/server4/main.cpp +++ b/example/cpp03/http/server4/main.cpp @@ -30,24 +30,24 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; // Launch the initial server coroutine. - http::server4::server(io_service, argv[1], argv[2], + http::server4::server(io_context, argv[1], argv[2], http::server4::file_handler(argv[3]))(); // Wait for signals indicating time to shut down. - boost::asio::signal_set signals(io_service); + boost::asio::signal_set signals(io_context); signals.add(SIGINT); signals.add(SIGTERM); #if defined(SIGQUIT) signals.add(SIGQUIT); #endif // defined(SIGQUIT) signals.async_wait(boost::bind( - &boost::asio::io_service::stop, &io_service)); + &boost::asio::io_context::stop, &io_context)); // Run the server. - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/http/server4/server.cpp b/example/cpp03/http/server4/server.cpp index 66aa329339..080fa345b9 100644 --- a/example/cpp03/http/server4/server.cpp +++ b/example/cpp03/http/server4/server.cpp @@ -15,14 +15,15 @@ namespace http { namespace server4 { -server::server(boost::asio::io_service& io_service, +server::server(boost::asio::io_context& io_context, const std::string& address, const std::string& port, boost::function request_handler) : request_handler_(request_handler) { - tcp::resolver resolver(io_service); - tcp::resolver::query query(address, port); - acceptor_.reset(new tcp::acceptor(io_service, *resolver.resolve(query))); + tcp::resolver resolver(io_context); + boost::asio::ip::tcp::endpoint endpoint = + *resolver.resolve(address, port).begin(); + acceptor_.reset(new tcp::acceptor(io_context, endpoint)); } // Enable the pseudo-keywords reenter, yield and fork. @@ -44,12 +45,12 @@ 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_io_service())); + socket_.reset(new tcp::socket(acceptor_->get_executor().context())); // Accept a new connection. The "yield" pseudo-keyword saves the current // line number and exits the coroutine's "reenter" block. We use the // server coroutine as the completion handler for the async_accept - // operation. When the asynchronous operation completes, the io_service + // operation. When the asynchronous operation completes, the io_context // invokes the function call operator, we "reenter" the coroutine, and // then control resumes at the following line. yield acceptor_->async_accept(*socket_, *this); diff --git a/example/cpp03/http/server4/server.hpp b/example/cpp03/http/server4/server.hpp index 7d01701af9..3ef3b68a9b 100644 --- a/example/cpp03/http/server4/server.hpp +++ b/example/cpp03/http/server4/server.hpp @@ -30,7 +30,7 @@ class server : boost::asio::coroutine public: /// Construct the server to listen on the specified TCP address and port, and /// serve up files from the given directory. - explicit server(boost::asio::io_service& io_service, + explicit server(boost::asio::io_context& io_context, const std::string& address, const std::string& port, boost::function request_handler); diff --git a/example/cpp03/icmp/ping.cpp b/example/cpp03/icmp/ping.cpp index a9aa57f808..4daf81948b 100644 --- a/example/cpp03/icmp/ping.cpp +++ b/example/cpp03/icmp/ping.cpp @@ -24,12 +24,11 @@ namespace posix_time = boost::posix_time; class pinger { public: - pinger(boost::asio::io_service& io_service, const char* destination) - : resolver_(io_service), socket_(io_service, icmp::v4()), - timer_(io_service), sequence_number_(0), num_replies_(0) + pinger(boost::asio::io_context& io_context, const char* destination) + : resolver_(io_context), socket_(io_context, icmp::v4()), + timer_(io_context), sequence_number_(0), num_replies_(0) { - icmp::resolver::query query(icmp::v4(), destination, ""); - destination_ = *resolver_.resolve(query); + destination_ = *resolver_.resolve(icmp::v4(), destination, "").begin(); start_send(); start_receive(); @@ -151,9 +150,9 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; - pinger p(io_service, argv[1]); - io_service.run(); + boost::asio::io_context io_context; + pinger p(io_context, argv[1]); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/invocation/prioritised_handlers.cpp b/example/cpp03/invocation/prioritised_handlers.cpp index 67ffee545a..ebf8483e81 100644 --- a/example/cpp03/invocation/prioritised_handlers.cpp +++ b/example/cpp03/invocation/prioritised_handlers.cpp @@ -127,32 +127,32 @@ void low_priority_handler() int main() { - boost::asio::io_service io_service; + boost::asio::io_context io_context; handler_priority_queue pri_queue; // Post a completion handler to be run immediately. - io_service.post(pri_queue.wrap(0, low_priority_handler)); + boost::asio::post(io_context, pri_queue.wrap(0, low_priority_handler)); // Start an asynchronous accept that will complete immediately. tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 0); - tcp::acceptor acceptor(io_service, endpoint); - tcp::socket server_socket(io_service); + tcp::acceptor acceptor(io_context, endpoint); + tcp::socket server_socket(io_context); acceptor.async_accept(server_socket, pri_queue.wrap(100, high_priority_handler)); - tcp::socket client_socket(io_service); + tcp::socket client_socket(io_context); client_socket.connect(acceptor.local_endpoint()); // Set a deadline timer to expire immediately. - boost::asio::deadline_timer timer(io_service); + boost::asio::deadline_timer timer(io_context); timer.expires_at(boost::posix_time::neg_infin); timer.async_wait(pri_queue.wrap(42, middle_priority_handler)); - while (io_service.run_one()) + while (io_context.run_one()) { // The custom invocation hook adds the handlers to the priority queue // rather than executing them from within the poll_one() call. - while (io_service.poll_one()) + while (io_context.poll_one()) ; pri_queue.execute_all(); diff --git a/example/cpp03/iostreams/daytime_server.cpp b/example/cpp03/iostreams/daytime_server.cpp index 7d7c3f0889..3e0356c79b 100644 --- a/example/cpp03/iostreams/daytime_server.cpp +++ b/example/cpp03/iostreams/daytime_server.cpp @@ -26,16 +26,16 @@ int main() { try { - boost::asio::io_service io_service; + boost::asio::io_context io_context; tcp::endpoint endpoint(tcp::v4(), 13); - tcp::acceptor acceptor(io_service, endpoint); + tcp::acceptor acceptor(io_context, endpoint); for (;;) { tcp::iostream stream; boost::system::error_code ec; - acceptor.accept(*stream.rdbuf(), ec); + acceptor.accept(stream.socket(), ec); if (!ec) { stream << make_daytime_string(); diff --git a/example/cpp03/iostreams/http_client.cpp b/example/cpp03/iostreams/http_client.cpp index 5f2bfc8736..52842abfd7 100644 --- a/example/cpp03/iostreams/http_client.cpp +++ b/example/cpp03/iostreams/http_client.cpp @@ -1,5 +1,5 @@ // -// sync_client.cpp +// http_client.cpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) @@ -33,7 +33,7 @@ int main(int argc, char* argv[]) // The entire sequence of I/O operations must complete within 60 seconds. // If an expiry occurs, the socket is automatically closed and the stream // becomes bad. - s.expires_from_now(boost::posix_time::seconds(60)); + s.expires_after(boost::posix_time::seconds(60)); // Establish a connection to the server. s.connect(argv[1], "http"); diff --git a/example/cpp03/local/connect_pair.cpp b/example/cpp03/local/connect_pair.cpp index 1d8a7f3196..934731b710 100644 --- a/example/cpp03/local/connect_pair.cpp +++ b/example/cpp03/local/connect_pair.cpp @@ -23,8 +23,8 @@ using boost::asio::local::stream_protocol; class uppercase_filter { public: - uppercase_filter(boost::asio::io_service& io_service) - : socket_(io_service) + uppercase_filter(boost::asio::io_context& io_context) + : socket_(io_context) { } @@ -82,11 +82,11 @@ class uppercase_filter boost::array data_; }; -void run(boost::asio::io_service* io_service) +void run(boost::asio::io_context* io_context) { try { - io_service->run(); + io_context->run(); } catch (std::exception& e) { @@ -99,16 +99,16 @@ int main() { try { - boost::asio::io_service io_service; + boost::asio::io_context io_context; // Create filter and establish a connection to it. - uppercase_filter filter(io_service); - stream_protocol::socket socket(io_service); + uppercase_filter filter(io_context); + stream_protocol::socket socket(io_context); boost::asio::local::connect_pair(socket, filter.socket()); filter.start(); - // The io_service runs in a background thread to perform filtering. - boost::thread thread(boost::bind(run, &io_service)); + // The io_context runs in a background thread to perform filtering. + boost::thread thread(boost::bind(run, &io_context)); for (;;) { diff --git a/example/cpp03/local/stream_client.cpp b/example/cpp03/local/stream_client.cpp index f0f7b978ca..915cbe2f3f 100644 --- a/example/cpp03/local/stream_client.cpp +++ b/example/cpp03/local/stream_client.cpp @@ -29,9 +29,9 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - stream_protocol::socket s(io_service); + stream_protocol::socket s(io_context); s.connect(stream_protocol::endpoint(argv[1])); using namespace std; // For strlen. diff --git a/example/cpp03/local/stream_server.cpp b/example/cpp03/local/stream_server.cpp index a376a82139..05194240c3 100644 --- a/example/cpp03/local/stream_server.cpp +++ b/example/cpp03/local/stream_server.cpp @@ -24,8 +24,8 @@ class session : public boost::enable_shared_from_this { public: - session(boost::asio::io_service& io_service) - : socket_(io_service) + session(boost::asio::io_context& io_context) + : socket_(io_context) { } @@ -81,11 +81,11 @@ typedef boost::shared_ptr session_ptr; class server { public: - server(boost::asio::io_service& io_service, const std::string& file) - : io_service_(io_service), - acceptor_(io_service, stream_protocol::endpoint(file)) + server(boost::asio::io_context& io_context, const std::string& file) + : io_context_(io_context), + acceptor_(io_context, stream_protocol::endpoint(file)) { - session_ptr new_session(new session(io_service_)); + session_ptr new_session(new session(io_context_)); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); @@ -99,14 +99,14 @@ class server new_session->start(); } - new_session.reset(new session(io_service_)); + new_session.reset(new session(io_context_)); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; stream_protocol::acceptor acceptor_; }; @@ -121,12 +121,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; std::remove(argv[1]); - server s(io_service, argv[1]); + server s(io_context, argv[1]); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/multicast/receiver.cpp b/example/cpp03/multicast/receiver.cpp index da98a5f21c..ed9d5ccb27 100644 --- a/example/cpp03/multicast/receiver.cpp +++ b/example/cpp03/multicast/receiver.cpp @@ -18,10 +18,10 @@ const short multicast_port = 30001; class receiver { public: - receiver(boost::asio::io_service& io_service, + receiver(boost::asio::io_context& io_context, const boost::asio::ip::address& listen_address, const boost::asio::ip::address& multicast_address) - : socket_(io_service) + : socket_(io_context) { // Create the socket so that multiple may be bound to the same address. boost::asio::ip::udp::endpoint listen_endpoint( @@ -78,11 +78,11 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; - receiver r(io_service, - boost::asio::ip::address::from_string(argv[1]), - boost::asio::ip::address::from_string(argv[2])); - io_service.run(); + boost::asio::io_context io_context; + receiver r(io_context, + boost::asio::ip::make_address(argv[1]), + boost::asio::ip::make_address(argv[2])); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/multicast/sender.cpp b/example/cpp03/multicast/sender.cpp index 42e763429c..15267248b4 100644 --- a/example/cpp03/multicast/sender.cpp +++ b/example/cpp03/multicast/sender.cpp @@ -21,11 +21,11 @@ const int max_message_count = 10; class sender { public: - sender(boost::asio::io_service& io_service, + sender(boost::asio::io_context& io_context, const boost::asio::ip::address& multicast_address) : endpoint_(multicast_address, multicast_port), - socket_(io_service, endpoint_.protocol()), - timer_(io_service), + socket_(io_context, endpoint_.protocol()), + timer_(io_context), message_count_(0) { std::ostringstream os; @@ -86,9 +86,9 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; - sender s(io_service, boost::asio::ip::address::from_string(argv[1])); - io_service.run(); + boost::asio::io_context io_context; + sender s(io_context, boost::asio::ip::make_address(argv[1])); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/nonblocking/third_party_lib.cpp b/example/cpp03/nonblocking/third_party_lib.cpp index cbaef56e2c..6ace6d8c63 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_service& io_service) + static pointer create(boost::asio::io_context& io_context) { - return pointer(new connection(io_service)); + return pointer(new connection(io_context)); } tcp::socket& socket() @@ -102,8 +102,8 @@ class connection } private: - connection(boost::asio::io_service& io_service) - : socket_(io_service), + connection(boost::asio::io_context& io_context) + : socket_(io_context), session_impl_(socket_), read_in_progress_(false), write_in_progress_(false) @@ -116,8 +116,7 @@ class connection if (session_impl_.want_read() && !read_in_progress_) { read_in_progress_ = true; - socket_.async_read_some( - boost::asio::null_buffers(), + socket_.async_wait(tcp::socket::wait_read, boost::bind(&connection::handle_read, shared_from_this(), boost::asio::placeholders::error)); @@ -127,8 +126,7 @@ class connection if (session_impl_.want_write() && !write_in_progress_) { write_in_progress_ = true; - socket_.async_write_some( - boost::asio::null_buffers(), + socket_.async_wait(tcp::socket::wait_write, boost::bind(&connection::handle_write, shared_from_this(), boost::asio::placeholders::error)); @@ -185,8 +183,8 @@ class connection class server { public: - server(boost::asio::io_service& io_service, unsigned short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) + server(boost::asio::io_context& io_context, unsigned short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { start_accept(); } @@ -195,7 +193,7 @@ class server void start_accept() { connection::pointer new_connection = - connection::create(acceptor_.get_io_service()); + connection::create(acceptor_.get_executor().context()); acceptor_.async_accept(new_connection->socket(), boost::bind(&server::handle_accept, this, new_connection, @@ -226,12 +224,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); + server s(io_context, atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/porthopper/client.cpp b/example/cpp03/porthopper/client.cpp index ba607a7054..05c020cd75 100644 --- a/example/cpp03/porthopper/client.cpp +++ b/example/cpp03/porthopper/client.cpp @@ -37,20 +37,19 @@ int main(int argc, char* argv[]) std::string host_name = argv[1]; std::string port = argv[2]; - boost::asio::io_service io_service; + boost::asio::io_context io_context; // Determine the location of the server. - tcp::resolver resolver(io_service); - tcp::resolver::query query(host_name, port); - tcp::endpoint remote_endpoint = *resolver.resolve(query); + tcp::resolver resolver(io_context); + tcp::endpoint remote_endpoint = *resolver.resolve(host_name, port).begin(); // Establish the control connection to the server. - tcp::socket control_socket(io_service); + tcp::socket control_socket(io_context); control_socket.connect(remote_endpoint); // Create a datagram socket to receive data from the server. boost::shared_ptr data_socket( - new udp::socket(io_service, udp::endpoint(udp::v4(), 0))); + new udp::socket(io_context, udp::endpoint(udp::v4(), 0))); // Determine what port we will receive data on. udp::endpoint data_endpoint = data_socket->local_endpoint(); @@ -82,7 +81,7 @@ int main(int argc, char* argv[]) // Create the new data socket. boost::shared_ptr new_data_socket( - new udp::socket(io_service, udp::endpoint(udp::v4(), 0))); + new udp::socket(io_context, udp::endpoint(udp::v4(), 0))); // Determine the new port we will use to receive data. udp::endpoint new_data_endpoint = new_data_socket->local_endpoint(); @@ -126,7 +125,7 @@ int main(int argc, char* argv[]) // Even though we're performing a renegotation, we want to continue // receiving data as smoothly as possible. Therefore we will continue to // try to receive a frame from the server on the old data socket. If we - // receive a frame on this socket we will interrupt the io_service, + // receive a frame on this socket we will interrupt the io_context, // print the frame, and resume waiting for the other operations to // complete. frame f2; @@ -138,19 +137,19 @@ int main(int argc, char* argv[]) lambda::if_(!lambda::_1) [ // We have successfully received a frame on the old data - // socket. Stop the io_service so that we can print it. - lambda::bind(&boost::asio::io_service::stop, &io_service), + // socket. Stop the io_context so that we can print it. + lambda::bind(&boost::asio::io_context::stop, &io_context), lambda::var(done) = false ] )); } // Run the operations in parallel. This will block until all operations - // have finished, or until the io_service is interrupted. (No threads!) - io_service.reset(); - io_service.run(); + // have finished, or until the io_context is interrupted. (No threads!) + io_context.restart(); + io_context.run(); - // If the io_service.run() was interrupted then we have received a frame + // If the io_context.run() was interrupted then we have received a frame // on the old data socket. We need to keep waiting for the renegotation // operations to complete. if (!done) diff --git a/example/cpp03/porthopper/server.cpp b/example/cpp03/porthopper/server.cpp index 0fdc7e011b..0426c365be 100644 --- a/example/cpp03/porthopper/server.cpp +++ b/example/cpp03/porthopper/server.cpp @@ -29,14 +29,15 @@ class server { public: // Construct the server to wait for incoming control connections. - server(boost::asio::io_service& io_service, unsigned short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - timer_(io_service), - udp_socket_(io_service, udp::endpoint(udp::v4(), 0)), + server(boost::asio::io_context& io_context, unsigned short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), + timer_(io_context), + udp_socket_(io_context, udp::endpoint(udp::v4(), 0)), next_frame_number_(1) { // Start waiting for a new control connection. - tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_io_service())); + tcp_socket_ptr new_socket( + new tcp::socket(acceptor_.get_executor().context())); acceptor_.async_accept(*new_socket, boost::bind(&server::handle_accept, this, boost::asio::placeholders::error, new_socket)); @@ -59,7 +60,8 @@ class server } // Start waiting for a new control connection. - tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_io_service())); + tcp_socket_ptr new_socket( + new tcp::socket(acceptor_.get_executor().context())); acceptor_.async_accept(*new_socket, boost::bind(&server::handle_accept, this, boost::asio::placeholders::error, new_socket)); @@ -73,7 +75,7 @@ class server { // Delay handling of the control request to simulate network latency. timer_ptr delay_timer( - new boost::asio::deadline_timer(acceptor_.get_io_service())); + new boost::asio::deadline_timer(acceptor_.get_executor().context())); delay_timer->expires_from_now(boost::posix_time::seconds(2)); delay_timer->async_wait( boost::bind(&server::handle_control_request_timer, this, @@ -171,12 +173,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); + server s(io_context, atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/serialization/client.cpp b/example/cpp03/serialization/client.cpp index 2d1f609b45..06f3e4c09e 100644 --- a/example/cpp03/serialization/client.cpp +++ b/example/cpp03/serialization/client.cpp @@ -23,12 +23,12 @@ class client { public: /// Constructor starts the asynchronous connect operation. - client(boost::asio::io_service& io_service, + client(boost::asio::io_context& io_context, const std::string& host, const std::string& service) - : connection_(io_service) + : connection_(io_context) { // Resolve the host name into an IP address. - boost::asio::ip::tcp::resolver resolver(io_service); + boost::asio::ip::tcp::resolver resolver(io_context); boost::asio::ip::tcp::resolver::query query(host, service); boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); @@ -54,7 +54,7 @@ class client else { // An error occurred. Log it and return. Since we are not starting a new - // operation the io_service will run out of work to do and the client will + // operation the io_context will run out of work to do and the client will // exit. std::cerr << e.message() << std::endl; } @@ -87,7 +87,7 @@ class client std::cerr << e.message() << std::endl; } - // Since we are not starting a new operation the io_service will run out of + // Since we are not starting a new operation the io_context will run out of // work to do and the client will exit. } @@ -112,9 +112,9 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; - s11n_example::client client(io_service, argv[1], argv[2]); - io_service.run(); + boost::asio::io_context io_context; + s11n_example::client client(io_context, argv[1], argv[2]); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/serialization/connection.hpp b/example/cpp03/serialization/connection.hpp index 41a24ab224..464abb63f9 100644 --- a/example/cpp03/serialization/connection.hpp +++ b/example/cpp03/serialization/connection.hpp @@ -35,8 +35,8 @@ class connection { public: /// Constructor. - connection(boost::asio::io_service& io_service) - : socket_(io_service) + connection(boost::asio::io_context& io_context) + : socket_(io_context) { } @@ -65,7 +65,7 @@ class connection { // Something went wrong, inform the caller. boost::system::error_code error(boost::asio::error::invalid_argument); - socket_.get_io_service().post(boost::bind(handler, error)); + socket_.get_io_context().post(boost::bind(handler, error)); return; } outbound_header_ = header_stream.str(); diff --git a/example/cpp03/serialization/server.cpp b/example/cpp03/serialization/server.cpp index 8fd045da80..6fb4881d94 100644 --- a/example/cpp03/serialization/server.cpp +++ b/example/cpp03/serialization/server.cpp @@ -25,8 +25,8 @@ class server public: /// Constructor opens the acceptor and starts waiting for the first incoming /// connection. - server(boost::asio::io_service& io_service, unsigned short port) - : acceptor_(io_service, + server(boost::asio::io_context& io_context, unsigned short port) + : acceptor_(io_context, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) { // Create the data to be sent to each client. @@ -55,7 +55,7 @@ class server stocks_.push_back(s); // Start an accept operation for a new connection. - connection_ptr new_conn(new connection(acceptor_.get_io_service())); + connection_ptr new_conn(new connection(acceptor_.get_io_context())); acceptor_.async_accept(new_conn->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error, new_conn)); @@ -75,7 +75,7 @@ class server } // Start an accept operation for a new connection. - connection_ptr new_conn(new connection(acceptor_.get_io_service())); + connection_ptr new_conn(new connection(acceptor_.get_io_context())); acceptor_.async_accept(new_conn->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error, new_conn)); @@ -110,9 +110,9 @@ int main(int argc, char* argv[]) } unsigned short port = boost::lexical_cast(argv[1]); - boost::asio::io_service io_service; - s11n_example::server server(io_service, port); - io_service.run(); + boost::asio::io_context io_context; + s11n_example::server server(io_context, port); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/services/basic_logger.hpp b/example/cpp03/services/basic_logger.hpp index 380fd21500..0f56c2fef8 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_service The io_service object used to locate the logger service. + * @param io_context The io_context object used to locate the logger service. * * @param identifier An identifier for this logger. */ - explicit basic_logger(boost::asio::io_service& io_service, + explicit basic_logger(boost::asio::io_context& io_context, const std::string& identifier) - : service_(boost::asio::use_service(io_service)), + : service_(boost::asio::use_service(io_context)), impl_(service_.null()) { service_.create(impl_, identifier); @@ -52,10 +52,10 @@ class basic_logger service_.destroy(impl_); } - /// Get the io_service associated with the object. - boost::asio::io_service& get_io_service() + /// Get the io_context associated with the object. + boost::asio::io_context& get_io_context() { - return service_.get_io_service(); + return service_.get_io_context(); } /// Set the output file for all logger instances. diff --git a/example/cpp03/services/daytime_client.cpp b/example/cpp03/services/daytime_client.cpp index c812063acb..204382a989 100644 --- a/example/cpp03/services/daytime_client.cpp +++ b/example/cpp03/services/daytime_client.cpp @@ -12,15 +12,13 @@ #include #include #include "logger.hpp" -#include "stream_socket_service.hpp" -typedef boost::asio::basic_stream_socket > debug_stream_socket; +using boost::asio::ip::tcp; char read_buffer[1024]; void read_handler(const boost::system::error_code& e, - std::size_t bytes_transferred, debug_stream_socket* s) + std::size_t bytes_transferred, tcp::socket* s) { if (!e) { @@ -30,19 +28,33 @@ void read_handler(const boost::system::error_code& e, boost::bind(read_handler, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, s)); } + else + { + services::logger logger(s->get_executor().context(), "read_handler"); + + std::string msg = "Read error: "; + msg += e.message(); + logger.log(msg); + } } -void connect_handler(const boost::system::error_code& e, debug_stream_socket* s) +void connect_handler(const boost::system::error_code& e, tcp::socket* s) { + services::logger logger(s->get_executor().context(), "connect_handler"); + if (!e) { + logger.log("Connection established"); + s->async_read_some(boost::asio::buffer(read_buffer), boost::bind(read_handler, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, s)); } else { - std::cerr << e.message() << std::endl; + std::string msg = "Unable to establish connection: "; + msg += e.message(); + logger.log(msg); } } @@ -56,25 +68,25 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; // Set the name of the file that all logger instances will use. - services::logger logger(io_service, ""); + services::logger logger(io_context, ""); logger.use_file("log.txt"); // Resolve the address corresponding to the given host. - boost::asio::ip::tcp::resolver resolver(io_service); - boost::asio::ip::tcp::resolver::query query(argv[1], "daytime"); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = + resolver.resolve(argv[1], "daytime"); // Start an asynchronous connect. - debug_stream_socket socket(io_service); - boost::asio::async_connect(socket, iterator, + tcp::socket socket(io_context); + boost::asio::async_connect(socket, endpoints, boost::bind(connect_handler, boost::asio::placeholders::error, &socket)); - // Run the io_service until all operations have finished. - io_service.run(); + // Run the io_context until all operations have finished. + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/services/logger_service.cpp b/example/cpp03/services/logger_service.cpp index 23fc764f6b..1324d30745 100644 --- a/example/cpp03/services/logger_service.cpp +++ b/example/cpp03/services/logger_service.cpp @@ -12,6 +12,6 @@ namespace services { -boost::asio::io_service::id logger_service::id; +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 d5e76437da..c1eea40333 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_service::service + : public boost::asio::io_context::service { public: /// The unique service identifier. - static boost::asio::io_service::id id; + static boost::asio::io_context::id id; /// The backend implementation of a logger. struct logger_impl @@ -41,21 +41,21 @@ class logger_service /// The type for an implementation of the logger. typedef logger_impl* impl_type; - /// Constructor creates a thread to run a private io_service. - logger_service(boost::asio::io_service& io_service) - : boost::asio::io_service::service(io_service), - work_io_service_(), - work_(new boost::asio::io_service::work(work_io_service_)), + /// 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), + work_io_context_(), + work_(boost::asio::make_work_guard(work_io_context_)), work_thread_(new boost::thread( - boost::bind(&boost::asio::io_service::run, &work_io_service_))) + boost::bind(&boost::asio::io_context::run, &work_io_context_))) { } - /// Destructor shuts down the private io_service. + /// Destructor shuts down the private io_context. ~logger_service() { - /// Indicate that we have finished with the private io_service. Its - /// io_service::run() function will exit once all other work has completed. + /// Indicate that we have finished with the private io_context. Its + /// io_context::run() function will exit once all other work has completed. work_.reset(); if (work_thread_) work_thread_->join(); @@ -92,7 +92,7 @@ class logger_service void use_file(impl_type& /*impl*/, const std::string& file) { // Pass the work of opening the file to the background thread. - work_io_service_.post(boost::bind( + boost::asio::post(work_io_context_, boost::bind( &logger_service::use_file_impl, this, file)); } @@ -104,13 +104,13 @@ class logger_service os << impl->identifier << ": " << message; // Pass the work of opening the file to the background thread. - work_io_service_.post(boost::bind( + boost::asio::post(work_io_context_, boost::bind( &logger_service::log_impl, this, os.str())); } private: /// Helper function used to open the output file from within the private - /// io_service's thread. + /// io_context's thread. void use_file_impl(const std::string& file) { ofstream_.close(); @@ -118,22 +118,23 @@ class logger_service ofstream_.open(file.c_str()); } - /// Helper function used to log a message from within the private io_service's + /// Helper function used to log a message from within the private io_context's /// thread. void log_impl(const std::string& text) { ofstream_ << text << std::endl; } - /// Private io_service used for performing logging operations. - boost::asio::io_service work_io_service_; + /// Private io_context used for performing logging operations. + boost::asio::io_context work_io_context_; - /// Work for the private io_service to perform. If we do not give the - /// io_service some work to do then the io_service::run() function will exit + /// Work for the private io_context to perform. If we do not give the + /// io_context some work to do then the io_context::run() function will exit /// immediately. - boost::scoped_ptr work_; + boost::asio::executor_work_guard< + boost::asio::io_context::executor_type> work_; - /// Thread used for running the work io_service's run loop. + /// Thread used for running the work io_context's run loop. boost::scoped_ptr work_thread_; /// The file to which log messages will be written. diff --git a/example/cpp03/services/stream_socket_service.hpp b/example/cpp03/services/stream_socket_service.hpp deleted file mode 100644 index 4c976604e1..0000000000 --- a/example/cpp03/services/stream_socket_service.hpp +++ /dev/null @@ -1,351 +0,0 @@ -// -// stream_socket_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2017 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 SERVICES_STREAM_SOCKET_SERVICE_HPP -#define SERVICES_STREAM_SOCKET_SERVICE_HPP - -#include -#include -#include -#include "logger.hpp" - -namespace services { - -/// Debugging stream socket service that wraps the normal stream socket service. -template -class stream_socket_service - : public boost::asio::io_service::service -{ -private: - /// The type of the wrapped stream socket service. - typedef boost::asio::stream_socket_service service_impl_type; - -public: - /// The unique service identifier. - static boost::asio::io_service::id id; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// The implementation type of a stream socket. - typedef typename service_impl_type::implementation_type implementation_type; - - /// The native type of a stream socket. - typedef typename service_impl_type::native_handle_type native_handle_type; - - /// Construct a new stream socket service for the specified io_service. - explicit stream_socket_service(boost::asio::io_service& io_service) - : boost::asio::io_service::service(io_service), - service_impl_(boost::asio::use_service(io_service)), - logger_(io_service, "stream_socket") - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new stream socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a stream socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a new stream socket implementation. - boost::system::error_code open(implementation_type& impl, - const protocol_type& protocol, boost::system::error_code& ec) - { - logger_.log("Opening new socket"); - return service_impl_.open(impl, protocol, ec); - } - - /// Open a stream socket from an existing native socket. - boost::system::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_handle_type& native_socket, - boost::system::error_code& ec) - { - logger_.log("Assigning from a native socket"); - return service_impl_.assign(impl, protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - logger_.log("Checking if socket is open"); - return service_impl_.is_open(impl); - } - - /// Close a stream socket implementation. - boost::system::error_code close(implementation_type& impl, - boost::system::error_code& ec) - { - logger_.log("Closing socket"); - return service_impl_.close(impl, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - boost::system::error_code& ec) const - { - logger_.log("Checking if socket is at out-of-band data mark"); - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - boost::system::error_code& ec) const - { - logger_.log("Determining number of bytes available for reading"); - return service_impl_.available(impl, ec); - } - - /// Bind the stream socket to the specified local endpoint. - boost::system::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, boost::system::error_code& ec) - { - logger_.log("Binding socket"); - return service_impl_.bind(impl, endpoint, ec); - } - - /// Connect the stream socket to the specified endpoint. - boost::system::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, boost::system::error_code& ec) - { - logger_.log("Connecting socket to " + - boost::lexical_cast(peer_endpoint)); - return service_impl_.connect(impl, peer_endpoint, ec); - } - - /// Handler to wrap asynchronous connect completion. - template - class connect_handler - { - public: - connect_handler(Handler h, logger& l) - : handler_(h), - logger_(l) - { - } - - void operator()(const boost::system::error_code& e) - { - if (e) - { - std::string msg = "Asynchronous connect failed: "; - msg += e.message(); - logger_.log(msg); - } - else - { - logger_.log("Asynchronous connect succeeded"); - } - - handler_(e); - } - - private: - Handler handler_; - logger& logger_; - }; - - /// Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler handler) - { - logger_.log("Starting asynchronous connect to " + - boost::lexical_cast(peer_endpoint)); - service_impl_.async_connect(impl, peer_endpoint, - connect_handler(handler, logger_)); - } - - /// Set a socket option. - template - boost::system::error_code set_option(implementation_type& impl, - const Option& option, boost::system::error_code& ec) - { - logger_.log("Setting socket option"); - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template - boost::system::error_code get_option(const implementation_type& impl, - Option& option, boost::system::error_code& ec) const - { - logger_.log("Getting socket option"); - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template - boost::system::error_code io_control(implementation_type& impl, - IO_Control_Command& command, boost::system::error_code& ec) - { - logger_.log("Performing IO control command on socket"); - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - logger_.log("Getting socket's local endpoint"); - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - boost::system::error_code& ec) const - { - logger_.log("Getting socket's remote endpoint"); - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - boost::system::error_code shutdown(implementation_type& impl, - boost::asio::socket_base::shutdown_type what, - boost::system::error_code& ec) - { - logger_.log("Shutting down socket"); - return service_impl_.shutdown(impl, what, ec); - } - - /// Send the given data to the peer. - template - std::size_t send(implementation_type& impl, const Const_Buffers& buffers, - boost::asio::socket_base::message_flags flags, - boost::system::error_code& ec) - { - logger_.log("Sending data on socket"); - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Handler to wrap asynchronous send completion. - template - class send_handler - { - public: - send_handler(Handler h, logger& l) - : handler_(h), - logger_(l) - { - } - - void operator()(const boost::system::error_code& e, - std::size_t bytes_transferred) - { - if (e) - { - std::string msg = "Asynchronous send failed: "; - msg += e.message(); - logger_.log(msg); - } - else - { - logger_.log("Asynchronous send succeeded"); - } - - handler_(e, bytes_transferred); - } - - private: - Handler handler_; - logger& logger_; - }; - - /// Start an asynchronous send. - template - void async_send(implementation_type& impl, const Const_Buffers& buffers, - boost::asio::socket_base::message_flags flags, Handler handler) - { - logger_.log("Starting asynchronous send"); - service_impl_.async_send(impl, buffers, flags, - send_handler(handler, logger_)); - } - - /// Receive some data from the peer. - template - std::size_t receive(implementation_type& impl, - const Mutable_Buffers& buffers, - boost::asio::socket_base::message_flags flags, - boost::system::error_code& ec) - { - logger_.log("Receiving data on socket"); - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Handler to wrap asynchronous receive completion. - template - class receive_handler - { - public: - receive_handler(Handler h, logger& l) - : handler_(h), - logger_(l) - { - } - - void operator()(const boost::system::error_code& e, - std::size_t bytes_transferred) - { - if (e) - { - std::string msg = "Asynchronous receive failed: "; - msg += e.message(); - logger_.log(msg); - } - else - { - logger_.log("Asynchronous receive succeeded"); - } - - handler_(e, bytes_transferred); - } - - private: - Handler handler_; - logger& logger_; - }; - - /// Start an asynchronous receive. - template - void async_receive(implementation_type& impl, const Mutable_Buffers& buffers, - boost::asio::socket_base::message_flags flags, Handler handler) - { - logger_.log("Starting asynchronous receive"); - service_impl_.async_receive(impl, buffers, flags, - receive_handler(handler, logger_)); - } - -private: - /// The wrapped stream socket service. - service_impl_type& service_impl_; - - /// The logger used for writing debug messages. - mutable logger logger_; -}; - -template -boost::asio::io_service::id stream_socket_service::id; - -} // namespace services - -#endif // SERVICES_STREAM_SOCKET_SERVICE_HPP diff --git a/example/cpp03/socks4/sync_client.cpp b/example/cpp03/socks4/sync_client.cpp index d331969f6c..e9106a059c 100644 --- a/example/cpp03/socks4/sync_client.cpp +++ b/example/cpp03/socks4/sync_client.cpp @@ -31,22 +31,21 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; // Get a list of endpoints corresponding to the SOCKS 4 server name. - tcp::resolver resolver(io_service); - tcp::resolver::query socks_query(argv[1], argv[2]); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(socks_query); + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = resolver.resolve(argv[1], argv[2]); // Try each endpoint until we successfully establish a connection to the // SOCKS 4 server. - tcp::socket socket(io_service); - boost::asio::connect(socket, endpoint_iterator); + tcp::socket socket(io_context); + boost::asio::connect(socket, endpoints); // Get an endpoint for the Boost website. This will be passed to the SOCKS // 4 server. Explicitly specify IPv4 since SOCKS 4 does not support IPv6. - tcp::resolver::query http_query(tcp::v4(), "www.boost.org", "http"); - tcp::endpoint http_endpoint = *resolver.resolve(http_query); + tcp::endpoint http_endpoint = + *resolver.resolve(tcp::v4(), "www.boost.org", "http").begin(); // Send the request to the SOCKS 4 server. socks4::request socks_request( diff --git a/example/cpp03/spawn/Jamfile.v2 b/example/cpp03/spawn/Jamfile.v2 index 9a3e7218ec..19b21c5298 100644 --- a/example/cpp03/spawn/Jamfile.v2 +++ b/example/cpp03/spawn/Jamfile.v2 @@ -43,3 +43,21 @@ exe server HPUX:ipv6 HAIKU:network ; + +exe parallel_grep + : parallel_grep.cpp + /boost/context//boost_context + /boost/coroutine//boost_coroutine + /boost/system//boost_system + : BOOST_ALL_NO_LIB=1 + multi + SOLARIS:socket + SOLARIS:nsl + NT:_WIN32_WINNT=0x0501 + NT,gcc:ws2_32 + NT,gcc:mswsock + NT,gcc-cygwin:__USE_W32_SOCKETS + HPUX,gcc:_XOPEN_SOURCE_EXTENDED + HPUX:ipv6 + HAIKU:network + ; diff --git a/example/cpp03/spawn/echo_server.cpp b/example/cpp03/spawn/echo_server.cpp index aa718c441b..db6a1679f5 100644 --- a/example/cpp03/spawn/echo_server.cpp +++ b/example/cpp03/spawn/echo_server.cpp @@ -9,7 +9,7 @@ // #include -#include +#include #include #include #include @@ -23,10 +23,10 @@ using boost::asio::ip::tcp; class session : public boost::enable_shared_from_this { public: - explicit session(boost::asio::io_service& io_service) - : strand_(io_service), - socket_(io_service), - timer_(io_service) + explicit session(boost::asio::io_context& io_context) + : strand_(io_context), + socket_(io_context), + timer_(io_context) { } @@ -76,20 +76,20 @@ class session : public boost::enable_shared_from_this } } - boost::asio::io_service::strand strand_; + boost::asio::io_context::strand strand_; tcp::socket socket_; boost::asio::deadline_timer timer_; }; -void do_accept(boost::asio::io_service& io_service, +void do_accept(boost::asio::io_context& io_context, unsigned short port, boost::asio::yield_context yield) { - tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), port)); + tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port)); for (;;) { boost::system::error_code ec; - boost::shared_ptr new_session(new session(io_service)); + boost::shared_ptr new_session(new session(io_context)); acceptor.async_accept(new_session->socket(), yield[ec]); if (!ec) new_session->go(); } @@ -105,13 +105,13 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - boost::asio::spawn(io_service, + boost::asio::spawn(io_context, boost::bind(do_accept, - boost::ref(io_service), atoi(argv[1]), _1)); + boost::ref(io_context), atoi(argv[1]), _1)); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/spawn/parallel_grep.cpp b/example/cpp03/spawn/parallel_grep.cpp new file mode 100644 index 0000000000..63aa2fc447 --- /dev/null +++ b/example/cpp03/spawn/parallel_grep.cpp @@ -0,0 +1,90 @@ +// +// parallel_grep.cpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 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) +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using boost::asio::dispatch; +using boost::asio::spawn; +using boost::asio::strand; +using boost::asio::thread_pool; +using boost::asio::yield_context; + +void print_match(std::string input_file, std::string line) +{ + std::cout << input_file << ':' << line << std::endl; +} + +void search_file(std::string search_string, std::string input_file, + strand output_strand, yield_context yield) +{ + std::ifstream is(input_file.c_str()); + std::string line; + std::size_t line_num = 0; + while (std::getline(is, line)) + { + // If we find a match, send a message to the output. + if (line.find(search_string) != std::string::npos) + { + dispatch(output_strand, boost::bind(&print_match, input_file, line)); + } + + // Every so often we yield control to another coroutine. + if (++line_num % 10 == 0) + post(yield); + } +} + +int main(int argc, char* argv[]) +{ + try + { + if (argc < 2) + { + std::cerr << "Usage: parallel_grep \n"; + return 1; + } + + // We use a fixed size pool of threads for reading the input files. The + // number of threads is automatically determined based on the number of + // CPUs available in the system. + thread_pool pool; + + // To prevent the output from being garbled, we use a strand to synchronise + // printing. + strand output_strand(pool.get_executor()); + + // Spawn a new coroutine for each file specified on the command line. + std::string search_string = argv[1]; + for (int argn = 2; argn < argc; ++argn) + { + std::string input_file = argv[argn]; + spawn(pool, boost::bind(&search_file, + search_string, input_file, output_strand, _1)); + } + + // Join the thread pool to wait for all the spawned tasks to complete. + pool.join(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/example/cpp03/ssl/client.cpp b/example/cpp03/ssl/client.cpp index 8a86865550..7239496add 100644 --- a/example/cpp03/ssl/client.cpp +++ b/example/cpp03/ssl/client.cpp @@ -19,16 +19,16 @@ enum { max_length = 1024 }; class client { public: - client(boost::asio::io_service& io_service, + client(boost::asio::io_context& io_context, boost::asio::ssl::context& context, - boost::asio::ip::tcp::resolver::iterator endpoint_iterator) - : socket_(io_service, context) + boost::asio::ip::tcp::resolver::results_type endpoints) + : socket_(io_context, context) { socket_.set_verify_mode(boost::asio::ssl::verify_peer); socket_.set_verify_callback( boost::bind(&client::verify_certificate, this, _1, _2)); - boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator, + boost::asio::async_connect(socket_.lowest_layer(), endpoints, boost::bind(&client::handle_connect, this, boost::asio::placeholders::error)); } @@ -134,18 +134,18 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - boost::asio::ip::tcp::resolver resolver(io_service); - boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + boost::asio::ip::tcp::resolver resolver(io_context); + boost::asio::ip::tcp::resolver::results_type endpoints = + resolver.resolve(argv[1], argv[2]); boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); ctx.load_verify_file("ca.pem"); - client c(io_service, ctx, iterator); + client c(io_context, ctx, endpoints); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/ssl/server.cpp b/example/cpp03/ssl/server.cpp index 772b178435..604189034e 100644 --- a/example/cpp03/ssl/server.cpp +++ b/example/cpp03/ssl/server.cpp @@ -19,9 +19,9 @@ typedef boost::asio::ssl::stream ssl_socket; class session { public: - session(boost::asio::io_service& io_service, + session(boost::asio::io_context& io_context, boost::asio::ssl::context& context) - : socket_(io_service, context) + : socket_(io_context, context) { } @@ -92,9 +92,9 @@ class session class server { public: - server(boost::asio::io_service& io_service, unsigned short port) - : io_service_(io_service), - acceptor_(io_service, + server(boost::asio::io_context& io_context, unsigned short port) + : io_context_(io_context), + acceptor_(io_context, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)), context_(boost::asio::ssl::context::sslv23) { @@ -117,7 +117,7 @@ class server void start_accept() { - session* new_session = new session(io_service_, context_); + session* new_session = new session(io_context_, context_); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, boost::asio::placeholders::error)); @@ -139,7 +139,7 @@ class server } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; boost::asio::ip::tcp::acceptor acceptor_; boost::asio::ssl::context context_; }; @@ -154,12 +154,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1])); + server s(io_context, atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/timeouts/async_tcp_client.cpp b/example/cpp03/timeouts/async_tcp_client.cpp index 9d52300ab3..2134e6395d 100644 --- a/example/cpp03/timeouts/async_tcp_client.cpp +++ b/example/cpp03/timeouts/async_tcp_client.cpp @@ -9,7 +9,7 @@ // #include -#include +#include #include #include #include @@ -83,20 +83,21 @@ using boost::asio::ip::tcp; class client { public: - client(boost::asio::io_service& io_service) + client(boost::asio::io_context& io_context) : stopped_(false), - socket_(io_service), - deadline_(io_service), - heartbeat_timer_(io_service) + socket_(io_context), + deadline_(io_context), + heartbeat_timer_(io_context) { } // Called by the user of the client class to initiate the connection process. - // The endpoint iterator will have been obtained using a tcp::resolver. - void start(tcp::resolver::iterator endpoint_iter) + // The endpoints will have been obtained using a tcp::resolver. + void start(tcp::resolver::results_type endpoints) { // Start the connect actor. - start_connect(endpoint_iter); + endpoints_ = endpoints; + start_connect(endpoints_.begin()); // Start the deadline actor. You will note that we're not setting any // particular deadline here. Instead, the connect and input actors will @@ -117,9 +118,9 @@ class client } private: - void start_connect(tcp::resolver::iterator endpoint_iter) + void start_connect(tcp::resolver::results_type::iterator endpoint_iter) { - if (endpoint_iter != tcp::resolver::iterator()) + if (endpoint_iter != endpoints_.end()) { std::cout << "Trying " << endpoint_iter->endpoint() << "...\n"; @@ -139,7 +140,7 @@ class client } void handle_connect(const boost::system::error_code& ec, - tcp::resolver::iterator endpoint_iter) + tcp::resolver::results_type::iterator endpoint_iter) { if (stopped_) return; @@ -273,6 +274,7 @@ class client private: bool stopped_; + tcp::resolver::results_type endpoints_; tcp::socket socket_; boost::asio::streambuf input_buffer_; deadline_timer deadline_; @@ -289,13 +291,13 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; - tcp::resolver r(io_service); - client c(io_service); + boost::asio::io_context io_context; + tcp::resolver r(io_context); + client c(io_context); - c.start(r.resolve(tcp::resolver::query(argv[1], argv[2]))); + c.start(r.resolve(argv[1], argv[2])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/timeouts/blocking_tcp_client.cpp b/example/cpp03/timeouts/blocking_tcp_client.cpp index 765a2a7a71..67224cfd0f 100644 --- a/example/cpp03/timeouts/blocking_tcp_client.cpp +++ b/example/cpp03/timeouts/blocking_tcp_client.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -48,14 +48,14 @@ using boost::lambda::_1; // and any outstanding operations are consequently cancelled. The socket // operations themselves use boost::lambda function objects as completion // handlers. For a given socket operation, the client object runs the -// io_service to block thread execution until the actor completes. +// io_context to block thread execution until the actor completes. // class client { public: client() - : socket_(io_service_), - deadline_(io_service_) + : socket_(io_context_), + deadline_(io_context_) { // No deadline is required until the first socket operation is started. We // set the deadline to positive infinity so that the actor takes no action @@ -70,8 +70,8 @@ class client boost::posix_time::time_duration timeout) { // Resolve the host name and service to a list of endpoints. - tcp::resolver::query query(host, service); - tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query); + tcp::resolver::results_type endpoints = + tcp::resolver(io_context_).resolve(host, service); // Set a deadline for the asynchronous operation. As a host name may // resolve to multiple endpoints, this function uses the composed operation @@ -90,10 +90,10 @@ class client // object is used as a callback and will update the ec variable when the // operation completes. The blocking_udp_client.cpp example shows how you // can use boost::bind rather than boost::lambda. - boost::asio::async_connect(socket_, iter, var(ec) = _1); + boost::asio::async_connect(socket_, endpoints, var(ec) = _1); // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); + do io_context_.run_one(); while (ec == boost::asio::error::would_block); // Determine whether a connection was successfully established. The // deadline actor may have had a chance to run and close our socket, even @@ -126,7 +126,7 @@ class client boost::asio::async_read_until(socket_, input_buffer_, '\n', var(ec) = _1); // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); + do io_context_.run_one(); while (ec == boost::asio::error::would_block); if (ec) throw boost::system::system_error(ec); @@ -161,7 +161,7 @@ class client boost::asio::async_write(socket_, boost::asio::buffer(data), var(ec) = _1); // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); + do io_context_.run_one(); while (ec == boost::asio::error::would_block); if (ec) throw boost::system::system_error(ec); @@ -190,7 +190,7 @@ class client deadline_.async_wait(bind(&client::check_deadline, this)); } - boost::asio::io_service io_service_; + boost::asio::io_context io_context_; tcp::socket socket_; deadline_timer deadline_; boost::asio::streambuf input_buffer_; diff --git a/example/cpp03/timeouts/blocking_udp_client.cpp b/example/cpp03/timeouts/blocking_udp_client.cpp index fd81522cc9..03aafca2f7 100644 --- a/example/cpp03/timeouts/blocking_udp_client.cpp +++ b/example/cpp03/timeouts/blocking_udp_client.cpp @@ -9,7 +9,7 @@ // #include -#include +#include #include #include #include @@ -51,15 +51,15 @@ using boost::asio::ip::udp; // | | // +----------------+ // -// The client object runs the io_service to block thread execution until the +// The client object runs the io_context to block thread execution until the // actor completes. // class client { public: client(const udp::endpoint& listen_endpoint) - : socket_(io_service_, listen_endpoint), - deadline_(io_service_) + : socket_(io_context_, listen_endpoint), + deadline_(io_context_) { // No deadline is required until the first socket operation is started. We // set the deadline to positive infinity so that the actor takes no action @@ -90,7 +90,7 @@ class client boost::bind(&client::handle_receive, _1, _2, &ec, &length)); // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); + do io_context_.run_one(); while (ec == boost::asio::error::would_block); return length; } @@ -129,7 +129,7 @@ class client } private: - boost::asio::io_service io_service_; + boost::asio::io_context io_context_; udp::socket socket_; deadline_timer deadline_; }; @@ -149,7 +149,7 @@ int main(int argc, char* argv[]) } udp::endpoint listen_endpoint( - boost::asio::ip::address::from_string(argv[1]), + boost::asio::ip::make_address(argv[1]), std::atoi(argv[2])); client c(listen_endpoint); diff --git a/example/cpp03/timeouts/server.cpp b/example/cpp03/timeouts/server.cpp index ce4dce60a8..23c276521e 100644 --- a/example/cpp03/timeouts/server.cpp +++ b/example/cpp03/timeouts/server.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -133,12 +133,12 @@ class tcp_session public boost::enable_shared_from_this { public: - tcp_session(boost::asio::io_service& io_service, channel& ch) + tcp_session(boost::asio::io_context& io_context, channel& ch) : channel_(ch), - socket_(io_service), - input_deadline_(io_service), - non_empty_output_queue_(io_service), - output_deadline_(io_service) + socket_(io_context), + input_deadline_(io_context), + non_empty_output_queue_(io_context), + output_deadline_(io_context) { input_deadline_.expires_at(boost::posix_time::pos_infin); output_deadline_.expires_at(boost::posix_time::pos_infin); @@ -334,9 +334,9 @@ class udp_broadcaster : public subscriber { public: - udp_broadcaster(boost::asio::io_service& io_service, + udp_broadcaster(boost::asio::io_context& io_context, const udp::endpoint& broadcast_endpoint) - : socket_(io_service) + : socket_(io_context) { socket_.connect(broadcast_endpoint); } @@ -356,13 +356,13 @@ class udp_broadcaster class server { public: - server(boost::asio::io_service& io_service, + server(boost::asio::io_context& io_context, const tcp::endpoint& listen_endpoint, const udp::endpoint& broadcast_endpoint) - : io_service_(io_service), - acceptor_(io_service, listen_endpoint) + : io_context_(io_context), + acceptor_(io_context, listen_endpoint) { - subscriber_ptr bc(new udp_broadcaster(io_service_, broadcast_endpoint)); + subscriber_ptr bc(new udp_broadcaster(io_context_, broadcast_endpoint)); channel_.join(bc); start_accept(); @@ -370,7 +370,7 @@ class server void start_accept() { - tcp_session_ptr new_session(new tcp_session(io_service_, channel_)); + tcp_session_ptr new_session(new tcp_session(io_context_, channel_)); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, _1)); @@ -388,7 +388,7 @@ class server } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; tcp::acceptor acceptor_; channel channel_; }; @@ -407,16 +407,16 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; tcp::endpoint listen_endpoint(tcp::v4(), atoi(argv[1])); udp::endpoint broadcast_endpoint( - boost::asio::ip::address::from_string(argv[2]), atoi(argv[3])); + boost::asio::ip::make_address(argv[2]), atoi(argv[3])); - server s(io_service, listen_endpoint, broadcast_endpoint); + server s(io_context, listen_endpoint, broadcast_endpoint); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/timers/tick_count_timer.cpp b/example/cpp03/timers/tick_count_timer.cpp index 4f0c85d054..8111a5cacd 100644 --- a/example/cpp03/timers/tick_count_timer.cpp +++ b/example/cpp03/timers/tick_count_timer.cpp @@ -101,9 +101,9 @@ int main() { try { - boost::asio::io_service io_service; + boost::asio::io_context io_context; - tick_count_timer timer(io_service, 5000); + tick_count_timer timer(io_context, 5000); std::cout << "Starting synchronous wait\n"; timer.wait(); std::cout << "Finished synchronous wait\n"; @@ -111,7 +111,7 @@ int main() timer.expires_from_now(5000); std::cout << "Starting asynchronous wait\n"; timer.async_wait(&handle_timeout); - io_service.run(); + io_context.run(); std::cout << "Finished asynchronous wait\n"; } catch (std::exception& e) diff --git a/example/cpp03/timers/time_t_timer.cpp b/example/cpp03/timers/time_t_timer.cpp index 19e84e35a4..95b443eccd 100644 --- a/example/cpp03/timers/time_t_timer.cpp +++ b/example/cpp03/timers/time_t_timer.cpp @@ -69,9 +69,9 @@ int main() { try { - boost::asio::io_service io_service; + boost::asio::io_context io_context; - time_t_timer timer(io_service); + time_t_timer timer(io_context); timer.expires_from_now(5); std::cout << "Starting synchronous wait\n"; @@ -81,7 +81,7 @@ int main() timer.expires_from_now(5); std::cout << "Starting asynchronous wait\n"; timer.async_wait(&handle_timeout); - io_service.run(); + io_context.run(); std::cout << "Finished asynchronous wait\n"; } catch (std::exception& e) diff --git a/example/cpp03/tutorial/daytime1/client.cpp b/example/cpp03/tutorial/daytime1/client.cpp index 2e00a5a773..d311365df7 100644 --- a/example/cpp03/tutorial/daytime1/client.cpp +++ b/example/cpp03/tutorial/daytime1/client.cpp @@ -24,14 +24,14 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - tcp::resolver resolver(io_service); - tcp::resolver::query query(argv[1], "daytime"); - tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + tcp::resolver resolver(io_context); + tcp::resolver::results_type endpoints = + resolver.resolve(argv[1], "daytime"); - tcp::socket socket(io_service); - boost::asio::connect(socket, endpoint_iterator); + tcp::socket socket(io_context); + boost::asio::connect(socket, endpoints); for (;;) { diff --git a/example/cpp03/tutorial/daytime2/server.cpp b/example/cpp03/tutorial/daytime2/server.cpp index 1e70b684b5..d6fa140f23 100644 --- a/example/cpp03/tutorial/daytime2/server.cpp +++ b/example/cpp03/tutorial/daytime2/server.cpp @@ -26,13 +26,13 @@ int main() { try { - boost::asio::io_service io_service; + boost::asio::io_context io_context; - tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13)); + tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 13)); for (;;) { - tcp::socket socket(io_service); + tcp::socket socket(io_context); acceptor.accept(socket); std::string message = make_daytime_string(); diff --git a/example/cpp03/tutorial/daytime3/server.cpp b/example/cpp03/tutorial/daytime3/server.cpp index ede7d9d024..196ba6ab2f 100644 --- a/example/cpp03/tutorial/daytime3/server.cpp +++ b/example/cpp03/tutorial/daytime3/server.cpp @@ -31,9 +31,9 @@ class tcp_connection public: typedef boost::shared_ptr pointer; - static pointer create(boost::asio::io_service& io_service) + static pointer create(boost::asio::io_context& io_context) { - return pointer(new tcp_connection(io_service)); + return pointer(new tcp_connection(io_context)); } tcp::socket& socket() @@ -52,8 +52,8 @@ class tcp_connection } private: - tcp_connection(boost::asio::io_service& io_service) - : socket_(io_service) + tcp_connection(boost::asio::io_context& io_context) + : socket_(io_context) { } @@ -69,8 +69,8 @@ class tcp_connection class tcp_server { public: - tcp_server(boost::asio::io_service& io_service) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13)) + tcp_server(boost::asio::io_context& io_context) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) { start_accept(); } @@ -79,7 +79,7 @@ class tcp_server void start_accept() { tcp_connection::pointer new_connection = - tcp_connection::create(acceptor_.get_io_service()); + tcp_connection::create(acceptor_.get_executor().context()); acceptor_.async_accept(new_connection->socket(), boost::bind(&tcp_server::handle_accept, this, new_connection, @@ -104,9 +104,9 @@ int main() { try { - boost::asio::io_service io_service; - tcp_server server(io_service); - io_service.run(); + boost::asio::io_context io_context; + tcp_server server(io_context); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/tutorial/daytime4/client.cpp b/example/cpp03/tutorial/daytime4/client.cpp index a6a001db43..1432ff1eea 100644 --- a/example/cpp03/tutorial/daytime4/client.cpp +++ b/example/cpp03/tutorial/daytime4/client.cpp @@ -24,13 +24,13 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - udp::resolver resolver(io_service); - udp::resolver::query query(udp::v4(), argv[1], "daytime"); - udp::endpoint receiver_endpoint = *resolver.resolve(query); + udp::resolver resolver(io_context); + udp::endpoint receiver_endpoint = + *resolver.resolve(udp::v4(), argv[1], "daytime").begin(); - udp::socket socket(io_service); + udp::socket socket(io_context); socket.open(udp::v4()); boost::array send_buf = {{ 0 }}; diff --git a/example/cpp03/tutorial/daytime5/server.cpp b/example/cpp03/tutorial/daytime5/server.cpp index 8890a36e28..7299587879 100644 --- a/example/cpp03/tutorial/daytime5/server.cpp +++ b/example/cpp03/tutorial/daytime5/server.cpp @@ -27,9 +27,9 @@ int main() { try { - boost::asio::io_service io_service; + boost::asio::io_context io_context; - udp::socket socket(io_service, udp::endpoint(udp::v4(), 13)); + udp::socket socket(io_context, udp::endpoint(udp::v4(), 13)); for (;;) { diff --git a/example/cpp03/tutorial/daytime6/server.cpp b/example/cpp03/tutorial/daytime6/server.cpp index dad2cb01af..09f9c0505c 100644 --- a/example/cpp03/tutorial/daytime6/server.cpp +++ b/example/cpp03/tutorial/daytime6/server.cpp @@ -28,8 +28,8 @@ std::string make_daytime_string() class udp_server { public: - udp_server(boost::asio::io_service& io_service) - : socket_(io_service, udp::endpoint(udp::v4(), 13)) + udp_server(boost::asio::io_context& io_context) + : socket_(io_context, udp::endpoint(udp::v4(), 13)) { start_receive(); } @@ -76,9 +76,9 @@ int main() { try { - boost::asio::io_service io_service; - udp_server server(io_service); - io_service.run(); + boost::asio::io_context io_context; + udp_server server(io_context); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/tutorial/daytime7/server.cpp b/example/cpp03/tutorial/daytime7/server.cpp index b8a0273a78..c83e74e4ad 100644 --- a/example/cpp03/tutorial/daytime7/server.cpp +++ b/example/cpp03/tutorial/daytime7/server.cpp @@ -33,9 +33,9 @@ class tcp_connection public: typedef boost::shared_ptr pointer; - static pointer create(boost::asio::io_service& io_service) + static pointer create(boost::asio::io_context& io_context) { - return pointer(new tcp_connection(io_service)); + return pointer(new tcp_connection(io_context)); } tcp::socket& socket() @@ -52,8 +52,8 @@ class tcp_connection } private: - tcp_connection(boost::asio::io_service& io_service) - : socket_(io_service) + tcp_connection(boost::asio::io_context& io_context) + : socket_(io_context) { } @@ -68,8 +68,8 @@ class tcp_connection class tcp_server { public: - tcp_server(boost::asio::io_service& io_service) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13)) + tcp_server(boost::asio::io_context& io_context) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) { start_accept(); } @@ -78,7 +78,7 @@ class tcp_server void start_accept() { tcp_connection::pointer new_connection = - tcp_connection::create(acceptor_.get_io_service()); + tcp_connection::create(acceptor_.get_executor().context()); acceptor_.async_accept(new_connection->socket(), boost::bind(&tcp_server::handle_accept, this, new_connection, @@ -102,8 +102,8 @@ class tcp_server class udp_server { public: - udp_server(boost::asio::io_service& io_service) - : socket_(io_service, udp::endpoint(udp::v4(), 13)) + udp_server(boost::asio::io_context& io_context) + : socket_(io_context, udp::endpoint(udp::v4(), 13)) { start_receive(); } @@ -144,10 +144,10 @@ int main() { try { - boost::asio::io_service io_service; - tcp_server server1(io_service); - udp_server server2(io_service); - io_service.run(); + boost::asio::io_context io_context; + tcp_server server1(io_context); + udp_server server2(io_context); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp03/tutorial/timer1/timer.cpp b/example/cpp03/tutorial/timer1/timer.cpp index 982db427d2..a2ef07a989 100644 --- a/example/cpp03/tutorial/timer1/timer.cpp +++ b/example/cpp03/tutorial/timer1/timer.cpp @@ -14,7 +14,7 @@ int main() { - boost::asio::io_service io; + boost::asio::io_context io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); t.wait(); diff --git a/example/cpp03/tutorial/timer2/timer.cpp b/example/cpp03/tutorial/timer2/timer.cpp index f88b774981..6a595975a3 100644 --- a/example/cpp03/tutorial/timer2/timer.cpp +++ b/example/cpp03/tutorial/timer2/timer.cpp @@ -19,7 +19,7 @@ void print(const boost::system::error_code& /*e*/) int main() { - boost::asio::io_service io; + boost::asio::io_context io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); t.async_wait(&print); diff --git a/example/cpp03/tutorial/timer3/timer.cpp b/example/cpp03/tutorial/timer3/timer.cpp index 813f377a30..ab957c474f 100644 --- a/example/cpp03/tutorial/timer3/timer.cpp +++ b/example/cpp03/tutorial/timer3/timer.cpp @@ -29,7 +29,7 @@ void print(const boost::system::error_code& /*e*/, int main() { - boost::asio::io_service io; + boost::asio::io_context io; int count = 0; boost::asio::deadline_timer t(io, boost::posix_time::seconds(1)); diff --git a/example/cpp03/tutorial/timer4/timer.cpp b/example/cpp03/tutorial/timer4/timer.cpp index 41d0d922e4..7af2cc869a 100644 --- a/example/cpp03/tutorial/timer4/timer.cpp +++ b/example/cpp03/tutorial/timer4/timer.cpp @@ -16,7 +16,7 @@ class printer { public: - printer(boost::asio::io_service& io) + printer(boost::asio::io_context& io) : timer_(io, boost::posix_time::seconds(1)), count_(0) { @@ -47,7 +47,7 @@ class printer int main() { - boost::asio::io_service io; + boost::asio::io_context io; printer p(io); io.run(); diff --git a/example/cpp03/tutorial/timer5/timer.cpp b/example/cpp03/tutorial/timer5/timer.cpp index 0e5752948e..9695670b55 100644 --- a/example/cpp03/tutorial/timer5/timer.cpp +++ b/example/cpp03/tutorial/timer5/timer.cpp @@ -17,14 +17,17 @@ class printer { public: - printer(boost::asio::io_service& io) + printer(boost::asio::io_context& io) : strand_(io), timer1_(io, boost::posix_time::seconds(1)), timer2_(io, boost::posix_time::seconds(1)), count_(0) { - timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this))); - timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this))); + timer1_.async_wait(boost::asio::bind_executor(strand_, + boost::bind(&printer::print1, this))); + + timer2_.async_wait(boost::asio::bind_executor(strand_, + boost::bind(&printer::print2, this))); } ~printer() @@ -40,7 +43,9 @@ class printer ++count_; timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1)); - timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this))); + + timer1_.async_wait(boost::asio::bind_executor(strand_, + boost::bind(&printer::print1, this))); } } @@ -52,12 +57,14 @@ class printer ++count_; timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1)); - timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this))); + + timer2_.async_wait(boost::asio::bind_executor(strand_, + boost::bind(&printer::print2, this))); } } private: - boost::asio::io_service::strand strand_; + boost::asio::io_context::strand strand_; boost::asio::deadline_timer timer1_; boost::asio::deadline_timer timer2_; int count_; @@ -65,9 +72,9 @@ class printer int main() { - boost::asio::io_service io; + boost::asio::io_context io; printer p(io); - boost::thread t(boost::bind(&boost::asio::io_service::run, &io)); + boost::thread t(boost::bind(&boost::asio::io_context::run, &io)); io.run(); t.join(); diff --git a/example/cpp03/tutorial/timer_dox.txt b/example/cpp03/tutorial/timer_dox.txt index 83a3285232..32e29982e5 100644 --- a/example/cpp03/tutorial/timer_dox.txt +++ b/example/cpp03/tutorial/timer_dox.txt @@ -292,8 +292,8 @@ Return to \ref tuttimer4 /** \page tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs -This tutorial demonstrates the use of the boost::asio::strand class to synchronise -callback handlers in a multithreaded program. +This tutorial demonstrates the use of the boost::asio::io_service::strand class to +synchronise callback handlers in a multithreaded program. The previous four tutorials avoided the issue of handler synchronisation by calling the boost::asio::io_service::run() function from one thread only. As you @@ -329,22 +329,25 @@ tutorial by running two timers in parallel. In addition to initialising a pair of boost::asio::deadline_timer members, the constructor initialises the strand_ member, an object of type -boost::asio::strand. +boost::asio::io_service::strand. -An boost::asio::strand guarantees that, for those handlers that are dispatched through -it, an executing handler will be allowed to complete before the next one is -started. This is guaranteed irrespective of the number of threads that are -calling boost::asio::io_service::run(). Of course, the handlers may still execute -concurrently with other handlers that were not dispatched through an -boost::asio::strand, or were dispatched through a different boost::asio::strand object. +An boost::asio::io_service::strand is an executor that guarantees that, for those +handlers that are dispatched through it, an executing handler will be allowed +to complete before the next one is started. This is guaranteed irrespective of +the number of threads that are calling boost::asio::io_service::run(). Of course, the +handlers may still execute concurrently with other handlers that were +not dispatched through an boost::asio::io_service::strand, or were dispatched +through a different boost::asio::io_service::strand object. \until { -When initiating the asynchronous operations, each callback handler is "wrapped" -using the boost::asio::strand object. The boost::asio::strand::wrap() function returns a new -handler that automatically dispatches its contained handler through the -boost::asio::strand object. By wrapping the handlers using the same boost::asio::strand, we -are ensuring that they cannot execute concurrently. +When initiating the asynchronous operations, each callback handler is "bound" +to an boost::asio::io_service::strand object. The +boost::asio::io_service::strand::bind_executor() function returns a new handler that +automatically dispatches its contained handler through the +boost::asio::io_service::strand object. By binding the handlers to the same +boost::asio::io_service::strand, we are ensuring that they cannot execute +concurrently. \until } \until } diff --git a/example/cpp03/windows/transmit_file.cpp b/example/cpp03/windows/transmit_file.cpp index 2be12c6992..38ff8a9d60 100644 --- a/example/cpp03/windows/transmit_file.cpp +++ b/example/cpp03/windows/transmit_file.cpp @@ -28,7 +28,7 @@ void transmit_file(tcp::socket& socket, random_access_handle& file, Handler handler) { // Construct an OVERLAPPED-derived object to contain the handler. - overlapped_ptr overlapped(socket.get_io_service(), handler); + overlapped_ptr overlapped(socket.get_executor().context(), handler); // Initiate the TransmitFile operation. BOOL ok = ::TransmitFile(socket.native_handle(), @@ -40,7 +40,7 @@ void transmit_file(tcp::socket& socket, { // The operation completed immediately, so a completion notification needs // to be posted. When complete() is called, ownership of the OVERLAPPED- - // derived object passes to the io_service. + // derived object passes to the io_context. boost::system::error_code ec(last_error, boost::asio::error::get_system_category()); overlapped.complete(ec, 0); @@ -48,7 +48,7 @@ void transmit_file(tcp::socket& socket, else { // The operation was successfully initiated, so ownership of the - // OVERLAPPED-derived object has passed to the io_service. + // OVERLAPPED-derived object has passed to the io_context. overlapped.release(); } } @@ -59,10 +59,10 @@ class connection public: typedef boost::shared_ptr pointer; - static pointer create(boost::asio::io_service& io_service, + static pointer create(boost::asio::io_context& io_context, const std::string& filename) { - return pointer(new connection(io_service, filename)); + return pointer(new connection(io_context, filename)); } tcp::socket& socket() @@ -85,10 +85,10 @@ class connection } private: - connection(boost::asio::io_service& io_service, const std::string& filename) - : socket_(io_service), + connection(boost::asio::io_context& io_context, const std::string& filename) + : socket_(io_context), filename_(filename), - file_(io_service) + file_(io_context) { } @@ -107,9 +107,9 @@ class connection class server { public: - server(boost::asio::io_service& io_service, + server(boost::asio::io_context& io_context, unsigned short port, const std::string& filename) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), filename_(filename) { start_accept(); @@ -119,7 +119,7 @@ class server void start_accept() { connection::pointer new_connection = - connection::create(acceptor_.get_io_service(), filename_); + connection::create(acceptor_.get_executor().context(), filename_); acceptor_.async_accept(new_connection->socket(), boost::bind(&server::handle_accept, this, new_connection, @@ -151,12 +151,12 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; using namespace std; // For atoi. - server s(io_service, atoi(argv[1]), argv[2]); + server s(io_context, atoi(argv[1]), argv[2]); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp11/allocation/server.cpp b/example/cpp11/allocation/server.cpp index c41eb8fdc9..c363a3d871 100644 --- a/example/cpp11/allocation/server.cpp +++ b/example/cpp11/allocation/server.cpp @@ -166,9 +166,8 @@ class session class server { public: - server(boost::asio::io_service& io_service, short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) + server(boost::asio::io_context& io_context, short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { do_accept(); } @@ -176,12 +175,12 @@ class server private: void do_accept() { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) + acceptor_.async_accept( + [this](boost::system::error_code ec, tcp::socket socket) { if (!ec) { - std::make_shared(std::move(socket_))->start(); + std::make_shared(std::move(socket))->start(); } do_accept(); @@ -189,7 +188,6 @@ class server } tcp::acceptor acceptor_; - tcp::socket socket_; }; int main(int argc, char* argv[]) @@ -202,9 +200,9 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; - server s(io_service, std::atoi(argv[1])); - io_service.run(); + boost::asio::io_context io_context; + server s(io_context, std::atoi(argv[1])); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp11/buffers/reference_counted.cpp b/example/cpp11/buffers/reference_counted.cpp index b83b1cfa39..462d5f04e1 100644 --- a/example/cpp11/buffers/reference_counted.cpp +++ b/example/cpp11/buffers/reference_counted.cpp @@ -72,9 +72,8 @@ class session class server { public: - server(boost::asio::io_service& io_service, short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) + server(boost::asio::io_context& io_context, short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { do_accept(); } @@ -82,12 +81,12 @@ class server private: void do_accept() { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) + acceptor_.async_accept( + [this](boost::system::error_code ec, tcp::socket socket) { if (!ec) { - std::make_shared(std::move(socket_))->start(); + std::make_shared(std::move(socket))->start(); } do_accept(); @@ -95,7 +94,6 @@ class server } tcp::acceptor acceptor_; - tcp::socket socket_; }; int main(int argc, char* argv[]) @@ -108,11 +106,11 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - server s(io_service, std::atoi(argv[1])); + server s(io_context, std::atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp11/chat/chat_client.cpp b/example/cpp11/chat/chat_client.cpp index a41df5c1ee..a422e0f9f8 100644 --- a/example/cpp11/chat/chat_client.cpp +++ b/example/cpp11/chat/chat_client.cpp @@ -22,17 +22,17 @@ typedef std::deque chat_message_queue; class chat_client { public: - chat_client(boost::asio::io_service& io_service, - tcp::resolver::iterator endpoint_iterator) - : io_service_(io_service), - socket_(io_service) + chat_client(boost::asio::io_context& io_context, + const tcp::resolver::results_type& endpoints) + : io_context_(io_context), + socket_(io_context) { - do_connect(endpoint_iterator); + do_connect(endpoints); } void write(const chat_message& msg) { - io_service_.post( + boost::asio::post(io_context_, [this, msg]() { bool write_in_progress = !write_msgs_.empty(); @@ -46,14 +46,14 @@ class chat_client void close() { - io_service_.post([this]() { socket_.close(); }); + boost::asio::post(io_context_, [this]() { socket_.close(); }); } private: - void do_connect(tcp::resolver::iterator endpoint_iterator) + void do_connect(const tcp::resolver::results_type& endpoints) { - boost::asio::async_connect(socket_, endpoint_iterator, - [this](boost::system::error_code ec, tcp::resolver::iterator) + boost::asio::async_connect(socket_, endpoints, + [this](boost::system::error_code ec, tcp::endpoint) { if (!ec) { @@ -121,7 +121,7 @@ class chat_client } private: - boost::asio::io_service& io_service_; + boost::asio::io_context& io_context_; tcp::socket socket_; chat_message read_msg_; chat_message_queue write_msgs_; @@ -137,13 +137,13 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - tcp::resolver resolver(io_service); - auto endpoint_iterator = resolver.resolve({ argv[1], argv[2] }); - chat_client c(io_service, endpoint_iterator); + tcp::resolver resolver(io_context); + auto endpoints = resolver.resolve(argv[1], argv[2]); + chat_client c(io_context, endpoints); - std::thread t([&io_service](){ io_service.run(); }); + std::thread t([&io_context](){ io_context.run(); }); char line[chat_message::max_body_length + 1]; while (std::cin.getline(line, chat_message::max_body_length + 1)) diff --git a/example/cpp11/chat/chat_server.cpp b/example/cpp11/chat/chat_server.cpp index 7f5dc4652b..4db62b4ba3 100644 --- a/example/cpp11/chat/chat_server.cpp +++ b/example/cpp11/chat/chat_server.cpp @@ -169,10 +169,9 @@ class chat_session class chat_server { public: - chat_server(boost::asio::io_service& io_service, + chat_server(boost::asio::io_context& io_context, const tcp::endpoint& endpoint) - : acceptor_(io_service, endpoint), - socket_(io_service) + : acceptor_(io_context, endpoint) { do_accept(); } @@ -180,12 +179,12 @@ class chat_server private: void do_accept() { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) + acceptor_.async_accept( + [this](boost::system::error_code ec, tcp::socket socket) { if (!ec) { - std::make_shared(std::move(socket_), room_)->start(); + std::make_shared(std::move(socket), room_)->start(); } do_accept(); @@ -193,7 +192,6 @@ class chat_server } tcp::acceptor acceptor_; - tcp::socket socket_; chat_room room_; }; @@ -209,16 +207,16 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; std::list servers; for (int i = 1; i < argc; ++i) { tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[i])); - servers.emplace_back(io_service, endpoint); + servers.emplace_back(io_context, endpoint); } - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp11/echo/async_tcp_echo_server.cpp b/example/cpp11/echo/async_tcp_echo_server.cpp index ad1a060f9c..14a3810a63 100644 --- a/example/cpp11/echo/async_tcp_echo_server.cpp +++ b/example/cpp11/echo/async_tcp_echo_server.cpp @@ -65,9 +65,8 @@ class session class server { public: - server(boost::asio::io_service& io_service, short port) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), - socket_(io_service) + server(boost::asio::io_context& io_context, short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { do_accept(); } @@ -75,12 +74,12 @@ class server private: void do_accept() { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) + acceptor_.async_accept( + [this](boost::system::error_code ec, tcp::socket socket) { if (!ec) { - std::make_shared(std::move(socket_))->start(); + std::make_shared(std::move(socket))->start(); } do_accept(); @@ -88,7 +87,6 @@ class server } tcp::acceptor acceptor_; - tcp::socket socket_; }; int main(int argc, char* argv[]) @@ -101,11 +99,11 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - server s(io_service, std::atoi(argv[1])); + server s(io_context, std::atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp11/echo/async_udp_echo_server.cpp b/example/cpp11/echo/async_udp_echo_server.cpp index 4c1da78752..3e0ab89586 100644 --- a/example/cpp11/echo/async_udp_echo_server.cpp +++ b/example/cpp11/echo/async_udp_echo_server.cpp @@ -17,8 +17,8 @@ using boost::asio::ip::udp; class server { public: - server(boost::asio::io_service& io_service, short port) - : socket_(io_service, udp::endpoint(udp::v4(), port)) + server(boost::asio::io_context& io_context, short port) + : socket_(io_context, udp::endpoint(udp::v4(), port)) { do_receive(); } @@ -67,11 +67,11 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - server s(io_service, std::atoi(argv[1])); + server s(io_context, std::atoi(argv[1])); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp11/echo/blocking_tcp_echo_client.cpp b/example/cpp11/echo/blocking_tcp_echo_client.cpp index c6ed7f6f81..557b14e41d 100644 --- a/example/cpp11/echo/blocking_tcp_echo_client.cpp +++ b/example/cpp11/echo/blocking_tcp_echo_client.cpp @@ -27,11 +27,11 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - tcp::socket s(io_service); - tcp::resolver resolver(io_service); - boost::asio::connect(s, resolver.resolve({argv[1], argv[2]})); + tcp::socket s(io_context); + tcp::resolver resolver(io_context); + boost::asio::connect(s, resolver.resolve(argv[1], argv[2])); std::cout << "Enter message: "; char request[max_length]; diff --git a/example/cpp11/echo/blocking_tcp_echo_server.cpp b/example/cpp11/echo/blocking_tcp_echo_server.cpp index b69f3ef4f4..44c69c0dae 100644 --- a/example/cpp11/echo/blocking_tcp_echo_server.cpp +++ b/example/cpp11/echo/blocking_tcp_echo_server.cpp @@ -42,14 +42,12 @@ void session(tcp::socket sock) } } -void server(boost::asio::io_service& io_service, unsigned short port) +void server(boost::asio::io_context& io_context, unsigned short port) { - tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port)); + tcp::acceptor a(io_context, tcp::endpoint(tcp::v4(), port)); for (;;) { - tcp::socket sock(io_service); - a.accept(sock); - std::thread(session, std::move(sock)).detach(); + std::thread(session, a.accept()).detach(); } } @@ -63,9 +61,9 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - server(io_service, std::atoi(argv[1])); + server(io_context, std::atoi(argv[1])); } catch (std::exception& e) { diff --git a/example/cpp11/echo/blocking_udp_echo_client.cpp b/example/cpp11/echo/blocking_udp_echo_client.cpp index 4e8215a1e0..8be33a0688 100644 --- a/example/cpp11/echo/blocking_udp_echo_client.cpp +++ b/example/cpp11/echo/blocking_udp_echo_client.cpp @@ -27,18 +27,19 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - udp::socket s(io_service, udp::endpoint(udp::v4(), 0)); + udp::socket s(io_context, udp::endpoint(udp::v4(), 0)); - udp::resolver resolver(io_service); - udp::endpoint endpoint = *resolver.resolve({udp::v4(), argv[1], argv[2]}); + udp::resolver resolver(io_context); + udp::resolver::results_type endpoints = + resolver.resolve(udp::v4(), argv[1], argv[2]); std::cout << "Enter message: "; char request[max_length]; std::cin.getline(request, max_length); size_t request_length = std::strlen(request); - s.send_to(boost::asio::buffer(request, request_length), endpoint); + s.send_to(boost::asio::buffer(request, request_length), *endpoints.begin()); char reply[max_length]; udp::endpoint sender_endpoint; diff --git a/example/cpp11/echo/blocking_udp_echo_server.cpp b/example/cpp11/echo/blocking_udp_echo_server.cpp index 970f5fe579..6626d74d82 100644 --- a/example/cpp11/echo/blocking_udp_echo_server.cpp +++ b/example/cpp11/echo/blocking_udp_echo_server.cpp @@ -16,9 +16,9 @@ using boost::asio::ip::udp; enum { max_length = 1024 }; -void server(boost::asio::io_service& io_service, unsigned short port) +void server(boost::asio::io_context& io_context, unsigned short port) { - udp::socket sock(io_service, udp::endpoint(udp::v4(), port)); + udp::socket sock(io_context, udp::endpoint(udp::v4(), port)); for (;;) { char data[max_length]; @@ -39,9 +39,9 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - server(io_service, std::atoi(argv[1])); + server(io_context, std::atoi(argv[1])); } catch (std::exception& e) { diff --git a/example/cpp11/futures/daytime_client.cpp b/example/cpp11/futures/daytime_client.cpp index 34f9ff22a9..2ec8a67290 100644 --- a/example/cpp11/futures/daytime_client.cpp +++ b/example/cpp11/futures/daytime_client.cpp @@ -12,32 +12,32 @@ #include #include #include -#include +#include #include #include using boost::asio::ip::udp; -void get_daytime(boost::asio::io_service& io_service, const char* hostname) +void get_daytime(boost::asio::io_context& io_context, const char* hostname) { try { - udp::resolver resolver(io_service); + udp::resolver resolver(io_context); - std::future iter = + std::future endpoints = resolver.async_resolve( - {udp::v4(), hostname, "daytime"}, + udp::v4(), hostname, "daytime", boost::asio::use_future); - // The async_resolve operation above returns the endpoint iterator as a - // future value that is not retrieved ... + // The async_resolve operation above returns the endpoints as a future + // value that is not retrieved ... - udp::socket socket(io_service, udp::v4()); + udp::socket socket(io_context, udp::v4()); std::array send_buf = {{ 0 }}; std::future send_length = socket.async_send_to(boost::asio::buffer(send_buf), - *iter.get(), // ... until here. This call may block. + *endpoints.get().begin(), // ... until here. This call may block. boost::asio::use_future); // Do other things here while the send completes. @@ -74,15 +74,15 @@ int main(int argc, char* argv[]) return 1; } - // We run the io_service off in its own thread so that it operates + // We run the io_context off in its own thread so that it operates // completely asynchronously with respect to the rest of the program. - boost::asio::io_service io_service; - boost::asio::io_service::work work(io_service); - std::thread thread([&io_service](){ io_service.run(); }); + boost::asio::io_context io_context; + auto work = boost::asio::make_work_guard(io_context); + std::thread thread([&io_context](){ io_context.run(); }); - get_daytime(io_service, argv[1]); + get_daytime(io_context, argv[1]); - io_service.stop(); + io_context.stop(); thread.join(); } catch (std::exception& e) diff --git a/example/cpp11/http/server/server.cpp b/example/cpp11/http/server/server.cpp index 4f761d9212..df453b8ed2 100644 --- a/example/cpp11/http/server/server.cpp +++ b/example/cpp11/http/server/server.cpp @@ -17,11 +17,10 @@ namespace server { server::server(const std::string& address, const std::string& port, const std::string& doc_root) - : io_service_(), - signals_(io_service_), - acceptor_(io_service_), + : io_context_(1), + signals_(io_context_), + acceptor_(io_context_), connection_manager_(), - socket_(io_service_), request_handler_(doc_root) { // Register to handle the signals that indicate when the server should exit. @@ -36,8 +35,9 @@ server::server(const std::string& address, const std::string& port, do_await_stop(); // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve({address, port}); + boost::asio::ip::tcp::resolver resolver(io_context_); + boost::asio::ip::tcp::endpoint endpoint = + *resolver.resolve(address, port).begin(); acceptor_.open(endpoint.protocol()); acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.bind(endpoint); @@ -48,17 +48,17 @@ server::server(const std::string& address, const std::string& port, void server::run() { - // The io_service::run() call will block until all asynchronous operations + // The io_context::run() call will block until all asynchronous operations // have finished. While the server is running, there is always at least one // asynchronous operation outstanding: the asynchronous accept call waiting // for new incoming connections. - io_service_.run(); + io_context_.run(); } void server::do_accept() { - acceptor_.async_accept(socket_, - [this](boost::system::error_code ec) + acceptor_.async_accept( + [this](boost::system::error_code ec, boost::asio::ip::tcp::socket socket) { // Check whether the server was stopped by a signal before this // completion handler had a chance to run. @@ -70,7 +70,7 @@ void server::do_accept() if (!ec) { connection_manager_.start(std::make_shared( - std::move(socket_), connection_manager_, request_handler_)); + std::move(socket), connection_manager_, request_handler_)); } do_accept(); @@ -83,7 +83,7 @@ void server::do_await_stop() [this](boost::system::error_code /*ec*/, int /*signo*/) { // The server is stopped by cancelling all outstanding asynchronous - // operations. Once all operations have finished the io_service::run() + // operations. Once all operations have finished the io_context::run() // call will exit. acceptor_.close(); connection_manager_.stop_all(); diff --git a/example/cpp11/http/server/server.hpp b/example/cpp11/http/server/server.hpp index 50d9882382..7b8aee0c5d 100644 --- a/example/cpp11/http/server/server.hpp +++ b/example/cpp11/http/server/server.hpp @@ -32,7 +32,7 @@ class server explicit server(const std::string& address, const std::string& port, const std::string& doc_root); - /// Run the server's io_service loop. + /// Run the server's io_context loop. void run(); private: @@ -42,8 +42,8 @@ class server /// Wait for a request to stop the server. void do_await_stop(); - /// The io_service used to perform asynchronous operations. - boost::asio::io_service io_service_; + /// The io_context used to perform asynchronous operations. + boost::asio::io_context io_context_; /// The signal_set is used to register for process termination notifications. boost::asio::signal_set signals_; @@ -54,9 +54,6 @@ class server /// The connection manager which owns all live connections. connection_manager connection_manager_; - /// The next socket to be accepted. - boost::asio::ip::tcp::socket socket_; - /// The handler for all incoming requests. request_handler request_handler_; }; diff --git a/example/cpp11/spawn/echo_server.cpp b/example/cpp11/spawn/echo_server.cpp index ac18373d54..350304e63e 100644 --- a/example/cpp11/spawn/echo_server.cpp +++ b/example/cpp11/spawn/echo_server.cpp @@ -8,7 +8,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include +#include #include #include #include @@ -23,8 +23,8 @@ class session : public std::enable_shared_from_this public: explicit session(tcp::socket socket) : socket_(std::move(socket)), - timer_(socket_.get_io_service()), - strand_(socket_.get_io_service()) + timer_(socket_.get_io_context()), + strand_(socket_.get_io_context()) { } @@ -67,7 +67,7 @@ class session : public std::enable_shared_from_this private: tcp::socket socket_; boost::asio::steady_timer timer_; - boost::asio::io_service::strand strand_; + boost::asio::io_context::strand strand_; }; int main(int argc, char* argv[]) @@ -80,24 +80,24 @@ int main(int argc, char* argv[]) return 1; } - boost::asio::io_service io_service; + boost::asio::io_context io_context; - boost::asio::spawn(io_service, + boost::asio::spawn(io_context, [&](boost::asio::yield_context yield) { - tcp::acceptor acceptor(io_service, + tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), std::atoi(argv[1]))); for (;;) { boost::system::error_code ec; - tcp::socket socket(io_service); + tcp::socket socket(io_context); acceptor.async_accept(socket, yield[ec]); if (!ec) std::make_shared(std::move(socket))->go(); } }); - io_service.run(); + io_context.run(); } catch (std::exception& e) { diff --git a/example/cpp11/spawn/parallel_grep.cpp b/example/cpp11/spawn/parallel_grep.cpp new file mode 100644 index 0000000000..7beb114618 --- /dev/null +++ b/example/cpp11/spawn/parallel_grep.cpp @@ -0,0 +1,84 @@ +// +// parallel_grep.cpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 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) +// + +#include +#include +#include +#include +#include +#include +#include +#include + +using boost::asio::dispatch; +using boost::asio::spawn; +using boost::asio::strand; +using boost::thread_pool; +using boost::asio::yield_context; + +int main(int argc, char* argv[]) +{ + try + { + if (argc < 2) + { + std::cerr << "Usage: parallel_grep \n"; + return 1; + } + + // We use a fixed size pool of threads for reading the input files. The + // number of threads is automatically determined based on the number of + // CPUs available in the system. + thread_pool pool; + + // To prevent the output from being garbled, we use a strand to synchronise + // printing. + strand output_strand(pool.get_executor()); + + // Spawn a new coroutine for each file specified on the command line. + std::string search_string = argv[1]; + for (int argn = 2; argn < argc; ++argn) + { + std::string input_file = argv[argn]; + spawn(pool, + [=](yield_context yield) + { + std::ifstream is(input_file.c_str()); + std::string line; + std::size_t line_num = 0; + while (std::getline(is, line)) + { + // If we find a match, send a message to the output. + if (line.find(search_string) != std::string::npos) + { + dispatch(output_strand, + [=] + { + std::cout << input_file << ':' << line << std::endl; + }); + } + + // Every so often we yield control to another coroutine. + if (++line_num % 10 == 0) + post(yield); + } + }); + } + + // Join the thread pool to wait for all the spawned tasks to complete. + pool.join(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/include/boost/asio.hpp b/include/boost/asio.hpp index 114d871c0c..b84f98fe42 100644 --- a/include/boost/asio.hpp +++ b/include/boost/asio.hpp @@ -17,6 +17,8 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#include +#include #include #include #include @@ -31,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +48,12 @@ #include #include #include +#include +#include #include +#include +#include +#include #include #include #include @@ -55,10 +63,18 @@ #include #include #include +#include +#include #include +#include #include #include +#include +#include #include +#include +#include +#include #include #include #include @@ -67,24 +83,29 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include +#include #include #include #include +#include #include #include #include @@ -100,7 +121,12 @@ #include #include #include +#include +#include +#include #include +#include +#include #include #include #include @@ -110,6 +136,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/asio/associated_allocator.hpp b/include/boost/asio/associated_allocator.hpp new file mode 100644 index 0000000000..b9ef5a452f --- /dev/null +++ b/include/boost/asio/associated_allocator.hpp @@ -0,0 +1,133 @@ +// +// associated_allocator.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 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 BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP +#define BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +struct associated_allocator_check +{ + typedef void type; +}; + +template +struct associated_allocator_impl +{ + typedef E type; + + static type get(const T&, const E& e) BOOST_ASIO_NOEXCEPT + { + return e; + } +}; + +template +struct associated_allocator_impl::type> +{ + typedef typename T::allocator_type type; + + static type get(const T& t, const E&) BOOST_ASIO_NOEXCEPT + { + return t.get_allocator(); + } +}; + +} // namespace detail + +/// Traits type used to obtain the allocator associated with an object. +/** + * A program may specialise this traits type if the @c T template parameter in + * the specialisation is a user-defined type. The template parameter @c + * Allocator shall be a type meeting the Allocator requirements. + * + * Specialisations shall meet the following requirements, where @c t is a const + * reference to an object of type @c T, and @c a is an object of type @c + * Allocator. + * + * @li Provide a nested typedef @c type that identifies a type meeting the + * Allocator requirements. + * + * @li Provide a noexcept static member function named @c get, callable as @c + * get(t) and with return type @c type. + * + * @li Provide a noexcept static member function named @c get, callable as @c + * get(t,a) and with return type @c type. + */ +template > +struct associated_allocator +{ + /// If @c T has a nested type @c allocator_type, T::allocator_type. + /// Otherwise @c Allocator. +#if defined(GENERATING_DOCUMENTATION) + typedef see_below type; +#else // defined(GENERATING_DOCUMENTATION) + typedef typename detail::associated_allocator_impl::type type; +#endif // defined(GENERATING_DOCUMENTATION) + + /// If @c T has a nested type @c allocator_type, returns + /// t.get_allocator(). Otherwise returns @c a. + static type get(const T& t, + const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT + { + return detail::associated_allocator_impl::get(t, a); + } +}; + +/// Helper function to obtain an object's associated allocator. +/** + * @returns associated_allocator::get(t) + */ +template +inline typename associated_allocator::type +get_associated_allocator(const T& t) BOOST_ASIO_NOEXCEPT +{ + return associated_allocator::get(t); +} + +/// Helper function to obtain an object's associated allocator. +/** + * @returns associated_allocator::get(t, a) + */ +template +inline typename associated_allocator::type +get_associated_allocator(const T& t, const Allocator& a) BOOST_ASIO_NOEXCEPT +{ + return associated_allocator::get(t, a); +} + +#if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES) + +template > +using associated_allocator_t + = typename associated_allocator::type; + +#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES) + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP diff --git a/include/boost/asio/associated_executor.hpp b/include/boost/asio/associated_executor.hpp new file mode 100644 index 0000000000..d0347afcfa --- /dev/null +++ b/include/boost/asio/associated_executor.hpp @@ -0,0 +1,151 @@ +// +// associated_executor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 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 BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP +#define BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +struct associated_executor_check +{ + typedef void type; +}; + +template +struct associated_executor_impl +{ + typedef E type; + + static type get(const T&, const E& e) BOOST_ASIO_NOEXCEPT + { + return e; + } +}; + +template +struct associated_executor_impl::type> +{ + typedef typename T::executor_type type; + + static type get(const T& t, const E&) BOOST_ASIO_NOEXCEPT + { + return t.get_executor(); + } +}; + +} // namespace detail + +/// Traits type used to obtain the executor associated with an object. +/** + * A program may specialise this traits type if the @c T template parameter in + * the specialisation is a user-defined type. The template parameter @c + * Executor shall be a type meeting the Executor requirements. + * + * Specialisations shall meet the following requirements, where @c t is a const + * reference to an object of type @c T, and @c e is an object of type @c + * Executor. + * + * @li Provide a nested typedef @c type that identifies a type meeting the + * Executor requirements. + * + * @li Provide a noexcept static member function named @c get, callable as @c + * get(t) and with return type @c type. + * + * @li Provide a noexcept static member function named @c get, callable as @c + * get(t,e) and with return type @c type. + */ +template +struct associated_executor +{ + /// If @c T has a nested type @c executor_type, T::executor_type. + /// Otherwise @c Executor. +#if defined(GENERATING_DOCUMENTATION) + typedef see_below type; +#else // defined(GENERATING_DOCUMENTATION) + typedef typename detail::associated_executor_impl::type type; +#endif // defined(GENERATING_DOCUMENTATION) + + /// If @c T has a nested type @c executor_type, returns + /// t.get_executor(). Otherwise returns @c ex. + static type get(const T& t, + const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT + { + return detail::associated_executor_impl::get(t, ex); + } +}; + +/// Helper function to obtain an object's associated executor. +/** + * @returns associated_executor::get(t) + */ +template +inline typename associated_executor::type +get_associated_executor(const T& t) BOOST_ASIO_NOEXCEPT +{ + return associated_executor::get(t); +} + +/// Helper function to obtain an object's associated executor. +/** + * @returns associated_executor::get(t, ex) + */ +template +inline typename associated_executor::type +get_associated_executor(const T& t, const Executor& ex, + typename enable_if::value>::type* = 0) BOOST_ASIO_NOEXCEPT +{ + return associated_executor::get(t, ex); +} + +/// Helper function to obtain an object's associated executor. +/** + * @returns associated_executor::get(t, ctx.get_executor()) + */ +template +inline typename associated_executor::type +get_associated_executor(const T& t, ExecutionContext& ctx, + typename enable_if::value>::type* = 0) BOOST_ASIO_NOEXCEPT +{ + return associated_executor::get(t, ctx.get_executor()); +} + +#if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES) + +template +using associated_executor_t = typename associated_executor::type; + +#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES) + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP diff --git a/include/boost/asio/async_result.hpp b/include/boost/asio/async_result.hpp index 6290b8462a..f49f2eb2e0 100644 --- a/include/boost/asio/async_result.hpp +++ b/include/boost/asio/async_result.hpp @@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include +#include #include #include @@ -24,11 +25,94 @@ namespace boost { namespace asio { /// An interface for customising the behaviour of an initiating function. +/** + * The async_result traits class is used for determining: + * + * @li the concrete completion handler type to be called at the end of the + * asynchronous operation; + * + * @li the initiating function return type; and + * + * @li how the return value of the initiating function is obtained. + * + * The trait allows the handler and return types to be determined at the point + * where the specific completion handler signature is known. + * + * This template may be specialised for user-defined completion token types. + * The primary template assumes that the CompletionToken is the completion + * handler. + */ +#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) +template +#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) +template +#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) +class async_result +{ +public: +#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + /// The concrete completion handler type for the specific signature. + typedef CompletionToken completion_handler_type; + + /// The return type of the initiating function. + typedef void return_type; +#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + // For backward compatibility, determine the concrete completion handler type + // by using the legacy handler_type trait. + typedef typename handler_type::type + completion_handler_type; + + // For backward compatibility, determine the initiating function return type + // using the legacy single-parameter version of async_result. + typedef typename async_result::type return_type; +#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + + /// Construct an async result from a given handler. + /** + * When using a specalised async_result, the constructor has an opportunity + * to initialise some state associated with the completion handler, which is + * then returned from the initiating function. + */ + explicit async_result(completion_handler_type& h) +#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + // No data members to initialise. +#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + : legacy_result_(h) +#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + { + (void)h; + } + + /// Obtain the value to be returned from the initiating function. + return_type get() + { +#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + // Nothing to do. +#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + return legacy_result_.get(); +#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + } + +private: + async_result(const async_result&) BOOST_ASIO_DELETED; + async_result& operator=(const async_result&) BOOST_ASIO_DELETED; + +#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + // No data members. +#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + async_result legacy_result_; +#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) +}; + +#if !defined(BOOST_ASIO_NO_DEPRECATED) + +/// (Deprecated: Use two-parameter version of async_result.) An interface for +/// customising the behaviour of an initiating function. /** * This template may be specialised for user-defined handler types. */ template -class async_result +class async_result { public: /// The return type of the initiating function. @@ -50,29 +134,65 @@ class async_result } }; -namespace detail { +#endif // !defined(BOOST_ASIO_NO_DEPRECATED) -// Helper template to deduce the true type of a handler, capture a local copy -// of the handler, and then create an async_result for the handler. -template -struct async_result_init +/// Helper template to deduce the handler type from a CompletionToken, capture +/// a local copy of the handler, and then create an async_result for the +/// handler. +template +struct async_completion { - explicit async_result_init(BOOST_ASIO_MOVE_ARG(Handler) orig_handler) - : handler(BOOST_ASIO_MOVE_CAST(Handler)(orig_handler)), - result(handler) + /// The real handler type to be used for the asynchronous operation. + typedef typename boost::asio::async_result< + typename decay::type, + Signature>::completion_handler_type completion_handler_type; + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Constructor. + /** + * The constructor creates the concrete completion handler and makes the link + * between the handler and the asynchronous result. + */ + explicit async_completion(CompletionToken& token) + : completion_handler(static_cast::value, + completion_handler_type&, CompletionToken&&>::type>(token)), + result(completion_handler) + { + } +#else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + explicit async_completion(typename decay::type& token) + : completion_handler(token), + result(completion_handler) { } - typename handler_type::type handler; - async_result::type> result; + explicit async_completion(const typename decay::type& token) + : completion_handler(token), + result(completion_handler) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// A copy of, or reference to, a real handler object. +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + typename conditional< + is_same::value, + completion_handler_type&, completion_handler_type>::type completion_handler; +#else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + completion_handler_type completion_handler; +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// The result of the asynchronous operation's initiating function. + async_result::type, Signature> result; }; -template -struct async_result_type_helper +namespace detail { + +template +struct async_result_helper + : async_result::type, Signature> { - typedef typename async_result< - typename handler_type::type - >::type type; }; } // namespace detail @@ -82,15 +202,22 @@ struct async_result_type_helper #include #if defined(GENERATING_DOCUMENTATION) -# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \ +# define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \ void_or_deduced #elif defined(_MSC_VER) && (_MSC_VER < 1500) -# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \ - typename ::boost::asio::detail::async_result_type_helper::type +# define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \ + typename ::boost::asio::detail::async_result_helper< \ + ct, sig>::return_type +#define BOOST_ASIO_HANDLER_TYPE(ct, sig) \ + typename ::boost::asio::detail::async_result_helper< \ + ct, sig>::completion_handler_type #else -# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \ +# define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \ + typename ::boost::asio::async_result< \ + typename ::boost::asio::decay::type, sig>::return_type +#define BOOST_ASIO_HANDLER_TYPE(ct, sig) \ typename ::boost::asio::async_result< \ - typename ::boost::asio::handler_type::type>::type + typename ::boost::asio::decay::type, sig>::completion_handler_type #endif #endif // BOOST_ASIO_ASYNC_RESULT_HPP diff --git a/include/boost/asio/basic_datagram_socket.hpp b/include/boost/asio/basic_datagram_socket.hpp index 22801ee081..c2aa00bf48 100644 --- a/include/boost/asio/basic_datagram_socket.hpp +++ b/include/boost/asio/basic_datagram_socket.hpp @@ -18,12 +18,15 @@ #include #include #include -#include #include #include #include #include +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +# include +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + #include namespace boost { @@ -38,18 +41,19 @@ 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: - /// (Deprecated: Use native_handle_type.) The native representation of a - /// socket. - typedef typename DatagramSocketService::native_handle_type native_type; - /// The native representation of a socket. - typedef typename DatagramSocketService::native_handle_type native_handle_type; +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef typename basic_socket< + Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type; +#endif /// The protocol type. typedef Protocol protocol_type; @@ -62,12 +66,12 @@ 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_service The io_service object that the datagram socket will use + * @param io_context The io_context object that the datagram socket will use * to dispatch handlers for any asynchronous operations performed on the * socket. */ - explicit basic_datagram_socket(boost::asio::io_service& io_service) - : basic_socket(io_service) + explicit basic_datagram_socket(boost::asio::io_context& io_context) + : basic_socket(io_context) { } @@ -75,7 +79,7 @@ class basic_datagram_socket /** * This constructor creates and opens a datagram socket. * - * @param io_service The io_service object that the datagram socket will use + * @param io_context The io_context object that the datagram socket will use * to dispatch handlers for any asynchronous operations performed on the * socket. * @@ -83,9 +87,9 @@ class basic_datagram_socket * * @throws boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_service& io_service, + basic_datagram_socket(boost::asio::io_context& io_context, const protocol_type& protocol) - : basic_socket(io_service, protocol) + : basic_socket(io_context, protocol) { } @@ -96,7 +100,7 @@ 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_service The io_service object that the datagram socket will use + * @param io_context The io_context object that the datagram socket will use * to dispatch handlers for any asynchronous operations performed on the * socket. * @@ -105,9 +109,9 @@ class basic_datagram_socket * * @throws boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_service& io_service, + basic_datagram_socket(boost::asio::io_context& io_context, const endpoint_type& endpoint) - : basic_socket(io_service, endpoint) + : basic_socket(io_context, endpoint) { } @@ -116,7 +120,7 @@ class basic_datagram_socket * This constructor creates a datagram socket object to hold an existing * native socket. * - * @param io_service The io_service object that the datagram socket will use + * @param io_context The io_context object that the datagram socket will use * to dispatch handlers for any asynchronous operations performed on the * socket. * @@ -126,10 +130,10 @@ class basic_datagram_socket * * @throws boost::system::system_error Thrown on failure. */ - basic_datagram_socket(boost::asio::io_service& io_service, + basic_datagram_socket(boost::asio::io_context& io_context, const protocol_type& protocol, const native_handle_type& native_socket) - : basic_socket( - io_service, protocol, native_socket) + : basic_socket( + io_context, protocol, native_socket) { } @@ -142,11 +146,10 @@ 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_service&) constructor. + * constructed using the @c basic_datagram_socket(io_context&) constructor. */ basic_datagram_socket(basic_datagram_socket&& other) - : basic_socket( - BOOST_ASIO_MOVE_CAST(basic_datagram_socket)(other)) + : basic_socket(std::move(other)) { } @@ -159,12 +162,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_service&) constructor. + * constructed using the @c basic_datagram_socket(io_context&) constructor. */ basic_datagram_socket& operator=(basic_datagram_socket&& other) { - basic_socket::operator=( - BOOST_ASIO_MOVE_CAST(basic_datagram_socket)(other)); + basic_socket::operator=(std::move(other)); return *this; } @@ -177,15 +179,13 @@ 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_service&) constructor. + * constructed using the @c basic_datagram_socket(io_context&) constructor. */ - template + template basic_datagram_socket( - basic_datagram_socket&& other, + basic_datagram_socket&& other, typename enable_if::value>::type* = 0) - : basic_socket( - BOOST_ASIO_MOVE_CAST2(basic_datagram_socket< - Protocol1, DatagramSocketService1>)(other)) + : basic_socket(std::move(other)) { } @@ -199,20 +199,27 @@ 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_service&) constructor. + * constructed using the @c basic_datagram_socket(io_context&) constructor. */ - template + template typename enable_if::value, basic_datagram_socket>::type& operator=( - basic_datagram_socket&& other) + basic_datagram_socket&& other) { - basic_socket::operator=( - BOOST_ASIO_MOVE_CAST2(basic_datagram_socket< - Protocol1, DatagramSocketService1>)(other)); + basic_socket::operator=(std::move(other)); return *this; } #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Destroys the socket. + /** + * This function destroys the socket, cancelling any outstanding asynchronous + * operations associated with the socket as if by calling @c cancel. + */ + ~basic_datagram_socket() + { + } + /// Send some data on a connected socket. /** * This function is used to send data on the datagram socket. The function @@ -318,7 +325,7 @@ class basic_datagram_socket * 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_service::post(). + * boost::asio::io_context::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 @@ -343,8 +350,18 @@ class basic_datagram_socket // not meet the documented type requirements for a WriteHandler. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) return this->get_service().async_send(this->get_implementation(), buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + async_completion init(handler); + + this->get_service().async_send(this->get_implementation(), + buffers, 0, init.completion_handler); + + return init.result.get(); +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } /// Start an asynchronous send on a connected socket. @@ -369,7 +386,7 @@ class basic_datagram_socket * 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_service::post(). + * boost::asio::io_context::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 @@ -386,8 +403,18 @@ class basic_datagram_socket // not meet the documented type requirements for a WriteHandler. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) return this->get_service().async_send(this->get_implementation(), buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + async_completion init(handler); + + this->get_service().async_send(this->get_implementation(), + buffers, flags, init.completion_handler); + + return init.result.get(); +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } /// Send a datagram to the specified endpoint. @@ -501,7 +528,7 @@ class basic_datagram_socket * 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_service::post(). + * boost::asio::io_context::post(). * * @par Example * To send a single data buffer use the @ref buffer function as follows: @@ -526,9 +553,20 @@ class basic_datagram_socket // not meet the documented type requirements for a WriteHandler. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) return this->get_service().async_send_to( this->get_implementation(), buffers, destination, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + async_completion init(handler); + + this->get_service().async_send_to( + this->get_implementation(), buffers, destination, 0, + init.completion_handler); + + return init.result.get(); +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } /// Start an asynchronous send. @@ -556,7 +594,7 @@ class basic_datagram_socket * 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_service::post(). + * boost::asio::io_context::post(). */ template BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, @@ -569,9 +607,20 @@ class basic_datagram_socket // not meet the documented type requirements for a WriteHandler. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) return this->get_service().async_send_to( this->get_implementation(), buffers, destination, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + async_completion init(handler); + + this->get_service().async_send_to( + this->get_implementation(), buffers, destination, flags, + init.completion_handler); + + return init.result.get(); +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } /// Receive some data on a connected socket. @@ -683,7 +732,7 @@ class basic_datagram_socket * 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_service::post(). + * boost::asio::io_context::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 @@ -709,8 +758,18 @@ class basic_datagram_socket // not meet the documented type requirements for a ReadHandler. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) return this->get_service().async_receive(this->get_implementation(), buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + async_completion init(handler); + + this->get_service().async_receive(this->get_implementation(), + buffers, 0, init.completion_handler); + + return init.result.get(); +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } /// Start an asynchronous receive on a connected socket. @@ -735,7 +794,7 @@ class basic_datagram_socket * 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_service::post(). + * boost::asio::io_context::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 @@ -752,8 +811,18 @@ class basic_datagram_socket // not meet the documented type requirements for a ReadHandler. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) return this->get_service().async_receive(this->get_implementation(), buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + async_completion init(handler); + + this->get_service().async_receive(this->get_implementation(), + buffers, flags, init.completion_handler); + + return init.result.get(); +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } /// Receive a datagram with the endpoint of the sender. @@ -870,7 +939,7 @@ class basic_datagram_socket * 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_service::post(). + * boost::asio::io_context::post(). * * @par Example * To receive into a single data buffer use the @ref buffer function as @@ -892,9 +961,20 @@ class basic_datagram_socket // not meet the documented type requirements for a ReadHandler. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) return this->get_service().async_receive_from( this->get_implementation(), buffers, sender_endpoint, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + async_completion init(handler); + + this->get_service().async_receive_from( + this->get_implementation(), buffers, sender_endpoint, 0, + init.completion_handler); + + return init.result.get(); +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } /// Start an asynchronous receive. @@ -924,7 +1004,7 @@ class basic_datagram_socket * 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_service::post(). + * boost::asio::io_context::post(). */ template BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, @@ -937,9 +1017,20 @@ class basic_datagram_socket // not meet the documented type requirements for a ReadHandler. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) return this->get_service().async_receive_from( this->get_implementation(), buffers, sender_endpoint, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) + async_completion init(handler); + + this->get_service().async_receive_from( + this->get_implementation(), buffers, sender_endpoint, flags, + init.completion_handler); + + return init.result.get(); +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) } }; diff --git a/include/boost/asio/basic_deadline_timer.hpp b/include/boost/asio/basic_deadline_timer.hpp index 930370046b..f7179a853e 100644 --- a/include/boost/asio/basic_deadline_timer.hpp +++ b/include/boost/asio/basic_deadline_timer.hpp @@ -22,10 +22,17 @@ #include #include -#include #include #include #include +#include + +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +# include +#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) +# include +# define BOOST_ASIO_SVC_T detail::deadline_timer_service +#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) #include @@ -51,7 +58,7 @@ namespace asio { * Performing a blocking wait: * @code * // Construct a timer without setting an expiry time. - * boost::asio::deadline_timer timer(io_service); + * boost::asio::deadline_timer timer(io_context); * * // Set an expiry time relative to now. * timer.expires_from_now(boost::posix_time::seconds(5)); @@ -74,7 +81,7 @@ namespace asio { * ... * * // Construct a timer with an absolute expiry time. - * boost::asio::deadline_timer timer(io_service, + * boost::asio::deadline_timer timer(io_context, * boost::posix_time::time_from_string("2005-12-07 23:59:59.000")); * * // Start an asynchronous wait. @@ -121,12 +128,15 @@ namespace asio { * it contains the value boost::asio::error::operation_aborted. */ template , - typename TimerService = deadline_timer_service > + typename TimeTraits = boost::asio::time_traits