]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | / Copyright (c) 2003-2016 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 | ||
10 | The [link boost_asio.reference.spawn `spawn()`] function is a high-level wrapper for | |
11 | running stackful coroutines. It is based on the Boost.Coroutine library. The | |
12 | `spawn()` function enables programs to implement asynchronous logic in a | |
13 | synchronous 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 | ||
40 | The first argument to `spawn()` may be a | |
41 | [link boost_asio.reference.io_service__strand `strand`], | |
42 | [link boost_asio.reference.io_service `io_service`], or | |
43 | [link boost_asio.reference.CompletionHandler completion handler]. | |
44 | This argument determines the context in which the coroutine is permitted to | |
45 | execute. For example, a server's per-client object may consist of multiple | |
46 | coroutines; they should all run on the same `strand` so that no explicit | |
47 | synchronisation is required. | |
48 | ||
49 | The second argument is a function object with signature: | |
50 | ||
51 | void coroutine(boost::asio::yield_context yield); | |
52 | ||
53 | that 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 | |
55 | handler, as in: | |
56 | ||
57 | std::size_t length = | |
58 | my_socket.async_read_some( | |
59 | boost::asio::buffer(data), yield); | |
60 | ||
61 | This starts the asynchronous operation and suspends the coroutine. The | |
62 | coroutine will be resumed automatically when the asynchronous operation | |
63 | completes. | |
64 | ||
65 | Where an asynchronous operation's handler signature has the form: | |
66 | ||
67 | void handler(boost::system::error_code ec, result_type result); | |
68 | ||
69 | the initiating function returns the result_type. In the `async_read_some` | |
70 | example above, this is `size_t`. If the asynchronous operation fails, the | |
71 | `error_code` is converted into a `system_error` exception and thrown. | |
72 | ||
73 | Where a handler signature has the form: | |
74 | ||
75 | void handler(boost::system::error_code ec); | |
76 | ||
77 | the initiating function returns `void`. As above, an error is passed back to | |
78 | the coroutine as a `system_error` exception. | |
79 | ||
80 | To collect the `error_code` from an operation, rather than have it throw an | |
81 | exception, 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] |