comparison DEPENDENCIES/generic/include/boost/asio/impl/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 // impl/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_IMPL_SPAWN_HPP
12 #define BOOST_ASIO_IMPL_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/asio/async_result.hpp>
20 #include <boost/asio/detail/handler_alloc_helpers.hpp>
21 #include <boost/asio/detail/handler_cont_helpers.hpp>
22 #include <boost/asio/detail/handler_invoke_helpers.hpp>
23 #include <boost/asio/detail/noncopyable.hpp>
24 #include <boost/asio/detail/shared_ptr.hpp>
25 #include <boost/asio/handler_type.hpp>
26
27 #include <boost/asio/detail/push_options.hpp>
28
29 namespace boost {
30 namespace asio {
31 namespace detail {
32
33 template <typename Handler, typename T>
34 class coro_handler
35 {
36 public:
37 coro_handler(basic_yield_context<Handler> ctx)
38 : coro_(ctx.coro_.lock()),
39 ca_(ctx.ca_),
40 handler_(ctx.handler_),
41 ec_(ctx.ec_),
42 value_(0)
43 {
44 }
45
46 void operator()(T value)
47 {
48 *ec_ = boost::system::error_code();
49 *value_ = value;
50 (*coro_)();
51 }
52
53 void operator()(boost::system::error_code ec, T value)
54 {
55 *ec_ = ec;
56 *value_ = value;
57 (*coro_)();
58 }
59
60 //private:
61 shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
62 typename basic_yield_context<Handler>::caller_type& ca_;
63 Handler& handler_;
64 boost::system::error_code* ec_;
65 T* value_;
66 };
67
68 template <typename Handler>
69 class coro_handler<Handler, void>
70 {
71 public:
72 coro_handler(basic_yield_context<Handler> ctx)
73 : coro_(ctx.coro_.lock()),
74 ca_(ctx.ca_),
75 handler_(ctx.handler_),
76 ec_(ctx.ec_)
77 {
78 }
79
80 void operator()()
81 {
82 *ec_ = boost::system::error_code();
83 (*coro_)();
84 }
85
86 void operator()(boost::system::error_code ec)
87 {
88 *ec_ = ec;
89 (*coro_)();
90 }
91
92 //private:
93 shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
94 typename basic_yield_context<Handler>::caller_type& ca_;
95 Handler& handler_;
96 boost::system::error_code* ec_;
97 };
98
99 template <typename Handler, typename T>
100 inline void* asio_handler_allocate(std::size_t size,
101 coro_handler<Handler, T>* this_handler)
102 {
103 return boost_asio_handler_alloc_helpers::allocate(
104 size, this_handler->handler_);
105 }
106
107 template <typename Handler, typename T>
108 inline void asio_handler_deallocate(void* pointer, std::size_t size,
109 coro_handler<Handler, T>* this_handler)
110 {
111 boost_asio_handler_alloc_helpers::deallocate(
112 pointer, size, this_handler->handler_);
113 }
114
115 template <typename Handler, typename T>
116 inline bool asio_handler_is_continuation(coro_handler<Handler, T>*)
117 {
118 return true;
119 }
120
121 template <typename Function, typename Handler, typename T>
122 inline void asio_handler_invoke(Function& function,
123 coro_handler<Handler, T>* this_handler)
124 {
125 boost_asio_handler_invoke_helpers::invoke(
126 function, this_handler->handler_);
127 }
128
129 template <typename Function, typename Handler, typename T>
130 inline void asio_handler_invoke(const Function& function,
131 coro_handler<Handler, T>* this_handler)
132 {
133 boost_asio_handler_invoke_helpers::invoke(
134 function, this_handler->handler_);
135 }
136
137 } // namespace detail
138
139 #if !defined(GENERATING_DOCUMENTATION)
140
141 template <typename Handler, typename ReturnType>
142 struct handler_type<basic_yield_context<Handler>, ReturnType()>
143 {
144 typedef detail::coro_handler<Handler, void> type;
145 };
146
147 template <typename Handler, typename ReturnType, typename Arg1>
148 struct handler_type<basic_yield_context<Handler>, ReturnType(Arg1)>
149 {
150 typedef detail::coro_handler<Handler, Arg1> type;
151 };
152
153 template <typename Handler, typename ReturnType>
154 struct handler_type<basic_yield_context<Handler>,
155 ReturnType(boost::system::error_code)>
156 {
157 typedef detail::coro_handler<Handler, void> type;
158 };
159
160 template <typename Handler, typename ReturnType, typename Arg2>
161 struct handler_type<basic_yield_context<Handler>,
162 ReturnType(boost::system::error_code, Arg2)>
163 {
164 typedef detail::coro_handler<Handler, Arg2> type;
165 };
166
167 template <typename Handler, typename T>
168 class async_result<detail::coro_handler<Handler, T> >
169 {
170 public:
171 typedef T type;
172
173 explicit async_result(detail::coro_handler<Handler, T>& h)
174 : ca_(h.ca_)
175 {
176 out_ec_ = h.ec_;
177 if (!out_ec_) h.ec_ = &ec_;
178 h.value_ = &value_;
179 }
180
181 type get()
182 {
183 ca_();
184 if (!out_ec_ && ec_) throw boost::system::system_error(ec_);
185 return value_;
186 }
187
188 private:
189 typename basic_yield_context<Handler>::caller_type& ca_;
190 boost::system::error_code* out_ec_;
191 boost::system::error_code ec_;
192 type value_;
193 };
194
195 template <typename Handler>
196 class async_result<detail::coro_handler<Handler, void> >
197 {
198 public:
199 typedef void type;
200
201 explicit async_result(detail::coro_handler<Handler, void>& h)
202 : ca_(h.ca_)
203 {
204 out_ec_ = h.ec_;
205 if (!out_ec_) h.ec_ = &ec_;
206 }
207
208 void get()
209 {
210 ca_();
211 if (!out_ec_ && ec_) throw boost::system::system_error(ec_);
212 }
213
214 private:
215 typename basic_yield_context<Handler>::caller_type& ca_;
216 boost::system::error_code* out_ec_;
217 boost::system::error_code ec_;
218 };
219
220 namespace detail {
221
222 template <typename Handler, typename Function>
223 struct spawn_data : private noncopyable
224 {
225 spawn_data(BOOST_ASIO_MOVE_ARG(Handler) handler,
226 bool call_handler, BOOST_ASIO_MOVE_ARG(Function) function)
227 : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
228 call_handler_(call_handler),
229 function_(BOOST_ASIO_MOVE_CAST(Function)(function))
230 {
231 }
232
233 weak_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
234 Handler handler_;
235 bool call_handler_;
236 Function function_;
237 };
238
239 template <typename Handler, typename Function>
240 struct coro_entry_point
241 {
242 void operator()(typename basic_yield_context<Handler>::caller_type& ca)
243 {
244 shared_ptr<spawn_data<Handler, Function> > data(data_);
245 ca(); // Yield until coroutine pointer has been initialised.
246 const basic_yield_context<Handler> yield(
247 data->coro_, ca, data->handler_);
248 (data->function_)(yield);
249 if (data->call_handler_)
250 (data->handler_)();
251 }
252
253 shared_ptr<spawn_data<Handler, Function> > data_;
254 };
255
256 template <typename Handler, typename Function>
257 struct spawn_helper
258 {
259 void operator()()
260 {
261 typedef typename basic_yield_context<Handler>::callee_type callee_type;
262 coro_entry_point<Handler, Function> entry_point = { data_ };
263 shared_ptr<callee_type> coro(new callee_type(entry_point, attributes_));
264 data_->coro_ = coro;
265 (*coro)();
266 }
267
268 shared_ptr<spawn_data<Handler, Function> > data_;
269 boost::coroutines::attributes attributes_;
270 };
271
272 inline void default_spawn_handler() {}
273
274 } // namespace detail
275
276 template <typename Handler, typename Function>
277 void spawn(BOOST_ASIO_MOVE_ARG(Handler) handler,
278 BOOST_ASIO_MOVE_ARG(Function) function,
279 const boost::coroutines::attributes& attributes)
280 {
281 detail::spawn_helper<Handler, Function> helper;
282 helper.data_.reset(
283 new detail::spawn_data<Handler, Function>(
284 BOOST_ASIO_MOVE_CAST(Handler)(handler), true,
285 BOOST_ASIO_MOVE_CAST(Function)(function)));
286 helper.attributes_ = attributes;
287 boost_asio_handler_invoke_helpers::invoke(helper, helper.data_->handler_);
288 }
289
290 template <typename Handler, typename Function>
291 void spawn(basic_yield_context<Handler> ctx,
292 BOOST_ASIO_MOVE_ARG(Function) function,
293 const boost::coroutines::attributes& attributes)
294 {
295 Handler handler(ctx.handler_); // Explicit copy that might be moved from.
296 detail::spawn_helper<Handler, Function> helper;
297 helper.data_.reset(
298 new detail::spawn_data<Handler, Function>(
299 BOOST_ASIO_MOVE_CAST(Handler)(handler), false,
300 BOOST_ASIO_MOVE_CAST(Function)(function)));
301 helper.attributes_ = attributes;
302 boost_asio_handler_invoke_helpers::invoke(helper, helper.data_->handler_);
303 }
304
305 template <typename Function>
306 void spawn(boost::asio::io_service::strand strand,
307 BOOST_ASIO_MOVE_ARG(Function) function,
308 const boost::coroutines::attributes& attributes)
309 {
310 boost::asio::spawn(strand.wrap(&detail::default_spawn_handler),
311 BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
312 }
313
314 template <typename Function>
315 void spawn(boost::asio::io_service& io_service,
316 BOOST_ASIO_MOVE_ARG(Function) function,
317 const boost::coroutines::attributes& attributes)
318 {
319 boost::asio::spawn(boost::asio::io_service::strand(io_service),
320 BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
321 }
322
323 #endif // !defined(GENERATING_DOCUMENTATION)
324
325 } // namespace asio
326 } // namespace boost
327
328 #include <boost/asio/detail/pop_options.hpp>
329
330 #endif // BOOST_ASIO_IMPL_SPAWN_HPP