Go to file
Christopher Kohlhoff 5de7e88324 Add the asio::spawn() function, a high-level wrapper for running
stackful coroutines. It is based on the Boost.Coroutine library.

Here is an example of its use:

  asio::spawn(my_strand, do_echo);

  // ...

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

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

The first argument to asio::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(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(
      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 a completion handler signature has the form:

  void handler(error_code ec, result_type result);

the initiating function returns the result_type. In the async_read_some
example above, this is std::size_t. If the asynchronous operation fails,
the error_code is converted into a system_error exception and thrown.

Where a completion handler signature has the form:

  void handler(error_code ec);

the initiating function returns void. As above, an error is passed back
in the future 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:

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

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

  void coroutine(asio::basic_yield_context<Handler> yield);
2013-05-13 16:27:18 +10:00
asio Add the asio::spawn() function, a high-level wrapper for running 2013-05-13 16:27:18 +10:00