| [/ |
| / Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
| / |
| / Distributed under the Boost Software License, Version 1.0. (See accompanying |
| / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| /] |
| |
| [section:spawn Stackful Coroutines] |
| |
| The [link asio.reference.spawn `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: |
| |
| 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 `spawn()` may be a |
| [link asio.reference.io_context__strand `strand`], |
| [link asio.reference.io_context `io_context`], or |
| [link asio.reference.CompletionHandler 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 an asynchronous operation's handler signature has the form: |
| |
| void handler(asio::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(asio::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: |
| |
| asio::error_code ec; |
| std::size_t length = |
| my_socket.async_read_some( |
| 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(asio::basic_yield_context<Handler> yield); |
| |
| [heading See Also] |
| |
| [link asio.reference.spawn spawn], |
| [link asio.reference.yield_context yield_context], |
| [link asio.reference.basic_yield_context basic_yield_context], |
| [link asio.examples.cpp03_examples.spawn Spawn example (C++03)], |
| [link asio.examples.cpp11_examples.spawn Spawn example (C++11)], |
| [link asio.overview.core.coroutine Stackless Coroutines]. |
| |
| [endsect] |