Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Stackful Coroutines

The spawn() function is a high-level wrapper for running stackful coroutines. It is based on the Boost.Coroutine library. The spawn() function enables programs to implement asynchronous logic in a synchronous manner, as shown in the following example:

boost::asio::spawn(my_strand, do_echo);

// ...

void do_echo(boost::asio::yield_context yield)
{
  try
  {
    char data[128];
    for (;;)
    {
      std::size_t length =
        my_socket.async_read_some(
          boost::asio::buffer(data), yield);

      boost::asio::async_write(my_socket,
          boost::asio::buffer(data, length), yield);
    }
  }
  catch (std::exception& e)
  {
    // ...
  }
}

The first argument to spawn() may be a strand, io_service, or 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 coroutines; they should all run on the same strand so that no explicit synchronisation is required.

The second argument is a function object with signature:

void coroutine(boost::asio::yield_context yield);

that specifies the code to be run as part of the coroutine. The parameter yield may be passed to an asynchronous operation in place of the completion handler, as in:

std::size_t length =
  my_socket.async_read_some(
    boost::asio::buffer(data), yield);

This starts the asynchronous operation and suspends the coroutine. The coroutine will be resumed automatically when the asynchronous operation completes.

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

void handler(boost::system::error_code ec, result_type result);

the initiating function returns the 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 initiating function returns void. As above, an error is passed back to the coroutine as a system_error exception.

To collect the error_code from an operation, rather than have it throw an exception, associate the output variable with the yield_context as follows:

boost::system::error_code ec;
std::size_t length =
  my_socket.async_read_some(
    boost::asio::buffer(data), yield[ec]);

Note: if spawn() is used with a custom completion handler of type Handler, the function object signature is actually:

void coroutine(boost::asio::basic_yield_context<Handler> yield);
See Also

spawn, yield_context, basic_yield_context, Spawn example (C++03), Spawn example (C++11), Stackless Coroutines.


PrevUpHomeNext