comparison DEPENDENCIES/generic/include/boost/asio/spawn.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 //
2 // spawn.hpp
3 // ~~~~~~~~~
4 //
5 // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10
11 #ifndef BOOST_ASIO_SPAWN_HPP
12 #define BOOST_ASIO_SPAWN_HPP
13
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/coroutine/coroutine.hpp>
20 #include <boost/asio/detail/weak_ptr.hpp>
21 #include <boost/asio/detail/wrapped_handler.hpp>
22 #include <boost/asio/io_service.hpp>
23 #include <boost/asio/strand.hpp>
24
25 #include <boost/asio/detail/push_options.hpp>
26
27 namespace boost {
28 namespace asio {
29
30 /// Context object the represents the currently executing coroutine.
31 /**
32 * The basic_yield_context class is used to represent the currently executing
33 * stackful coroutine. A basic_yield_context may be passed as a handler to an
34 * asynchronous operation. For example:
35 *
36 * @code template <typename Handler>
37 * void my_coroutine(basic_yield_context<Handler> yield)
38 * {
39 * ...
40 * std::size_t n = my_socket.async_read_some(buffer, yield);
41 * ...
42 * } @endcode
43 *
44 * The initiating function (async_read_some in the above example) suspends the
45 * current coroutine. The coroutine is resumed when the asynchronous operation
46 * completes, and the result of the operation is returned.
47 */
48 template <typename Handler>
49 class basic_yield_context
50 {
51 public:
52 /// The coroutine callee type, used by the implementation.
53 /**
54 * When using Boost.Coroutine v1, this type is:
55 * @code typename coroutine<void()> @endcode
56 * When using Boost.Coroutine v2 (unidirectional coroutines), this type is:
57 * @code push_coroutine<void> @endcode
58 */
59 #if defined(GENERATING_DOCUMENTATION)
60 typedef implementation_defined callee_type;
61 #elif defined(BOOST_COROUTINES_UNIDRECT) || defined(BOOST_COROUTINES_V2)
62 typedef boost::coroutines::push_coroutine<void> callee_type;
63 #else
64 typedef boost::coroutines::coroutine<void()> callee_type;
65 #endif
66
67 /// The coroutine caller type, used by the implementation.
68 /**
69 * When using Boost.Coroutine v1, this type is:
70 * @code typename coroutine<void()>::caller_type @endcode
71 * When using Boost.Coroutine v2 (unidirectional coroutines), this type is:
72 * @code pull_coroutine<void> @endcode
73 */
74 #if defined(GENERATING_DOCUMENTATION)
75 typedef implementation_defined caller_type;
76 #elif defined(BOOST_COROUTINES_UNIDRECT) || defined(BOOST_COROUTINES_V2)
77 typedef boost::coroutines::pull_coroutine<void> caller_type;
78 #else
79 typedef boost::coroutines::coroutine<void()>::caller_type caller_type;
80 #endif
81
82 /// Construct a yield context to represent the specified coroutine.
83 /**
84 * Most applications do not need to use this constructor. Instead, the
85 * spawn() function passes a yield context as an argument to the coroutine
86 * function.
87 */
88 basic_yield_context(
89 const detail::weak_ptr<callee_type>& coro,
90 caller_type& ca, Handler& handler)
91 : coro_(coro),
92 ca_(ca),
93 handler_(handler),
94 ec_(0)
95 {
96 }
97
98 /// Return a yield context that sets the specified error_code.
99 /**
100 * By default, when a yield context is used with an asynchronous operation, a
101 * non-success error_code is converted to system_error and thrown. This
102 * operator may be used to specify an error_code object that should instead be
103 * set with the asynchronous operation's result. For example:
104 *
105 * @code template <typename Handler>
106 * void my_coroutine(basic_yield_context<Handler> yield)
107 * {
108 * ...
109 * std::size_t n = my_socket.async_read_some(buffer, yield[ec]);
110 * if (ec)
111 * {
112 * // An error occurred.
113 * }
114 * ...
115 * } @endcode
116 */
117 basic_yield_context operator[](boost::system::error_code& ec) const
118 {
119 basic_yield_context tmp(*this);
120 tmp.ec_ = &ec;
121 return tmp;
122 }
123
124 #if defined(GENERATING_DOCUMENTATION)
125 private:
126 #endif // defined(GENERATING_DOCUMENTATION)
127 detail::weak_ptr<callee_type> coro_;
128 caller_type& ca_;
129 Handler& handler_;
130 boost::system::error_code* ec_;
131 };
132
133 #if defined(GENERATING_DOCUMENTATION)
134 /// Context object that represents the currently executing coroutine.
135 typedef basic_yield_context<unspecified> yield_context;
136 #else // defined(GENERATING_DOCUMENTATION)
137 typedef basic_yield_context<
138 detail::wrapped_handler<
139 io_service::strand, void(*)(),
140 detail::is_continuation_if_running> > yield_context;
141 #endif // defined(GENERATING_DOCUMENTATION)
142
143 /**
144 * @defgroup spawn boost::asio::spawn
145 *
146 * @brief Start a new stackful coroutine.
147 *
148 * The spawn() function is a high-level wrapper over the Boost.Coroutine
149 * library. This function enables programs to implement asynchronous logic in a
150 * synchronous manner, as illustrated by the following example:
151 *
152 * @code boost::asio::spawn(my_strand, do_echo);
153 *
154 * // ...
155 *
156 * void do_echo(boost::asio::yield_context yield)
157 * {
158 * try
159 * {
160 * char data[128];
161 * for (;;)
162 * {
163 * std::size_t length =
164 * my_socket.async_read_some(
165 * boost::asio::buffer(data), yield);
166 *
167 * boost::asio::async_write(my_socket,
168 * boost::asio::buffer(data, length), yield);
169 * }
170 * }
171 * catch (std::exception& e)
172 * {
173 * // ...
174 * }
175 * } @endcode
176 */
177 /*@{*/
178
179 /// Start a new stackful coroutine, calling the specified handler when it
180 /// completes.
181 /**
182 * This function is used to launch a new coroutine.
183 *
184 * @param handler A handler to be called when the coroutine exits. More
185 * importantly, the handler provides an execution context (via the the handler
186 * invocation hook) for the coroutine. The handler must have the signature:
187 * @code void handler(); @endcode
188 *
189 * @param function The coroutine function. The function must have the signature:
190 * @code void function(basic_yield_context<Handler> yield); @endcode
191 *
192 * @param attributes Boost.Coroutine attributes used to customise the coroutine.
193 */
194 template <typename Handler, typename Function>
195 void spawn(BOOST_ASIO_MOVE_ARG(Handler) handler,
196 BOOST_ASIO_MOVE_ARG(Function) function,
197 const boost::coroutines::attributes& attributes
198 = boost::coroutines::attributes());
199
200 /// Start a new stackful coroutine, inheriting the execution context of another.
201 /**
202 * This function is used to launch a new coroutine.
203 *
204 * @param ctx Identifies the current coroutine as a parent of the new
205 * coroutine. This specifies that the new coroutine should inherit the
206 * execution context of the parent. For example, if the parent coroutine is
207 * executing in a particular strand, then the new coroutine will execute in the
208 * same strand.
209 *
210 * @param function The coroutine function. The function must have the signature:
211 * @code void function(basic_yield_context<Handler> yield); @endcode
212 *
213 * @param attributes Boost.Coroutine attributes used to customise the coroutine.
214 */
215 template <typename Handler, typename Function>
216 void spawn(basic_yield_context<Handler> ctx,
217 BOOST_ASIO_MOVE_ARG(Function) function,
218 const boost::coroutines::attributes& attributes
219 = boost::coroutines::attributes());
220
221 /// Start a new stackful coroutine that executes in the context of a strand.
222 /**
223 * This function is used to launch a new coroutine.
224 *
225 * @param strand Identifies a strand. By starting multiple coroutines on the
226 * same strand, the implementation ensures that none of those coroutines can
227 * execute simultaneously.
228 *
229 * @param function The coroutine function. The function must have the signature:
230 * @code void function(yield_context yield); @endcode
231 *
232 * @param attributes Boost.Coroutine attributes used to customise the coroutine.
233 */
234 template <typename Function>
235 void spawn(boost::asio::io_service::strand strand,
236 BOOST_ASIO_MOVE_ARG(Function) function,
237 const boost::coroutines::attributes& attributes
238 = boost::coroutines::attributes());
239
240 /// Start a new stackful coroutine that executes on a given io_service.
241 /**
242 * This function is used to launch a new coroutine.
243 *
244 * @param io_service Identifies the io_service that will run the coroutine. The
245 * new coroutine is implicitly given its own strand within this io_service.
246 *
247 * @param function The coroutine function. The function must have the signature:
248 * @code void function(yield_context yield); @endcode
249 *
250 * @param attributes Boost.Coroutine attributes used to customise the coroutine.
251 */
252 template <typename Function>
253 void spawn(boost::asio::io_service& io_service,
254 BOOST_ASIO_MOVE_ARG(Function) function,
255 const boost::coroutines::attributes& attributes
256 = boost::coroutines::attributes());
257
258 /*@}*/
259
260 } // namespace asio
261 } // namespace boost
262
263 #include <boost/asio/detail/pop_options.hpp>
264
265 #include <boost/asio/impl/spawn.hpp>
266
267 #endif // BOOST_ASIO_SPAWN_HPP