1[/ 2 / Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 3 / 4 / Distributed under the Boost Software License, Version 1.0. (See accompanying 5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 /] 7 8[section:spawn Stackful Coroutines] 9 10The [link boost_asio.reference.spawn `spawn()`] function is a high-level wrapper for 11running stackful coroutines. It is based on the Boost.Coroutine library. The 12`spawn()` function enables programs to implement asynchronous logic in a 13synchronous manner, as shown in the following example: 14 15 boost::asio::spawn(my_strand, do_echo); 16 17 // ... 18 19 void do_echo(boost::asio::yield_context yield) 20 { 21 try 22 { 23 char data[128]; 24 for (;;) 25 { 26 std::size_t length = 27 my_socket.async_read_some( 28 boost::asio::buffer(data), yield); 29 30 boost::asio::async_write(my_socket, 31 boost::asio::buffer(data, length), yield); 32 } 33 } 34 catch (std::exception& e) 35 { 36 // ... 37 } 38 } 39 40The first argument to `spawn()` may be a 41[link boost_asio.reference.io_context__strand `strand`], 42[link boost_asio.reference.io_context `io_context`], or 43[link boost_asio.reference.CompletionHandler completion handler]. 44This argument determines the context in which the coroutine is permitted to 45execute. For example, a server's per-client object may consist of multiple 46coroutines; they should all run on the same `strand` so that no explicit 47synchronisation is required. 48 49The second argument is a function object with signature: 50 51 void coroutine(boost::asio::yield_context yield); 52 53that specifies the code to be run as part of the coroutine. The parameter 54`yield` may be passed to an asynchronous operation in place of the completion 55handler, as in: 56 57 std::size_t length = 58 my_socket.async_read_some( 59 boost::asio::buffer(data), yield); 60 61This starts the asynchronous operation and suspends the coroutine. The 62coroutine will be resumed automatically when the asynchronous operation 63completes. 64 65Where an asynchronous operation's handler signature has the form: 66 67 void handler(boost::system::error_code ec, result_type result); 68 69the initiating function returns the result_type. In the `async_read_some` 70example above, this is `size_t`. If the asynchronous operation fails, the 71`error_code` is converted into a `system_error` exception and thrown. 72 73Where a handler signature has the form: 74 75 void handler(boost::system::error_code ec); 76 77the initiating function returns `void`. As above, an error is passed back to 78the coroutine as a `system_error` exception. 79 80To collect the `error_code` from an operation, rather than have it throw an 81exception, associate the output variable with the `yield_context` as follows: 82 83 boost::system::error_code ec; 84 std::size_t length = 85 my_socket.async_read_some( 86 boost::asio::buffer(data), yield[ec]); 87 88[*Note:] if `spawn()` is used with a custom completion handler of type 89`Handler`, the function object signature is actually: 90 91 void coroutine(boost::asio::basic_yield_context<Handler> yield); 92 93[heading See Also] 94 95[link boost_asio.reference.spawn spawn], 96[link boost_asio.reference.yield_context yield_context], 97[link boost_asio.reference.basic_yield_context basic_yield_context], 98[link boost_asio.examples.cpp03_examples.spawn Spawn example (C++03)], 99[link boost_asio.examples.cpp11_examples.spawn Spawn example (C++11)], 100[link boost_asio.overview.core.coroutine Stackless Coroutines]. 101 102[endsect] 103