]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/coroutine/include/boost/coroutine/detail/symmetric_coroutine_impl.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / coroutine / include / boost / coroutine / detail / symmetric_coroutine_impl.hpp
1
2 // Copyright Oliver Kowalke 2009.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #ifndef BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H
8 #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H
9
10 #include <boost/assert.hpp>
11 #include <boost/config.hpp>
12 #include <boost/cstdint.hpp>
13 #include <boost/utility.hpp>
14
15 #include <boost/coroutine/detail/config.hpp>
16 #include <boost/coroutine/detail/coroutine_context.hpp>
17 #include <boost/coroutine/detail/flags.hpp>
18 #include <boost/coroutine/detail/parameters.hpp>
19 #include <boost/coroutine/detail/preallocated.hpp>
20 #include <boost/coroutine/detail/trampoline.hpp>
21 #include <boost/coroutine/exceptions.hpp>
22 #include <boost/coroutine/stack_context.hpp>
23
24 #ifdef BOOST_HAS_ABI_HEADERS
25 # include BOOST_ABI_PREFIX
26 #endif
27
28 namespace boost {
29 namespace coroutines {
30 namespace detail {
31
32 template< typename R >
33 class symmetric_coroutine_impl : private noncopyable
34 {
35 public:
36 typedef parameters< R > param_type;
37
38 symmetric_coroutine_impl( preallocated const& palloc,
39 bool unwind) BOOST_NOEXCEPT :
40 flags_( 0),
41 caller_(),
42 callee_( trampoline< symmetric_coroutine_impl< R > >, palloc)
43 {
44 if ( unwind) flags_ |= flag_force_unwind;
45 }
46
47 virtual ~symmetric_coroutine_impl() {}
48
49 bool force_unwind() const BOOST_NOEXCEPT
50 { return 0 != ( flags_ & flag_force_unwind); }
51
52 bool unwind_requested() const BOOST_NOEXCEPT
53 { return 0 != ( flags_ & flag_unwind_stack); }
54
55 bool is_started() const BOOST_NOEXCEPT
56 { return 0 != ( flags_ & flag_started); }
57
58 bool is_running() const BOOST_NOEXCEPT
59 { return 0 != ( flags_ & flag_running); }
60
61 bool is_complete() const BOOST_NOEXCEPT
62 { return 0 != ( flags_ & flag_complete); }
63
64 void unwind_stack() BOOST_NOEXCEPT
65 {
66 if ( is_started() && ! is_complete() && force_unwind() )
67 {
68 flags_ |= flag_unwind_stack;
69 flags_ |= flag_running;
70 param_type to( unwind_t::force_unwind);
71 caller_.jump(
72 callee_,
73 & to);
74 flags_ &= ~flag_running;
75 flags_ &= ~flag_unwind_stack;
76
77 BOOST_ASSERT( is_complete() );
78 }
79 }
80
81 void resume( R r) BOOST_NOEXCEPT
82 {
83 param_type to( const_cast< R * >( & r), this);
84 resume_( & to);
85 }
86
87 R * yield()
88 {
89 BOOST_ASSERT( is_running() );
90 BOOST_ASSERT( ! is_complete() );
91
92 flags_ &= ~flag_running;
93 param_type to;
94 param_type * from(
95 static_cast< param_type * >(
96 callee_.jump(
97 caller_,
98 & to) ) );
99 flags_ |= flag_running;
100 if ( from->do_unwind) throw forced_unwind();
101 BOOST_ASSERT( from->data);
102 return from->data;
103 }
104
105 template< typename X >
106 R * yield_to( symmetric_coroutine_impl< X > * other, X x)
107 {
108 typename symmetric_coroutine_impl< X >::param_type to( & x, other);
109 return yield_to_( other, & to);
110 }
111
112 template< typename X >
113 R * yield_to( symmetric_coroutine_impl< X & > * other, X & x)
114 {
115 typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
116 return yield_to_( other, & to);
117 }
118
119 template< typename X >
120 R * yield_to( symmetric_coroutine_impl< X > * other)
121 {
122 typename symmetric_coroutine_impl< X >::param_type to( other);
123 return yield_to_( other, & to);
124 }
125
126 virtual void run( R *) BOOST_NOEXCEPT = 0;
127
128 virtual void destroy() = 0;
129
130 protected:
131 template< typename X >
132 friend class symmetric_coroutine_impl;
133
134 int flags_;
135 coroutine_context caller_;
136 coroutine_context callee_;
137
138 void resume_( param_type * to) BOOST_NOEXCEPT
139 {
140 BOOST_ASSERT( ! is_running() );
141 BOOST_ASSERT( ! is_complete() );
142
143 flags_ |= flag_running;
144 caller_.jump(
145 callee_,
146 to);
147 flags_ &= ~flag_running;
148 }
149
150 template< typename Other >
151 R * yield_to_( Other * other, typename Other::param_type * to)
152 {
153 BOOST_ASSERT( is_running() );
154 BOOST_ASSERT( ! is_complete() );
155 BOOST_ASSERT( ! other->is_running() );
156 BOOST_ASSERT( ! other->is_complete() );
157
158 other->caller_ = caller_;
159 flags_ &= ~flag_running;
160 param_type * from(
161 static_cast< param_type * >(
162 callee_.jump(
163 other->callee_,
164 to) ) );
165 flags_ |= flag_running;
166 if ( from->do_unwind) throw forced_unwind();
167 BOOST_ASSERT( from->data);
168 return from->data;
169 }
170 };
171
172 template< typename R >
173 class symmetric_coroutine_impl< R & > : private noncopyable
174 {
175 public:
176 typedef parameters< R & > param_type;
177
178 symmetric_coroutine_impl( preallocated const& palloc,
179 bool unwind) BOOST_NOEXCEPT :
180 flags_( 0),
181 caller_(),
182 callee_( trampoline< symmetric_coroutine_impl< R > >, palloc)
183 {
184 if ( unwind) flags_ |= flag_force_unwind;
185 }
186
187 virtual ~symmetric_coroutine_impl() {}
188
189 bool force_unwind() const BOOST_NOEXCEPT
190 { return 0 != ( flags_ & flag_force_unwind); }
191
192 bool unwind_requested() const BOOST_NOEXCEPT
193 { return 0 != ( flags_ & flag_unwind_stack); }
194
195 bool is_started() const BOOST_NOEXCEPT
196 { return 0 != ( flags_ & flag_started); }
197
198 bool is_running() const BOOST_NOEXCEPT
199 { return 0 != ( flags_ & flag_running); }
200
201 bool is_complete() const BOOST_NOEXCEPT
202 { return 0 != ( flags_ & flag_complete); }
203
204 void unwind_stack() BOOST_NOEXCEPT
205 {
206 if ( is_started() && ! is_complete() && force_unwind() )
207 {
208 flags_ |= flag_unwind_stack;
209 flags_ |= flag_running;
210 param_type to( unwind_t::force_unwind);
211 caller_.jump(
212 callee_,
213 & to);
214 flags_ &= ~flag_running;
215 flags_ &= ~flag_unwind_stack;
216
217 BOOST_ASSERT( is_complete() );
218 }
219 }
220
221 void resume( R & arg) BOOST_NOEXCEPT
222 {
223 param_type to( & arg, this);
224 resume_( & to);
225 }
226
227 R * yield()
228 {
229 BOOST_ASSERT( is_running() );
230 BOOST_ASSERT( ! is_complete() );
231
232 flags_ &= ~flag_running;
233 param_type to;
234 param_type * from(
235 static_cast< param_type * >(
236 callee_.jump(
237 caller_,
238 & to) ) );
239 flags_ |= flag_running;
240 if ( from->do_unwind) throw forced_unwind();
241 BOOST_ASSERT( from->data);
242 return from->data;
243 }
244
245 template< typename X >
246 R * yield_to( symmetric_coroutine_impl< X > * other, X x)
247 {
248 typename symmetric_coroutine_impl< X >::param_type to( & x, other);
249 return yield_to_( other, & to);
250 }
251
252 template< typename X >
253 R * yield_to( symmetric_coroutine_impl< X & > * other, X & x)
254 {
255 typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
256 return yield_to_( other, & to);
257 }
258
259 template< typename X >
260 R * yield_to( symmetric_coroutine_impl< X > * other)
261 {
262 typename symmetric_coroutine_impl< X >::param_type to( other);
263 return yield_to_( other, & to);
264 }
265
266 virtual void run( R *) BOOST_NOEXCEPT = 0;
267
268 virtual void destroy() = 0;
269
270 protected:
271 template< typename X >
272 friend class symmetric_coroutine_impl;
273
274 int flags_;
275 coroutine_context caller_;
276 coroutine_context callee_;
277
278 void resume_( param_type * to) BOOST_NOEXCEPT
279 {
280 BOOST_ASSERT( ! is_running() );
281 BOOST_ASSERT( ! is_complete() );
282
283 flags_ |= flag_running;
284 caller_.jump(
285 callee_,
286 to);
287 flags_ &= ~flag_running;
288 }
289
290 template< typename Other >
291 R * yield_to_( Other * other, typename Other::param_type * to)
292 {
293 BOOST_ASSERT( is_running() );
294 BOOST_ASSERT( ! is_complete() );
295 BOOST_ASSERT( ! other->is_running() );
296 BOOST_ASSERT( ! other->is_complete() );
297
298 other->caller_ = caller_;
299 flags_ &= ~flag_running;
300 param_type * from(
301 static_cast< param_type * >(
302 callee_.jump(
303 other->callee_,
304 to) ) );
305 flags_ |= flag_running;
306 if ( from->do_unwind) throw forced_unwind();
307 BOOST_ASSERT( from->data);
308 return from->data;
309 }
310 };
311
312 template<>
313 class symmetric_coroutine_impl< void > : private noncopyable
314 {
315 public:
316 typedef parameters< void > param_type;
317
318 symmetric_coroutine_impl( preallocated const& palloc,
319 bool unwind) BOOST_NOEXCEPT :
320 flags_( 0),
321 caller_(),
322 callee_( trampoline_void< symmetric_coroutine_impl< void > >, palloc)
323 {
324 if ( unwind) flags_ |= flag_force_unwind;
325 }
326
327 virtual ~symmetric_coroutine_impl() {}
328
329 inline bool force_unwind() const BOOST_NOEXCEPT
330 { return 0 != ( flags_ & flag_force_unwind); }
331
332 inline bool unwind_requested() const BOOST_NOEXCEPT
333 { return 0 != ( flags_ & flag_unwind_stack); }
334
335 inline bool is_started() const BOOST_NOEXCEPT
336 { return 0 != ( flags_ & flag_started); }
337
338 inline bool is_running() const BOOST_NOEXCEPT
339 { return 0 != ( flags_ & flag_running); }
340
341 inline bool is_complete() const BOOST_NOEXCEPT
342 { return 0 != ( flags_ & flag_complete); }
343
344 inline void unwind_stack() BOOST_NOEXCEPT
345 {
346 if ( is_started() && ! is_complete() && force_unwind() )
347 {
348 flags_ |= flag_unwind_stack;
349 flags_ |= flag_running;
350 param_type to( unwind_t::force_unwind);
351 caller_.jump(
352 callee_,
353 & to);
354 flags_ &= ~flag_running;
355 flags_ &= ~flag_unwind_stack;
356
357 BOOST_ASSERT( is_complete() );
358 }
359 }
360
361 inline void resume() BOOST_NOEXCEPT
362 {
363 BOOST_ASSERT( ! is_running() );
364 BOOST_ASSERT( ! is_complete() );
365
366 param_type to( this);
367 flags_ |= flag_running;
368 caller_.jump(
369 callee_,
370 & to);
371 flags_ &= ~flag_running;
372 }
373
374 inline void yield()
375 {
376 BOOST_ASSERT( is_running() );
377 BOOST_ASSERT( ! is_complete() );
378
379 flags_ &= ~flag_running;
380 param_type to;
381 param_type * from(
382 static_cast< param_type * >(
383 callee_.jump(
384 caller_,
385 & to) ) );
386 flags_ |= flag_running;
387 if ( from->do_unwind) throw forced_unwind();
388 }
389
390 template< typename X >
391 void yield_to( symmetric_coroutine_impl< X > * other, X x)
392 {
393 typename symmetric_coroutine_impl< X >::param_type to( & x, other);
394 yield_to_( other, & to);
395 }
396
397 template< typename X >
398 void yield_to( symmetric_coroutine_impl< X & > * other, X & x)
399 {
400 typename symmetric_coroutine_impl< X & >::param_type to( & x, other);
401 yield_to_( other, & to);
402 }
403
404 template< typename X >
405 void yield_to( symmetric_coroutine_impl< X > * other)
406 {
407 typename symmetric_coroutine_impl< X >::param_type to( other);
408 yield_to_( other, & to);
409 }
410
411 virtual void run() BOOST_NOEXCEPT = 0;
412
413 virtual void destroy() = 0;
414
415 protected:
416 template< typename X >
417 friend class symmetric_coroutine_impl;
418
419 int flags_;
420 coroutine_context caller_;
421 coroutine_context callee_;
422
423 template< typename Other >
424 void yield_to_( Other * other, typename Other::param_type * to)
425 {
426 BOOST_ASSERT( is_running() );
427 BOOST_ASSERT( ! is_complete() );
428 BOOST_ASSERT( ! other->is_running() );
429 BOOST_ASSERT( ! other->is_complete() );
430
431 other->caller_ = caller_;
432 flags_ &= ~flag_running;
433 param_type * from(
434 static_cast< param_type * >(
435 callee_.jump(
436 other->callee_,
437 to) ) );
438 flags_ |= flag_running;
439 if ( from->do_unwind) throw forced_unwind();
440 }
441 };
442
443 }}}
444
445 #ifdef BOOST_HAS_ABI_HEADERS
446 # include BOOST_ABI_SUFFIX
447 #endif
448
449 #endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_IMPL_H