| Home | Libraries | People | FAQ | More

#### Coroutines TS Support

Support for the Coroutines TS is provided via the `awaitable` class template, the `use_awaitable` completion token, and the `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:

    boost::asio::co_spawn(executor,
        [socket = std::move(socket)]() mutable
        {
          return echo(std::move(socket));
        },
        boost::asio::detached);

    // ...

    boost::asio::awaitable<void> echo(tcp::socket socket)
    {
      try
      {
        char data[1024];
        for (;;)
        {
          std::size_t n = co_await socket.async_read_some(boost::asio::buffer(data), boost::asio::use_awaitable);
          co_await async_write(socket, boost::asio::buffer(data, n), boost::asio::use_awaitable);
        }
      }
      catch (std::exception& e)
      {
        std::printf("echo Exception: %s\n", e.what());
      }
    }

The first argument to `co_spawn()` is an 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 `boost::asio::awaitable<R>`, 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, `boost::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(boost::asio::buffer(data), boost::asio::use_awaitable);

Where an asynchronous operation's handler signature has the form:

    void handler(boost::system::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(boost::system::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.

###### See Also

co_spawn, detached, redirect_error, awaitable, use_awaitable_t, use_awaitable, this_coro::executor, Coroutines TS examples, Stackful Coroutines, Stackless Coroutines.