[/ / Copyright (c) 2003-2020 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:coroutines_ts Coroutines TS Support] Support for the Coroutines TS is provided via the [link asio.reference.awaitable `awaitable`] class template, the [link asio.reference.use_awaitable_t `use_awaitable`] completion token, and the [link asio.reference.co_spawn `co_spawn()`] function. These facilities allow programs to implement asynchronous logic in a synchronous manner, in conjunction with the `co_await` keyword, as shown in the following example: asio::co_spawn(executor, [socket = std::move(socket)]() mutable { return echo(std::move(socket)); }, asio::detached); // ... asio::awaitable echo(tcp::socket socket) { try { char data[1024]; for (;;) { std::size_t n = co_await socket.async_read_some(asio::buffer(data), asio::use_awaitable); co_await async_write(socket, asio::buffer(data, n), asio::use_awaitable); } } catch (std::exception& e) { std::printf("echo Exception: %s\n", e.what()); } } The first argument to `co_spawn()` is an [link asio.reference.Executor1 executor] that determines the context in which the coroutine is permitted to execute. For example, a server's per-client object may consist of multiple coroutines; they should all run on the same `strand` so that no explicit synchronisation is required. The second argument is a nullary function object that returns a [link asio.reference.awaitable `asio::awaitable`], where `R` is the type of return value produced by the coroutine. In the above example, the coroutine returns `void`. The third argument is a completion token, and this is used by `co_spawn()` to produce a completion handler with signature `void(std::exception_ptr, R)`. This completion handler is invoked with the result of the coroutine once it has finished. In the above example we pass a completion token type, [link asio.reference.detached `asio::detached`], which is used to explicitly ignore the result of an asynchronous operation. In this example the body of the coroutine is implemented in the `echo` function. When the `use_awaitable` completion token is passed to an asynchronous operation, the operation's initiating function returns an `awaitable` that may be used with the `co_await` keyword: std::size_t n = co_await socket.async_read_some(asio::buffer(data), asio::use_awaitable); Where an asynchronous operation's handler signature has the form: void handler(asio::error_code ec, result_type result); the resulting type of the `co_await` expression is `result_type`. In the `async_read_some` example above, this is `size_t`. If the asynchronous operation fails, the `error_code` is converted into a `system_error` exception and thrown. Where a handler signature has the form: void handler(asio::error_code ec); the `co_await` expression produces a `void` result. As above, an error is passed back to the coroutine as a `system_error` exception. [heading See Also] [link asio.reference.co_spawn co_spawn], [link asio.reference.detached detached], [link asio.reference.redirect_error redirect_error], [link asio.reference.awaitable awaitable], [link asio.reference.use_awaitable_t use_awaitable_t], [link asio.reference.use_awaitable use_awaitable], [link asio.reference.this_coro__executor this_coro::executor], [link asio.examples.cpp17_examples.coroutines_ts_support Coroutines TS examples], [link asio.overview.core.spawn Stackful Coroutines], [link asio.overview.core.coroutine Stackless Coroutines]. [endsect]