]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/coroutine/include/boost/coroutine/detail/symmetric_coroutine_call.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / coroutine / include / boost / coroutine / detail / symmetric_coroutine_call.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_CALL_H
8 #define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H
9
10 #include <boost/assert.hpp>
11 #include <boost/config.hpp>
12 #include <boost/move/move.hpp>
13 #include <boost/utility/explicit_operator_bool.hpp>
14
15 #include <boost/coroutine/attributes.hpp>
16 #include <boost/coroutine/detail/config.hpp>
17 #include <boost/coroutine/detail/preallocated.hpp>
18 #include <boost/coroutine/detail/symmetric_coroutine_impl.hpp>
19 #include <boost/coroutine/detail/symmetric_coroutine_object.hpp>
20 #include <boost/coroutine/detail/symmetric_coroutine_yield.hpp>
21 #include <boost/coroutine/stack_allocator.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 Arg >
33 class symmetric_coroutine_call
34 {
35 private:
36 template< typename X >
37 friend class symmetric_coroutine_yield;
38
39 typedef symmetric_coroutine_impl< Arg > impl_type;
40
41 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
42
43 struct dummy {};
44
45 impl_type * impl_;
46
47 public:
48 typedef Arg value_type;
49 typedef symmetric_coroutine_yield< Arg > yield_type;
50
51 symmetric_coroutine_call() BOOST_NOEXCEPT :
52 impl_( 0)
53 {}
54
55 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
56 # ifdef BOOST_MSVC
57 typedef void ( * coroutine_fn)( yield_type &);
58
59 explicit symmetric_coroutine_call( coroutine_fn fn,
60 attributes const& attrs = attributes(),
61 stack_allocator stack_alloc = stack_allocator() ) :
62 impl_( 0)
63 {
64 // create a stack-context
65 stack_context stack_ctx;
66 // allocate the coroutine-stack
67 stack_alloc.allocate( stack_ctx, attrs.size);
68 BOOST_ASSERT( 0 != stack_ctx.sp);
69 // typedef of internal coroutine-type
70 typedef symmetric_coroutine_object< Arg, coroutine_fn, stack_allocator > object_t;
71 // reserve space on top of coroutine-stack for internal coroutine-type
72 std::size_t size = stack_ctx.size - sizeof( object_t);
73 BOOST_ASSERT( 0 != size);
74 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
75 BOOST_ASSERT( 0 != sp);
76 // placement new for internal coroutine
77 impl_ = new ( sp) object_t(
78 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
79 BOOST_ASSERT( impl_);
80 }
81
82 template< typename StackAllocator >
83 explicit symmetric_coroutine_call( coroutine_fn fn,
84 attributes const& attrs,
85 StackAllocator stack_alloc) :
86 impl_( 0)
87 {
88 // create a stack-context
89 stack_context stack_ctx;
90 // allocate the coroutine-stack
91 stack_alloc.allocate( stack_ctx, attrs.size);
92 BOOST_ASSERT( 0 != stack_ctx.sp);
93 // typedef of internal coroutine-type
94 typedef symmetric_coroutine_object< Arg, coroutine_fn, StackAllocator > object_t;
95 // reserve space on top of coroutine-stack for internal coroutine-type
96 std::size_t size = stack_ctx.size - sizeof( object_t);
97 BOOST_ASSERT( 0 != size);
98 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
99 BOOST_ASSERT( 0 != sp);
100 // placement new for internal coroutine
101 impl_ = new ( sp) object_t(
102 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
103 BOOST_ASSERT( impl_);
104 }
105 # endif
106 template< typename Fn >
107 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
108 attributes const& attrs = attributes(),
109 stack_allocator stack_alloc = stack_allocator() ) :
110 impl_( 0)
111 {
112 // create a stack-context
113 stack_context stack_ctx;
114 // allocate the coroutine-stack
115 stack_alloc.allocate( stack_ctx, attrs.size);
116 BOOST_ASSERT( 0 != stack_ctx.sp);
117 // typedef of internal coroutine-type
118 typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
119 // reserve space on top of coroutine-stack for internal coroutine-type
120 std::size_t size = stack_ctx.size - sizeof( object_t);
121 BOOST_ASSERT( 0 != size);
122 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
123 BOOST_ASSERT( 0 != sp);
124 // placement new for internal coroutine
125 impl_ = new ( sp) object_t(
126 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
127 BOOST_ASSERT( impl_);
128 }
129
130 template< typename Fn, typename StackAllocator >
131 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
132 attributes const& attrs,
133 StackAllocator stack_alloc) :
134 impl_( 0)
135 {
136 // create a stack-context
137 stack_context stack_ctx;
138 // allocate the coroutine-stack
139 stack_alloc.allocate( stack_ctx, attrs.size);
140 BOOST_ASSERT( 0 != stack_ctx.sp);
141 // typedef of internal coroutine-type
142 typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
143 // reserve space on top of coroutine-stack for internal coroutine-type
144 std::size_t size = stack_ctx.size - sizeof( object_t);
145 BOOST_ASSERT( 0 != size);
146 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
147 BOOST_ASSERT( 0 != sp);
148 // placement new for internal coroutine
149 impl_ = new ( sp) object_t(
150 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
151 BOOST_ASSERT( impl_);
152 }
153 #else
154 template< typename Fn >
155 explicit symmetric_coroutine_call( Fn fn,
156 attributes const& attrs = attributes(),
157 stack_allocator stack_alloc = stack_allocator() ) :
158 impl_( 0)
159 {
160 // create a stack-context
161 stack_context stack_ctx;
162 // allocate the coroutine-stack
163 stack_alloc.allocate( stack_ctx, attrs.size);
164 BOOST_ASSERT( 0 != stack_ctx.sp);
165 // typedef of internal coroutine-type
166 typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
167 // reserve space on top of coroutine-stack for internal coroutine-type
168 std::size_t size = stack_ctx.size - sizeof( object_t);
169 BOOST_ASSERT( 0 != size);
170 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
171 BOOST_ASSERT( 0 != sp);
172 // placement new for internal coroutine
173 impl_ = new ( sp) object_t(
174 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
175 BOOST_ASSERT( impl_);
176 }
177
178 template< typename Fn, typename StackAllocator >
179 explicit symmetric_coroutine_call( Fn fn,
180 attributes const& attrs,
181 StackAllocator stack_alloc) :
182 impl_( 0)
183 {
184 // create a stack-context
185 stack_context stack_ctx;
186 // allocate the coroutine-stack
187 stack_alloc.allocate( stack_ctx, attrs.size);
188 BOOST_ASSERT( 0 != stack_ctx.sp);
189 // typedef of internal coroutine-type
190 typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
191 // reserve space on top of coroutine-stack for internal coroutine-type
192 std::size_t size = stack_ctx.size - sizeof( object_t);
193 BOOST_ASSERT( 0 != size);
194 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
195 BOOST_ASSERT( 0 != sp);
196 // placement new for internal coroutine
197 impl_ = new ( sp) object_t(
198 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
199 BOOST_ASSERT( impl_);
200 }
201
202 template< typename Fn >
203 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
204 attributes const& attrs = attributes(),
205 stack_allocator stack_alloc = stack_allocator() ) :
206 impl_( 0)
207 {
208 // create a stack-context
209 stack_context stack_ctx;
210 // allocate the coroutine-stack
211 stack_alloc.allocate( stack_ctx, attrs.size);
212 BOOST_ASSERT( 0 != stack_ctx.sp);
213 // typedef of internal coroutine-type
214 typedef symmetric_coroutine_object< Arg, Fn, stack_allocator > object_t;
215 // reserve space on top of coroutine-stack for internal coroutine-type
216 std::size_t size = stack_ctx.size - sizeof( object_t);
217 BOOST_ASSERT( 0 != size);
218 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
219 BOOST_ASSERT( 0 != sp);
220 // placement new for internal coroutine
221 impl_ = new ( sp) object_t(
222 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
223 BOOST_ASSERT( impl_);
224 }
225
226 template< typename Fn, typename StackAllocator >
227 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
228 attributes const& attrs,
229 StackAllocator stack_alloc) :
230 impl_( 0)
231 {
232 // create a stack-context
233 stack_context stack_ctx;
234 // allocate the coroutine-stack
235 stack_alloc.allocate( stack_ctx, attrs.size);
236 BOOST_ASSERT( 0 != stack_ctx.sp);
237 // typedef of internal coroutine-type
238 typedef symmetric_coroutine_object< Arg, Fn, StackAllocator > object_t;
239 // reserve space on top of coroutine-stack for internal coroutine-type
240 std::size_t size = stack_ctx.size - sizeof( object_t);
241 BOOST_ASSERT( 0 != size);
242 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
243 BOOST_ASSERT( 0 != sp);
244 // placement new for internal coroutine
245 impl_ = new ( sp) object_t(
246 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
247 BOOST_ASSERT( impl_);
248 }
249 #endif
250
251 ~symmetric_coroutine_call()
252 {
253 if ( 0 != impl_)
254 {
255 impl_->destroy();
256 impl_ = 0;
257 }
258 }
259
260 symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
261 impl_( 0)
262 { swap( other); }
263
264 symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
265 {
266 symmetric_coroutine_call tmp( boost::move( other) );
267 swap( tmp);
268 return * this;
269 }
270
271 BOOST_EXPLICIT_OPERATOR_BOOL();
272
273 bool operator!() const BOOST_NOEXCEPT
274 { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
275
276 void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
277 { std::swap( impl_, other.impl_); }
278
279 symmetric_coroutine_call & operator()( Arg arg) BOOST_NOEXCEPT
280 {
281 BOOST_ASSERT( * this);
282
283 impl_->resume( arg);
284 return * this;
285 }
286 };
287
288 template< typename Arg >
289 class symmetric_coroutine_call< Arg & >
290 {
291 private:
292 template< typename X >
293 friend class symmetric_coroutine_yield;
294
295 typedef symmetric_coroutine_impl< Arg & > impl_type;
296
297 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
298
299 struct dummy {};
300
301 impl_type * impl_;
302
303 public:
304 typedef Arg value_type;
305 typedef symmetric_coroutine_yield< Arg & > yield_type;
306
307 symmetric_coroutine_call() BOOST_NOEXCEPT :
308 impl_( 0)
309 {}
310
311 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
312 # ifdef BOOST_MSVC
313 typedef void ( * coroutine_fn)( yield_type &);
314
315 explicit symmetric_coroutine_call( coroutine_fn fn,
316 attributes const& attrs = attributes(),
317 stack_allocator stack_alloc = stack_allocator() ) :
318 impl_( 0)
319 {
320 // create a stack-context
321 stack_context stack_ctx;
322 // allocate the coroutine-stack
323 stack_alloc.allocate( stack_ctx, attrs.size);
324 BOOST_ASSERT( 0 != stack_ctx.sp);
325 // typedef of internal coroutine-type
326 typedef symmetric_coroutine_object< Arg &, coroutine_fn, stack_allocator > object_t;
327 // reserve space on top of coroutine-stack for internal coroutine-type
328 std::size_t size = stack_ctx.size - sizeof( object_t);
329 BOOST_ASSERT( 0 != size);
330 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
331 BOOST_ASSERT( 0 != sp);
332 // placement new for internal coroutine
333 impl_ = new ( sp) object_t(
334 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
335 BOOST_ASSERT( impl_);
336 }
337
338 template< typename StackAllocator >
339 explicit symmetric_coroutine_call( coroutine_fn fn,
340 attributes const& attrs,
341 StackAllocator stack_alloc) :
342 impl_( 0)
343 {
344 // create a stack-context
345 stack_context stack_ctx;
346 // allocate the coroutine-stack
347 stack_alloc.allocate( stack_ctx, attrs.size);
348 BOOST_ASSERT( 0 != stack_ctx.sp);
349 // typedef of internal coroutine-type
350 typedef symmetric_coroutine_object< Arg &, coroutine_fn, StackAllocator > object_t;
351 // reserve space on top of coroutine-stack for internal coroutine-type
352 std::size_t size = stack_ctx.size - sizeof( object_t);
353 BOOST_ASSERT( 0 != size);
354 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
355 BOOST_ASSERT( 0 != sp);
356 // placement new for internal coroutine
357 impl_ = new ( sp) object_t(
358 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
359 BOOST_ASSERT( impl_);
360 }
361 # endif
362 template< typename Fn >
363 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
364 attributes const& attrs = attributes(),
365 stack_allocator stack_alloc = stack_allocator() ) :
366 impl_( 0)
367 {
368 // create a stack-context
369 stack_context stack_ctx;
370 // allocate the coroutine-stack
371 stack_alloc.allocate( stack_ctx, attrs.size);
372 BOOST_ASSERT( 0 != stack_ctx.sp);
373 // typedef of internal coroutine-type
374 typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
375 // reserve space on top of coroutine-stack for internal coroutine-type
376 std::size_t size = stack_ctx.size - sizeof( object_t);
377 BOOST_ASSERT( 0 != size);
378 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
379 BOOST_ASSERT( 0 != sp);
380 // placement new for internal coroutine
381 impl_ = new ( sp) object_t(
382 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
383 BOOST_ASSERT( impl_);
384 }
385
386 template< typename Fn, typename StackAllocator >
387 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
388 attributes const& attrs,
389 StackAllocator stack_alloc) :
390 impl_( 0)
391 {
392 // create a stack-context
393 stack_context stack_ctx;
394 // allocate the coroutine-stack
395 stack_alloc.allocate( stack_ctx, attrs.size);
396 BOOST_ASSERT( 0 != stack_ctx.sp);
397 // typedef of internal coroutine-type
398 typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
399 // reserve space on top of coroutine-stack for internal coroutine-type
400 std::size_t size = stack_ctx.size - sizeof( object_t);
401 BOOST_ASSERT( 0 != size);
402 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
403 BOOST_ASSERT( 0 != sp);
404 // placement new for internal coroutine
405 impl_ = new ( sp) object_t(
406 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
407 BOOST_ASSERT( impl_);
408 }
409 #else
410 template< typename Fn >
411 explicit symmetric_coroutine_call( Fn fn,
412 attributes const& attrs = attributes(),
413 stack_allocator stack_alloc = stack_allocator() ) :
414 impl_( 0)
415 {
416 // create a stack-context
417 stack_context stack_ctx;
418 // allocate the coroutine-stack
419 stack_alloc.allocate( stack_ctx, attrs.size);
420 BOOST_ASSERT( 0 != stack_ctx.sp);
421 // typedef of internal coroutine-type
422 typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
423 // reserve space on top of coroutine-stack for internal coroutine-type
424 std::size_t size = stack_ctx.size - sizeof( object_t);
425 BOOST_ASSERT( 0 != size);
426 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
427 BOOST_ASSERT( 0 != sp);
428 // placement new for internal coroutine
429 impl_ = new ( sp) object_t(
430 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
431 BOOST_ASSERT( impl_);
432 }
433
434 template< typename Fn, typename StackAllocator >
435 explicit symmetric_coroutine_call( Fn fn,
436 attributes const& attrs,
437 StackAllocator stack_alloc) :
438 impl_( 0)
439 {
440 // create a stack-context
441 stack_context stack_ctx;
442 // allocate the coroutine-stack
443 stack_alloc.allocate( stack_ctx, attrs.size);
444 BOOST_ASSERT( 0 != stack_ctx.sp);
445 // typedef of internal coroutine-type
446 typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
447 // reserve space on top of coroutine-stack for internal coroutine-type
448 std::size_t size = stack_ctx.size - sizeof( object_t);
449 BOOST_ASSERT( 0 != size);
450 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
451 BOOST_ASSERT( 0 != sp);
452 // placement new for internal coroutine
453 impl_ = new ( sp) object_t(
454 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
455 BOOST_ASSERT( impl_);
456 }
457
458 template< typename Fn >
459 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
460 attributes const& attrs = attributes(),
461 stack_allocator stack_alloc = stack_allocator() ) :
462 impl_( 0)
463 {
464 // create a stack-context
465 stack_context stack_ctx;
466 // allocate the coroutine-stack
467 stack_alloc.allocate( stack_ctx, attrs.size);
468 BOOST_ASSERT( 0 != stack_ctx.sp);
469 // typedef of internal coroutine-type
470 typedef symmetric_coroutine_object< Arg &, Fn, stack_allocator > object_t;
471 // reserve space on top of coroutine-stack for internal coroutine-type
472 std::size_t size = stack_ctx.size - sizeof( object_t);
473 BOOST_ASSERT( 0 != size);
474 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
475 BOOST_ASSERT( 0 != sp);
476 // placement new for internal coroutine
477 impl_ = new ( sp) object_t(
478 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
479 BOOST_ASSERT( impl_);
480 }
481
482 template< typename Fn, typename StackAllocator >
483 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
484 attributes const& attrs,
485 StackAllocator stack_alloc) :
486 impl_( 0)
487 {
488 // create a stack-context
489 stack_context stack_ctx;
490 // allocate the coroutine-stack
491 stack_alloc.allocate( stack_ctx, attrs.size);
492 BOOST_ASSERT( 0 != stack_ctx.sp);
493 // typedef of internal coroutine-type
494 typedef symmetric_coroutine_object< Arg &, Fn, StackAllocator > object_t;
495 // reserve space on top of coroutine-stack for internal coroutine-type
496 std::size_t size = stack_ctx.size - sizeof( object_t);
497 BOOST_ASSERT( 0 != size);
498 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
499 BOOST_ASSERT( 0 != sp);
500 // placement new for internal coroutine
501 impl_ = new ( sp) object_t(
502 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
503 BOOST_ASSERT( impl_);
504 }
505 #endif
506
507 ~symmetric_coroutine_call()
508 {
509 if ( 0 != impl_)
510 {
511 impl_->destroy();
512 impl_ = 0;
513 }
514 }
515
516 symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
517 impl_( 0)
518 { swap( other); }
519
520 symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
521 {
522 symmetric_coroutine_call tmp( boost::move( other) );
523 swap( tmp);
524 return * this;
525 }
526
527 BOOST_EXPLICIT_OPERATOR_BOOL();
528
529 bool operator!() const BOOST_NOEXCEPT
530 { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
531
532 void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
533 { std::swap( impl_, other.impl_); }
534
535 symmetric_coroutine_call & operator()( Arg & arg) BOOST_NOEXCEPT
536 {
537 BOOST_ASSERT( * this);
538
539 impl_->resume( arg);
540 return * this;
541 }
542 };
543
544 template<>
545 class symmetric_coroutine_call< void >
546 {
547 private:
548 template< typename X >
549 friend class symmetric_coroutine_yield;
550
551 typedef symmetric_coroutine_impl< void > impl_type;
552
553 BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_call)
554
555 struct dummy {};
556
557 impl_type * impl_;
558
559 public:
560 typedef void value_type;
561 typedef symmetric_coroutine_yield< void > yield_type;
562
563 symmetric_coroutine_call() BOOST_NOEXCEPT :
564 impl_( 0)
565 {}
566
567 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
568 # ifdef BOOST_MSVC
569 typedef void ( * coroutine_fn)( yield_type &);
570
571 explicit symmetric_coroutine_call( coroutine_fn fn,
572 attributes const& attrs = attributes(),
573 stack_allocator stack_alloc = stack_allocator() ) :
574 impl_( 0)
575 {
576 // create a stack-context
577 stack_context stack_ctx;
578 // allocate the coroutine-stack
579 stack_alloc.allocate( stack_ctx, attrs.size);
580 BOOST_ASSERT( 0 != stack_ctx.sp);
581 // typedef of internal coroutine-type
582 typedef symmetric_coroutine_object< void, coroutine_fn, stack_allocator > object_t;
583 // reserve space on top of coroutine-stack for internal coroutine-type
584 std::size_t size = stack_ctx.size - sizeof( object_t);
585 BOOST_ASSERT( 0 != size);
586 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
587 BOOST_ASSERT( 0 != sp);
588 // placement new for internal coroutine
589 impl_ = new ( sp) object_t(
590 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
591 BOOST_ASSERT( impl_);
592 }
593
594 template< typename StackAllocator >
595 explicit symmetric_coroutine_call( coroutine_fn fn,
596 attributes const& attrs,
597 StackAllocator stack_alloc) :
598 impl_( 0)
599 {
600 // create a stack-context
601 stack_context stack_ctx;
602 // allocate the coroutine-stack
603 stack_alloc.allocate( stack_ctx, attrs.size);
604 BOOST_ASSERT( 0 != stack_ctx.sp);
605 // typedef of internal coroutine-type
606 typedef symmetric_coroutine_object< void, coroutine_fn, StackAllocator > object_t;
607 // reserve space on top of coroutine-stack for internal coroutine-type
608 std::size_t size = stack_ctx.size - sizeof( object_t);
609 BOOST_ASSERT( 0 != size);
610 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
611 BOOST_ASSERT( 0 != sp);
612 // placement new for internal coroutine
613 impl_ = new ( sp) object_t(
614 boost::forward< coroutine_fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
615 BOOST_ASSERT( impl_);
616 }
617 # endif
618 template< typename Fn >
619 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
620 attributes const& attrs = attributes(),
621 stack_allocator stack_alloc = stack_allocator() ) :
622 impl_( 0)
623 {
624 // create a stack-context
625 stack_context stack_ctx;
626 // allocate the coroutine-stack
627 stack_alloc.allocate( stack_ctx, attrs.size);
628 BOOST_ASSERT( 0 != stack_ctx.sp);
629 // typedef of internal coroutine-type
630 typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
631 // reserve space on top of coroutine-stack for internal coroutine-type
632 std::size_t size = stack_ctx.size - sizeof( object_t);
633 BOOST_ASSERT( 0 != size);
634 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
635 BOOST_ASSERT( 0 != sp);
636 // placement new for internal coroutine
637 impl_ = new ( sp) object_t(
638 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
639 BOOST_ASSERT( impl_);
640 }
641
642 template< typename Fn, typename StackAllocator >
643 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
644 attributes const& attrs,
645 StackAllocator stack_alloc) :
646 impl_( 0)
647 {
648 // create a stack-context
649 stack_context stack_ctx;
650 // allocate the coroutine-stack
651 stack_alloc.allocate( stack_ctx, attrs.size);
652 BOOST_ASSERT( 0 != stack_ctx.sp);
653 // typedef of internal coroutine-type
654 typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
655 // reserve space on top of coroutine-stack for internal coroutine-type
656 std::size_t size = stack_ctx.size - sizeof( object_t);
657 BOOST_ASSERT( 0 != size);
658 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
659 BOOST_ASSERT( 0 != sp);
660 // placement new for internal coroutine
661 impl_ = new ( sp) object_t(
662 boost::forward< Fn >( fn), attrs, preallocated( sp, size, stack_ctx), stack_alloc);
663 BOOST_ASSERT( impl_);
664 }
665 #else
666 template< typename Fn >
667 explicit symmetric_coroutine_call( Fn fn,
668 attributes const& attrs = attributes(),
669 stack_allocator stack_alloc = stack_allocator() ) :
670 impl_( 0)
671 {
672 // create a stack-context
673 stack_context stack_ctx;
674 // allocate the coroutine-stack
675 stack_alloc.allocate( stack_ctx, attrs.size);
676 BOOST_ASSERT( 0 != stack_ctx.sp);
677 // typedef of internal coroutine-type
678 typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
679 // reserve space on top of coroutine-stack for internal coroutine-type
680 std::size_t size = stack_ctx.size - sizeof( object_t);
681 BOOST_ASSERT( 0 != size);
682 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
683 BOOST_ASSERT( 0 != sp);
684 // placement new for internal coroutine
685 impl_ = new ( sp) object_t(
686 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
687 BOOST_ASSERT( impl_);
688 }
689
690 template< typename Fn, typename StackAllocator >
691 explicit symmetric_coroutine_call( Fn fn,
692 attributes const& attrs,
693 StackAllocator stack_alloc) :
694 impl_( 0)
695 {
696 // create a stack-context
697 stack_context stack_ctx;
698 // allocate the coroutine-stack
699 stack_alloc.allocate( stack_ctx, attrs.size);
700 BOOST_ASSERT( 0 != stack_ctx.sp);
701 // typedef of internal coroutine-type
702 typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
703 // reserve space on top of coroutine-stack for internal coroutine-type
704 std::size_t size = stack_ctx.size - sizeof( object_t);
705 BOOST_ASSERT( 0 != size);
706 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
707 BOOST_ASSERT( 0 != sp);
708 // placement new for internal coroutine
709 impl_ = new ( sp) object_t(
710 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
711 BOOST_ASSERT( impl_);
712 }
713
714 template< typename Fn >
715 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
716 attributes const& attrs = attributes(),
717 stack_allocator stack_alloc = stack_allocator() ) :
718 impl_( 0)
719 {
720 // create a stack-context
721 stack_context stack_ctx;
722 // allocate the coroutine-stack
723 stack_alloc.allocate( stack_ctx, attrs.size);
724 BOOST_ASSERT( 0 != stack_ctx.sp);
725 // typedef of internal coroutine-type
726 typedef symmetric_coroutine_object< void, Fn, stack_allocator > object_t;
727 // reserve space on top of coroutine-stack for internal coroutine-type
728 std::size_t size = stack_ctx.size - sizeof( object_t);
729 BOOST_ASSERT( 0 != size);
730 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
731 BOOST_ASSERT( 0 != sp);
732 // placement new for internal coroutine
733 impl_ = new ( sp) object_t(
734 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
735 BOOST_ASSERT( impl_);
736 }
737
738 template< typename Fn, typename StackAllocator >
739 explicit symmetric_coroutine_call( BOOST_RV_REF( Fn) fn,
740 attributes const& attrs,
741 StackAllocator stack_alloc) :
742 impl_( 0)
743 {
744 // create a stack-context
745 stack_context stack_ctx;
746 // allocate the coroutine-stack
747 stack_alloc.allocate( stack_ctx, attrs.size);
748 BOOST_ASSERT( 0 != stack_ctx.sp);
749 // typedef of internal coroutine-type
750 typedef symmetric_coroutine_object< void, Fn, StackAllocator > object_t;
751 // reserve space on top of coroutine-stack for internal coroutine-type
752 std::size_t size = stack_ctx.size - sizeof( object_t);
753 BOOST_ASSERT( 0 != size);
754 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
755 BOOST_ASSERT( 0 != sp);
756 // placement new for internal coroutine
757 impl_ = new ( sp) object_t(
758 fn, attrs, preallocated( sp, size, stack_ctx), stack_alloc);
759 BOOST_ASSERT( impl_);
760 }
761 #endif
762
763 ~symmetric_coroutine_call()
764 {
765 if ( 0 != impl_)
766 {
767 impl_->destroy();
768 impl_ = 0;
769 }
770 }
771
772 inline symmetric_coroutine_call( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT :
773 impl_( 0)
774 { swap( other); }
775
776 inline symmetric_coroutine_call & operator=( BOOST_RV_REF( symmetric_coroutine_call) other) BOOST_NOEXCEPT
777 {
778 symmetric_coroutine_call tmp( boost::move( other) );
779 swap( tmp);
780 return * this;
781 }
782
783 BOOST_EXPLICIT_OPERATOR_BOOL();
784
785 inline bool operator!() const BOOST_NOEXCEPT
786 { return 0 == impl_ || impl_->is_complete() || impl_->is_running(); }
787
788 inline void swap( symmetric_coroutine_call & other) BOOST_NOEXCEPT
789 { std::swap( impl_, other.impl_); }
790
791 inline symmetric_coroutine_call & operator()() BOOST_NOEXCEPT
792 {
793 BOOST_ASSERT( * this);
794
795 impl_->resume();
796 return * this;
797 }
798 };
799
800 template< typename Arg >
801 void swap( symmetric_coroutine_call< Arg > & l,
802 symmetric_coroutine_call< Arg > & r)
803 { l.swap( r); }
804
805 }}}
806
807 #ifdef BOOST_HAS_ABI_HEADERS
808 # include BOOST_ABI_SUFFIX
809 #endif
810
811 #endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_CALL_H