asio C++ library

PrevUpHomeNext

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:

asio::co_spawn(executor, echo(std::move(socket)), asio::detached);

// ...

asio::awaitable<void> 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 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 an awaitable<R>, that is the result of the coroutine's entry point function, and in the above example is the result of the call to echo. (Alternatively, this argument can be a function object that returns the awaitable<R>.) The template parameter 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, 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.

See Also

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


PrevUpHomeNext