| Home | Libraries | People | FAQ | More

#### 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_context`, 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.