]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/coroutine/asymmetric_coroutine.hpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / boost / coroutine / asymmetric_coroutine.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_ASYMMETRIC_COROUTINE_H
8 #define BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H
9
10 #ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING
11 # if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
12 # pragma message ("Warning: Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING.")
13 # elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
14 # warning "Boost.Coroutine is now deprecated. Please switch to Boost.Coroutine2. To disable this warning message, define BOOST_COROUTINES_NO_DEPRECATION_WARNING."
15 # endif
16 #endif
17
18 #include <cstddef>
19 #include <iterator>
20 #include <memory>
21
22 #include <boost/assert.hpp>
23 #include <boost/config.hpp>
24 #include <boost/move/move.hpp>
25 #include <boost/range.hpp>
26 #include <boost/throw_exception.hpp>
27 #include <boost/utility/explicit_operator_bool.hpp>
28
29 #include <boost/coroutine/attributes.hpp>
30 #include <boost/coroutine/detail/config.hpp>
31 #include <boost/coroutine/detail/coroutine_context.hpp>
32 #include <boost/coroutine/detail/parameters.hpp>
33 #include <boost/coroutine/exceptions.hpp>
34 #include <boost/coroutine/stack_allocator.hpp>
35 #include <boost/coroutine/detail/pull_coroutine_impl.hpp>
36 #include <boost/coroutine/detail/pull_coroutine_object.hpp>
37 #include <boost/coroutine/detail/pull_coroutine_synthesized.hpp>
38 #include <boost/coroutine/detail/push_coroutine_impl.hpp>
39 #include <boost/coroutine/detail/push_coroutine_object.hpp>
40 #include <boost/coroutine/detail/push_coroutine_synthesized.hpp>
41 #include <boost/coroutine/stack_context.hpp>
42
43 #ifdef BOOST_HAS_ABI_HEADERS
44 # include BOOST_ABI_PREFIX
45 #endif
46
47 namespace boost {
48 namespace coroutines {
49
50 template< typename R >
51 class pull_coroutine;
52
53 template< typename Arg >
54 class push_coroutine
55 {
56 private:
57 template< typename V, typename X, typename Y, typename Z >
58 friend class detail::pull_coroutine_object;
59
60 typedef detail::push_coroutine_impl< Arg > impl_type;
61 typedef detail::push_coroutine_synthesized< Arg > synth_type;
62 typedef detail::parameters< Arg > param_type;
63
64 struct dummy {};
65
66 impl_type * impl_;
67
68 BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
69
70 explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
71 impl_( & impl)
72 { BOOST_ASSERT( impl_); }
73
74 public:
75 push_coroutine() BOOST_NOEXCEPT :
76 impl_( 0)
77 {}
78
79 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
80 # ifdef BOOST_MSVC
81 typedef void ( * coroutine_fn)( pull_coroutine< Arg > &);
82
83 explicit push_coroutine( coroutine_fn,
84 attributes const& = attributes() );
85
86 template< typename StackAllocator >
87 explicit push_coroutine( coroutine_fn,
88 attributes const&,
89 StackAllocator);
90 # endif
91 template< typename Fn >
92 explicit push_coroutine( BOOST_RV_REF( Fn),
93 attributes const& = attributes() );
94
95 template< typename Fn, typename StackAllocator >
96 explicit push_coroutine( BOOST_RV_REF( Fn),
97 attributes const&,
98 StackAllocator);
99 #else
100 template< typename Fn >
101 explicit push_coroutine( Fn fn,
102 attributes const& = attributes() );
103
104 template< typename Fn, typename StackAllocator >
105 explicit push_coroutine( Fn fn,
106 attributes const&,
107 StackAllocator);
108
109 template< typename Fn >
110 explicit push_coroutine( BOOST_RV_REF( Fn),
111 attributes const& = attributes() );
112
113 template< typename Fn, typename StackAllocator >
114 explicit push_coroutine( BOOST_RV_REF( Fn),
115 attributes const&,
116 StackAllocator);
117 #endif
118
119 ~push_coroutine()
120 {
121 if ( 0 != impl_)
122 {
123 impl_->destroy();
124 impl_ = 0;
125 }
126 }
127
128 push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
129 impl_( 0)
130 { swap( other); }
131
132 push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
133 {
134 push_coroutine tmp( boost::move( other) );
135 swap( tmp);
136 return * this;
137 }
138
139 BOOST_EXPLICIT_OPERATOR_BOOL();
140
141 bool operator!() const BOOST_NOEXCEPT
142 { return 0 == impl_ || impl_->is_complete(); }
143
144 void swap( push_coroutine & other) BOOST_NOEXCEPT
145 { std::swap( impl_, other.impl_); }
146
147 push_coroutine & operator()( Arg arg)
148 {
149 BOOST_ASSERT( * this);
150
151 impl_->push( arg);
152 return * this;
153 }
154
155 class iterator
156 {
157 private:
158 push_coroutine< Arg > * c_;
159
160 public:
161 typedef std::output_iterator_tag iterator_category;
162 typedef void value_type;
163 typedef void difference_type;
164 typedef void pointer;
165 typedef void reference;
166
167 iterator() :
168 c_( 0)
169 {}
170
171 explicit iterator( push_coroutine< Arg > * c) :
172 c_( c)
173 {}
174
175 iterator & operator=( Arg a)
176 {
177 BOOST_ASSERT( c_);
178 if ( ! ( * c_)( a) ) c_ = 0;
179 return * this;
180 }
181
182 bool operator==( iterator const& other) const
183 { return other.c_ == c_; }
184
185 bool operator!=( iterator const& other) const
186 { return other.c_ != c_; }
187
188 iterator & operator*()
189 { return * this; }
190
191 iterator & operator++()
192 { return * this; }
193 };
194
195 struct const_iterator;
196 };
197
198 template< typename Arg >
199 class push_coroutine< Arg & >
200 {
201 private:
202 template< typename V, typename X, typename Y, typename Z >
203 friend class detail::pull_coroutine_object;
204
205 typedef detail::push_coroutine_impl< Arg & > impl_type;
206 typedef detail::push_coroutine_synthesized< Arg & > synth_type;
207 typedef detail::parameters< Arg & > param_type;
208
209 struct dummy {};
210
211 impl_type * impl_;
212
213 BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
214
215 explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
216 impl_( & impl)
217 { BOOST_ASSERT( impl_); }
218
219 public:
220 push_coroutine() BOOST_NOEXCEPT :
221 impl_( 0)
222 {}
223
224 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
225 # ifdef BOOST_MSVC
226 typedef void ( * coroutine_fn)( pull_coroutine< Arg & > &);
227
228 explicit push_coroutine( coroutine_fn,
229 attributes const& = attributes() );
230
231 template< typename StackAllocator >
232 explicit push_coroutine( coroutine_fn,
233 attributes const&,
234 StackAllocator);
235 # endif
236 template< typename Fn >
237 explicit push_coroutine( BOOST_RV_REF( Fn),
238 attributes const& = attributes() );
239
240 template< typename Fn, typename StackAllocator >
241 explicit push_coroutine( BOOST_RV_REF( Fn),
242 attributes const&,
243 StackAllocator);
244 #else
245 template< typename Fn >
246 explicit push_coroutine( Fn,
247 attributes const& = attributes() );
248
249 template< typename Fn, typename StackAllocator >
250 explicit push_coroutine( Fn,
251 attributes const&,
252 StackAllocator);
253
254 template< typename Fn >
255 explicit push_coroutine( BOOST_RV_REF( Fn),
256 attributes const& = attributes() );
257
258 template< typename Fn, typename StackAllocator >
259 explicit push_coroutine( BOOST_RV_REF( Fn),
260 attributes const&,
261 StackAllocator);
262 #endif
263
264 ~push_coroutine()
265 {
266 if ( 0 != impl_)
267 {
268 impl_->destroy();
269 impl_ = 0;
270 }
271 }
272
273 push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
274 impl_( 0)
275 { swap( other); }
276
277 push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
278 {
279 push_coroutine tmp( boost::move( other) );
280 swap( tmp);
281 return * this;
282 }
283
284 BOOST_EXPLICIT_OPERATOR_BOOL();
285
286 bool operator!() const BOOST_NOEXCEPT
287 { return 0 == impl_ || impl_->is_complete(); }
288
289 void swap( push_coroutine & other) BOOST_NOEXCEPT
290 { std::swap( impl_, other.impl_); }
291
292 push_coroutine & operator()( Arg & arg)
293 {
294 BOOST_ASSERT( * this);
295
296 impl_->push( arg);
297 return * this;
298 }
299
300 class iterator
301 {
302 private:
303 push_coroutine< Arg & > * c_;
304
305 public:
306 typedef std::output_iterator_tag iterator_category;
307 typedef void value_type;
308 typedef void difference_type;
309 typedef void pointer;
310 typedef void reference;
311
312 iterator() :
313 c_( 0)
314 {}
315
316 explicit iterator( push_coroutine< Arg & > * c) :
317 c_( c)
318 {}
319
320 iterator & operator=( Arg & a)
321 {
322 BOOST_ASSERT( c_);
323 if ( ! ( * c_)( a) ) c_ = 0;
324 return * this;
325 }
326
327 bool operator==( iterator const& other) const
328 { return other.c_ == c_; }
329
330 bool operator!=( iterator const& other) const
331 { return other.c_ != c_; }
332
333 iterator & operator*()
334 { return * this; }
335
336 iterator & operator++()
337 { return * this; }
338 };
339
340 struct const_iterator;
341 };
342
343 template<>
344 class push_coroutine< void >
345 {
346 private:
347 template< typename V, typename X, typename Y, typename Z >
348 friend class detail::pull_coroutine_object;
349
350 typedef detail::push_coroutine_impl< void > impl_type;
351 typedef detail::push_coroutine_synthesized< void > synth_type;
352 typedef detail::parameters< void > param_type;
353
354 struct dummy {};
355
356 impl_type * impl_;
357
358 BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
359
360 explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
361 impl_( & impl)
362 { BOOST_ASSERT( impl_); }
363
364 public:
365 push_coroutine() BOOST_NOEXCEPT :
366 impl_( 0)
367 {}
368
369 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
370 # ifdef BOOST_MSVC
371 typedef void ( * coroutine_fn)( pull_coroutine< void > &);
372
373 explicit push_coroutine( coroutine_fn,
374 attributes const& = attributes() );
375
376 template< typename StackAllocator >
377 explicit push_coroutine( coroutine_fn,
378 attributes const&,
379 StackAllocator);
380 # endif
381 template< typename Fn >
382 explicit push_coroutine( BOOST_RV_REF( Fn),
383 attributes const& = attributes() );
384
385 template< typename Fn, typename StackAllocator >
386 explicit push_coroutine( BOOST_RV_REF( Fn),
387 attributes const&,
388 StackAllocator);
389 #else
390 template< typename Fn >
391 explicit push_coroutine( Fn,
392 attributes const& = attributes() );
393
394 template< typename Fn, typename StackAllocator >
395 explicit push_coroutine( Fn,
396 attributes const&,
397 StackAllocator);
398
399 template< typename Fn >
400 explicit push_coroutine( BOOST_RV_REF( Fn),
401 attributes const& = attributes() );
402
403 template< typename Fn, typename StackAllocator >
404 explicit push_coroutine( BOOST_RV_REF( Fn),
405 attributes const&,
406 StackAllocator);
407 #endif
408
409 ~push_coroutine()
410 {
411 if ( 0 != impl_)
412 {
413 impl_->destroy();
414 impl_ = 0;
415 }
416 }
417
418 inline push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
419 impl_( 0)
420 { swap( other); }
421
422 inline push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
423 {
424 push_coroutine tmp( boost::move( other) );
425 swap( tmp);
426 return * this;
427 }
428
429 BOOST_EXPLICIT_OPERATOR_BOOL();
430
431 inline bool operator!() const BOOST_NOEXCEPT
432 { return 0 == impl_ || impl_->is_complete(); }
433
434 inline void swap( push_coroutine & other) BOOST_NOEXCEPT
435 { std::swap( impl_, other.impl_); }
436
437 inline push_coroutine & operator()()
438 {
439 BOOST_ASSERT( * this);
440
441 impl_->push();
442 return * this;
443 }
444
445 struct iterator;
446 struct const_iterator;
447 };
448
449
450
451 template< typename R >
452 class pull_coroutine
453 {
454 private:
455 template< typename V, typename X, typename Y, typename Z >
456 friend class detail::push_coroutine_object;
457
458 typedef detail::pull_coroutine_impl< R > impl_type;
459 typedef detail::pull_coroutine_synthesized< R > synth_type;
460 typedef detail::parameters< R > param_type;
461
462 struct dummy {};
463
464 impl_type * impl_;
465
466 BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
467
468 explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
469 impl_( & impl)
470 { BOOST_ASSERT( impl_); }
471
472 public:
473 pull_coroutine() BOOST_NOEXCEPT :
474 impl_( 0)
475 {}
476
477 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
478 # ifdef BOOST_MSVC
479 typedef void ( * coroutine_fn)( push_coroutine< R > &);
480
481 explicit pull_coroutine( coroutine_fn fn,
482 attributes const& attrs = attributes() ) :
483 impl_( 0)
484 {
485 // create a stack-context
486 stack_context stack_ctx;
487 stack_allocator stack_alloc;
488 // allocate the coroutine-stack
489 stack_alloc.allocate( stack_ctx, attrs.size);
490 BOOST_ASSERT( 0 != stack_ctx.sp);
491 // typedef of internal coroutine-type
492 typedef detail::pull_coroutine_object<
493 push_coroutine< R >, R, coroutine_fn, stack_allocator
494 > 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 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
503 BOOST_ASSERT( impl_);
504 impl_->pull();
505 }
506
507 template< typename StackAllocator >
508 explicit pull_coroutine( coroutine_fn fn,
509 attributes const& attrs,
510 StackAllocator stack_alloc) :
511 impl_( 0)
512 {
513 // create a stack-context
514 stack_context stack_ctx;
515 // allocate the coroutine-stack
516 stack_alloc.allocate( stack_ctx, attrs.size);
517 BOOST_ASSERT( 0 != stack_ctx.sp);
518 // typedef of internal coroutine-type
519 typedef detail::pull_coroutine_object<
520 push_coroutine< R >, R, coroutine_fn, StackAllocator
521 > object_t;
522 // reserve space on top of coroutine-stack for internal coroutine-type
523 std::size_t size = stack_ctx.size - sizeof( object_t);
524 BOOST_ASSERT( 0 != size);
525 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
526 BOOST_ASSERT( 0 != sp);
527 // placement new for internal coroutine
528 impl_ = new ( sp) object_t(
529 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
530 BOOST_ASSERT( impl_);
531 impl_->pull();
532 }
533 # endif
534 template< typename Fn >
535 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
536 attributes const& attrs = attributes() ) :
537 impl_( 0)
538 {
539 // create a stack-context
540 stack_context stack_ctx;
541 stack_allocator stack_alloc;
542 // allocate the coroutine-stack
543 stack_alloc.allocate( stack_ctx, attrs.size);
544 BOOST_ASSERT( 0 != stack_ctx.sp);
545 // typedef of internal coroutine-type
546 typedef detail::pull_coroutine_object<
547 push_coroutine< R >, R, Fn, stack_allocator
548 > object_t;
549 // reserve space on top of coroutine-stack for internal coroutine-type
550 std::size_t size = stack_ctx.size - sizeof( object_t);
551 BOOST_ASSERT( 0 != size);
552 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
553 BOOST_ASSERT( 0 != sp);
554 // placement new for internal coroutine
555 impl_ = new ( sp) object_t(
556 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
557 BOOST_ASSERT( impl_);
558 impl_->pull();
559 }
560
561 template< typename Fn, typename StackAllocator >
562 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
563 attributes const& attrs,
564 StackAllocator stack_alloc) :
565 impl_( 0)
566 {
567 // create a stack-context
568 stack_context stack_ctx;
569 // allocate the coroutine-stack
570 stack_alloc.allocate( stack_ctx, attrs.size);
571 BOOST_ASSERT( 0 != stack_ctx.sp);
572 // typedef of internal coroutine-type
573 typedef detail::pull_coroutine_object<
574 push_coroutine< R >, R, Fn, StackAllocator
575 > object_t;
576 // reserve space on top of coroutine-stack for internal coroutine-type
577 std::size_t size = stack_ctx.size - sizeof( object_t);
578 BOOST_ASSERT( 0 != size);
579 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
580 BOOST_ASSERT( 0 != sp);
581 // placement new for internal coroutine
582 impl_ = new ( sp) object_t(
583 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
584 BOOST_ASSERT( impl_);
585 impl_->pull();
586 }
587 #else
588 template< typename Fn >
589 explicit pull_coroutine( Fn fn,
590 attributes const& attrs = attributes() ) :
591 impl_( 0)
592 {
593 // create a stack-context
594 stack_context stack_ctx;
595 stack_allocator stack_alloc;
596 // allocate the coroutine-stack
597 stack_alloc.allocate( stack_ctx, attrs.size);
598 BOOST_ASSERT( 0 != stack_ctx.sp);
599 // typedef of internal coroutine-type
600 typedef detail::pull_coroutine_object<
601 push_coroutine< R >, R, Fn, stack_allocator
602 > object_t;
603 // reserve space on top of coroutine-stack for internal coroutine-type
604 std::size_t size = stack_ctx.size - sizeof( object_t);
605 BOOST_ASSERT( 0 != size);
606 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
607 BOOST_ASSERT( 0 != sp);
608 // placement new for internal coroutine
609 impl_ = new ( sp) object_t(
610 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
611 BOOST_ASSERT( impl_);
612 impl_->pull();
613 }
614
615 template< typename Fn, typename StackAllocator >
616 explicit pull_coroutine( Fn fn,
617 attributes const& attrs,
618 StackAllocator stack_alloc) :
619 impl_( 0)
620 {
621 // create a stack-context
622 stack_context stack_ctx;
623 // allocate the coroutine-stack
624 stack_alloc.allocate( stack_ctx, attrs.size);
625 BOOST_ASSERT( 0 != stack_ctx.sp);
626 // typedef of internal coroutine-type
627 typedef detail::pull_coroutine_object<
628 push_coroutine< R >, R, Fn, StackAllocator
629 > object_t;
630 // reserve space on top of coroutine-stack for internal coroutine-type
631 std::size_t size = stack_ctx.size - sizeof( object_t);
632 BOOST_ASSERT( 0 != size);
633 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
634 BOOST_ASSERT( 0 != sp);
635 // placement new for internal coroutine
636 impl_ = new ( sp) object_t(
637 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
638 BOOST_ASSERT( impl_);
639 impl_->pull();
640 }
641
642 template< typename Fn >
643 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
644 attributes const& attrs = attributes() ) :
645 impl_( 0)
646 {
647 // create a stack-context
648 stack_context stack_ctx;
649 stack_allocator stack_alloc;
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 detail::pull_coroutine_object<
655 push_coroutine< R >, R, Fn, stack_allocator
656 > object_t;
657 // reserve space on top of coroutine-stack for internal coroutine-type
658 std::size_t size = stack_ctx.size - sizeof( object_t);
659 BOOST_ASSERT( 0 != size);
660 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
661 BOOST_ASSERT( 0 != sp);
662 // placement new for internal coroutine
663 impl_ = new ( sp) object_t(
664 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
665 BOOST_ASSERT( impl_);
666 impl_->pull();
667 }
668
669 template< typename Fn, typename StackAllocator >
670 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
671 attributes const& attrs,
672 StackAllocator stack_alloc) :
673 impl_( 0)
674 {
675 // create a stack-context
676 stack_context stack_ctx;
677 // allocate the coroutine-stack
678 stack_alloc.allocate( stack_ctx, attrs.size);
679 BOOST_ASSERT( 0 != stack_ctx.sp);
680 // typedef of internal coroutine-type
681 typedef detail::pull_coroutine_object<
682 push_coroutine< R >, R, Fn, StackAllocator
683 > object_t;
684 // reserve space on top of coroutine-stack for internal coroutine-type
685 std::size_t size = stack_ctx.size - sizeof( object_t);
686 BOOST_ASSERT( 0 != size);
687 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
688 BOOST_ASSERT( 0 != sp);
689 // placement new for internal coroutine
690 impl_ = new ( sp) object_t(
691 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
692 BOOST_ASSERT( impl_);
693 impl_->pull();
694 }
695 #endif
696
697 ~pull_coroutine()
698 {
699 if ( 0 != impl_)
700 {
701 impl_->destroy();
702 impl_ = 0;
703 }
704 }
705
706 pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
707 impl_( 0)
708 { swap( other); }
709
710 pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
711 {
712 pull_coroutine tmp( boost::move( other) );
713 swap( tmp);
714 return * this;
715 }
716
717 BOOST_EXPLICIT_OPERATOR_BOOL();
718
719 bool operator!() const BOOST_NOEXCEPT
720 { return 0 == impl_ || impl_->is_complete(); }
721
722 void swap( pull_coroutine & other) BOOST_NOEXCEPT
723 { std::swap( impl_, other.impl_); }
724
725 pull_coroutine & operator()()
726 {
727 BOOST_ASSERT( * this);
728
729 impl_->pull();
730 return * this;
731 }
732
733 R get() const
734 {
735 BOOST_ASSERT( 0 != impl_);
736
737 return impl_->get();
738 }
739
740 class iterator
741 {
742 private:
743 pull_coroutine< R > * c_;
744 R * val_;
745
746 void fetch_()
747 {
748 BOOST_ASSERT( c_);
749
750 if ( ! ( * c_) )
751 {
752 c_ = 0;
753 val_ = 0;
754 return;
755 }
756 val_ = c_->impl_->get_pointer();
757 }
758
759 void increment_()
760 {
761 BOOST_ASSERT( c_);
762 BOOST_ASSERT( * c_);
763
764 ( * c_)();
765 fetch_();
766 }
767
768 public:
769 typedef std::input_iterator_tag iterator_category;
770 typedef typename remove_reference< R >::type value_type;
771 typedef std::ptrdiff_t difference_type;
772 typedef value_type * pointer;
773 typedef value_type & reference;
774
775 typedef pointer pointer_t;
776 typedef reference reference_t;
777
778 iterator() :
779 c_( 0), val_( 0)
780 {}
781
782 explicit iterator( pull_coroutine< R > * c) :
783 c_( c), val_( 0)
784 { fetch_(); }
785
786 iterator( iterator const& other) :
787 c_( other.c_), val_( other.val_)
788 {}
789
790 iterator & operator=( iterator const& other)
791 {
792 if ( this == & other) return * this;
793 c_ = other.c_;
794 val_ = other.val_;
795 return * this;
796 }
797
798 bool operator==( iterator const& other) const
799 { return other.c_ == c_ && other.val_ == val_; }
800
801 bool operator!=( iterator const& other) const
802 { return other.c_ != c_ || other.val_ != val_; }
803
804 iterator & operator++()
805 {
806 increment_();
807 return * this;
808 }
809
810 iterator operator++( int);
811
812 reference_t operator*() const
813 {
814 if ( ! val_)
815 boost::throw_exception(
816 invalid_result() );
817 return * val_;
818 }
819
820 pointer_t operator->() const
821 {
822 if ( ! val_)
823 boost::throw_exception(
824 invalid_result() );
825 return val_;
826 }
827 };
828
829 class const_iterator
830 {
831 private:
832 pull_coroutine< R > * c_;
833 R * val_;
834
835 void fetch_()
836 {
837 BOOST_ASSERT( c_);
838
839 if ( ! ( * c_) )
840 {
841 c_ = 0;
842 val_ = 0;
843 return;
844 }
845 val_ = c_->impl_->get_pointer();
846 }
847
848 void increment_()
849 {
850 BOOST_ASSERT( c_);
851 BOOST_ASSERT( * c_);
852
853 ( * c_)();
854 fetch_();
855 }
856
857 public:
858 typedef std::input_iterator_tag iterator_category;
859 typedef const typename remove_reference< R >::type value_type;
860 typedef std::ptrdiff_t difference_type;
861 typedef value_type * pointer;
862 typedef value_type & reference;
863
864 typedef pointer pointer_t;
865 typedef reference reference_t;
866
867 const_iterator() :
868 c_( 0), val_( 0)
869 {}
870
871 explicit const_iterator( pull_coroutine< R > const* c) :
872 c_( const_cast< pull_coroutine< R > * >( c) ),
873 val_( 0)
874 { fetch_(); }
875
876 const_iterator( const_iterator const& other) :
877 c_( other.c_), val_( other.val_)
878 {}
879
880 const_iterator & operator=( const_iterator const& other)
881 {
882 if ( this == & other) return * this;
883 c_ = other.c_;
884 val_ = other.val_;
885 return * this;
886 }
887
888 bool operator==( const_iterator const& other) const
889 { return other.c_ == c_ && other.val_ == val_; }
890
891 bool operator!=( const_iterator const& other) const
892 { return other.c_ != c_ || other.val_ != val_; }
893
894 const_iterator & operator++()
895 {
896 increment_();
897 return * this;
898 }
899
900 const_iterator operator++( int);
901
902 reference_t operator*() const
903 {
904 if ( ! val_)
905 boost::throw_exception(
906 invalid_result() );
907 return * val_;
908 }
909
910 pointer_t operator->() const
911 {
912 if ( ! val_)
913 boost::throw_exception(
914 invalid_result() );
915 return val_;
916 }
917 };
918
919 friend class iterator;
920 friend class const_iterator;
921 };
922
923 template< typename R >
924 class pull_coroutine< R & >
925 {
926 private:
927 template< typename V, typename X, typename Y, typename Z >
928 friend class detail::push_coroutine_object;
929
930 typedef detail::pull_coroutine_impl< R & > impl_type;
931 typedef detail::pull_coroutine_synthesized< R & > synth_type;
932 typedef detail::parameters< R & > param_type;
933
934 struct dummy {};
935
936 impl_type * impl_;
937
938 BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
939
940 explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
941 impl_( & impl)
942 { BOOST_ASSERT( impl_); }
943
944 public:
945 pull_coroutine() BOOST_NOEXCEPT :
946 impl_( 0)
947 {}
948
949 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
950 # ifdef BOOST_MSVC
951 typedef void ( * coroutine_fn)( push_coroutine< R & > &);
952
953 explicit pull_coroutine( coroutine_fn fn,
954 attributes const& attrs = attributes() ) :
955 impl_( 0)
956 {
957 // create a stack-context
958 stack_context stack_ctx;
959 stack_allocator stack_alloc;
960 // allocate the coroutine-stack
961 stack_alloc.allocate( stack_ctx, attrs.size);
962 BOOST_ASSERT( 0 != stack_ctx.sp);
963 // typedef of internal coroutine-type
964 typedef detail::pull_coroutine_object<
965 push_coroutine< R & >, R &, coroutine_fn, stack_allocator
966 > object_t;
967 // reserve space on top of coroutine-stack for internal coroutine-type
968 std::size_t size = stack_ctx.size - sizeof( object_t);
969 BOOST_ASSERT( 0 != size);
970 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
971 BOOST_ASSERT( 0 != sp);
972 // placement new for internal coroutine
973 impl_ = new ( sp) object_t(
974 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
975 BOOST_ASSERT( impl_);
976 impl_->pull();
977 }
978
979 template< typename StackAllocator >
980 explicit pull_coroutine( coroutine_fn fn,
981 attributes const& attrs,
982 StackAllocator stack_alloc) :
983 impl_( 0)
984 {
985 // create a stack-context
986 stack_context stack_ctx;
987 // allocate the coroutine-stack
988 stack_alloc.allocate( stack_ctx, attrs.size);
989 BOOST_ASSERT( 0 != stack_ctx.sp);
990 // typedef of internal coroutine-type
991 typedef detail::pull_coroutine_object<
992 push_coroutine< R & >, R &, coroutine_fn, StackAllocator
993 > object_t;
994 // reserve space on top of coroutine-stack for internal coroutine-type
995 std::size_t size = stack_ctx.size - sizeof( object_t);
996 BOOST_ASSERT( 0 != size);
997 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
998 BOOST_ASSERT( 0 != sp);
999 // placement new for internal coroutine
1000 impl_ = new ( sp) object_t(
1001 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1002 BOOST_ASSERT( impl_);
1003 impl_->pull();
1004 }
1005 # endif
1006 template< typename Fn >
1007 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1008 attributes const& attrs = attributes() ) :
1009 impl_( 0)
1010 {
1011 // create a stack-context
1012 stack_context stack_ctx;
1013 stack_allocator stack_alloc;
1014 // allocate the coroutine-stack
1015 stack_alloc.allocate( stack_ctx, attrs.size);
1016 BOOST_ASSERT( 0 != stack_ctx.sp);
1017 // typedef of internal coroutine-type
1018 typedef detail::pull_coroutine_object<
1019 push_coroutine< R & >, R &, Fn, stack_allocator
1020 > object_t;
1021 // reserve space on top of coroutine-stack for internal coroutine-type
1022 std::size_t size = stack_ctx.size - sizeof( object_t);
1023 BOOST_ASSERT( 0 != size);
1024 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1025 BOOST_ASSERT( 0 != sp);
1026 // placement new for internal coroutine
1027 impl_ = new ( sp) object_t(
1028 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1029 BOOST_ASSERT( impl_);
1030 impl_->pull();
1031 }
1032
1033 template< typename Fn, typename StackAllocator >
1034 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1035 attributes const& attrs,
1036 StackAllocator stack_alloc) :
1037 impl_( 0)
1038 {
1039 // create a stack-context
1040 stack_context stack_ctx;
1041 // allocate the coroutine-stack
1042 stack_alloc.allocate( stack_ctx, attrs.size);
1043 BOOST_ASSERT( 0 != stack_ctx.sp);
1044 // typedef of internal coroutine-type
1045 typedef detail::pull_coroutine_object<
1046 push_coroutine< R & >, R &, Fn, StackAllocator
1047 > object_t;
1048 // reserve space on top of coroutine-stack for internal coroutine-type
1049 std::size_t size = stack_ctx.size - sizeof( object_t);
1050 BOOST_ASSERT( 0 != size);
1051 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1052 BOOST_ASSERT( 0 != sp);
1053 // placement new for internal coroutine
1054 impl_ = new ( sp) object_t(
1055 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1056 BOOST_ASSERT( impl_);
1057 impl_->pull();
1058 }
1059 #else
1060 template< typename Fn >
1061 explicit pull_coroutine( Fn fn,
1062 attributes const& attrs = attributes() ) :
1063 impl_( 0)
1064 {
1065 // create a stack-context
1066 stack_context stack_ctx;
1067 stack_allocator stack_alloc;
1068 // allocate the coroutine-stack
1069 stack_alloc.allocate( stack_ctx, attrs.size);
1070 BOOST_ASSERT( 0 != stack_ctx.sp);
1071 // typedef of internal coroutine-type
1072 typedef detail::pull_coroutine_object<
1073 push_coroutine< R & >, R &, Fn, stack_allocator
1074 > object_t;
1075 // reserve space on top of coroutine-stack for internal coroutine-type
1076 std::size_t size = stack_ctx.size - sizeof( object_t);
1077 BOOST_ASSERT( 0 != size);
1078 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1079 BOOST_ASSERT( 0 != sp);
1080 // placement new for internal coroutine
1081 impl_ = new ( sp) object_t(
1082 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1083 BOOST_ASSERT( impl_);
1084 impl_->pull();
1085 }
1086
1087 template< typename Fn, typename StackAllocator >
1088 explicit pull_coroutine( Fn fn,
1089 attributes const& attrs,
1090 StackAllocator stack_alloc) :
1091 impl_( 0)
1092 {
1093 // create a stack-context
1094 stack_context stack_ctx;
1095 // allocate the coroutine-stack
1096 stack_alloc.allocate( stack_ctx, attrs.size);
1097 BOOST_ASSERT( 0 != stack_ctx.sp);
1098 // typedef of internal coroutine-type
1099 typedef detail::pull_coroutine_object<
1100 push_coroutine< R & >, R &, Fn, StackAllocator
1101 > object_t;
1102 // reserve space on top of coroutine-stack for internal coroutine-type
1103 std::size_t size = stack_ctx.size - sizeof( object_t);
1104 BOOST_ASSERT( 0 != size);
1105 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1106 BOOST_ASSERT( 0 != sp);
1107 // placement new for internal coroutine
1108 impl_ = new ( sp) object_t(
1109 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1110 BOOST_ASSERT( impl_);
1111 impl_->pull();
1112 }
1113
1114 template< typename Fn >
1115 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1116 attributes const& attrs = attributes() ) :
1117 impl_( 0)
1118 {
1119 // create a stack-context
1120 stack_context stack_ctx;
1121 stack_allocator stack_alloc;
1122 // allocate the coroutine-stack
1123 stack_alloc.allocate( stack_ctx, attrs.size);
1124 BOOST_ASSERT( 0 != stack_ctx.sp);
1125 // typedef of internal coroutine-type
1126 typedef detail::pull_coroutine_object<
1127 push_coroutine< R & >, R &, Fn, stack_allocator
1128 > object_t;
1129 // reserve space on top of coroutine-stack for internal coroutine-type
1130 std::size_t size = stack_ctx.size - sizeof( object_t);
1131 BOOST_ASSERT( 0 != size);
1132 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1133 BOOST_ASSERT( 0 != sp);
1134 // placement new for internal coroutine
1135 impl_ = new ( sp) object_t(
1136 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1137 BOOST_ASSERT( impl_);
1138 impl_->pull();
1139 }
1140
1141 template< typename Fn, typename StackAllocator >
1142 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1143 attributes const& attrs,
1144 StackAllocator stack_alloc) :
1145 impl_( 0)
1146 {
1147 // create a stack-context
1148 stack_context stack_ctx;
1149 // allocate the coroutine-stack
1150 stack_alloc.allocate( stack_ctx, attrs.size);
1151 BOOST_ASSERT( 0 != stack_ctx.sp);
1152 // typedef of internal coroutine-type
1153 typedef detail::pull_coroutine_object<
1154 push_coroutine< R & >, R &, Fn, StackAllocator
1155 > object_t;
1156 // reserve space on top of coroutine-stack for internal coroutine-type
1157 std::size_t size = stack_ctx.size - sizeof( object_t);
1158 BOOST_ASSERT( 0 != size);
1159 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1160 BOOST_ASSERT( 0 != sp);
1161 // placement new for internal coroutine
1162 impl_ = new ( sp) object_t(
1163 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1164 BOOST_ASSERT( impl_);
1165 impl_->pull();
1166 }
1167 #endif
1168
1169 ~pull_coroutine()
1170 {
1171 if ( 0 != impl_)
1172 {
1173 impl_->destroy();
1174 impl_ = 0;
1175 }
1176 }
1177
1178 pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
1179 impl_( 0)
1180 { swap( other); }
1181
1182 pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
1183 {
1184 pull_coroutine tmp( boost::move( other) );
1185 swap( tmp);
1186 return * this;
1187 }
1188
1189 BOOST_EXPLICIT_OPERATOR_BOOL();
1190
1191 bool operator!() const BOOST_NOEXCEPT
1192 { return 0 == impl_ || impl_->is_complete(); }
1193
1194 void swap( pull_coroutine & other) BOOST_NOEXCEPT
1195 { std::swap( impl_, other.impl_); }
1196
1197 pull_coroutine & operator()()
1198 {
1199 BOOST_ASSERT( * this);
1200
1201 impl_->pull();
1202 return * this;
1203 }
1204
1205 R & get() const
1206 { return impl_->get(); }
1207
1208 class iterator
1209 {
1210 private:
1211 pull_coroutine< R & > * c_;
1212 R * val_;
1213
1214 void fetch_()
1215 {
1216 BOOST_ASSERT( c_);
1217
1218 if ( ! ( * c_) )
1219 {
1220 c_ = 0;
1221 val_ = 0;
1222 return;
1223 }
1224 val_ = c_->impl_->get_pointer();
1225 }
1226
1227 void increment_()
1228 {
1229 BOOST_ASSERT( c_);
1230 BOOST_ASSERT( * c_);
1231
1232 ( * c_)();
1233 fetch_();
1234 }
1235
1236 public:
1237 typedef std::input_iterator_tag iterator_category;
1238 typedef typename remove_reference< R >::type value_type;
1239 typedef std::ptrdiff_t difference_type;
1240 typedef value_type * pointer;
1241 typedef value_type & reference;
1242
1243 typedef pointer pointer_t;
1244 typedef reference reference_t;
1245
1246 iterator() :
1247 c_( 0), val_( 0)
1248 {}
1249
1250 explicit iterator( pull_coroutine< R & > * c) :
1251 c_( c), val_( 0)
1252 { fetch_(); }
1253
1254 iterator( iterator const& other) :
1255 c_( other.c_), val_( other.val_)
1256 {}
1257
1258 iterator & operator=( iterator const& other)
1259 {
1260 if ( this == & other) return * this;
1261 c_ = other.c_;
1262 val_ = other.val_;
1263 return * this;
1264 }
1265
1266 bool operator==( iterator const& other) const
1267 { return other.c_ == c_ && other.val_ == val_; }
1268
1269 bool operator!=( iterator const& other) const
1270 { return other.c_ != c_ || other.val_ != val_; }
1271
1272 iterator & operator++()
1273 {
1274 increment_();
1275 return * this;
1276 }
1277
1278 iterator operator++( int);
1279
1280 reference_t operator*() const
1281 {
1282 if ( ! val_)
1283 boost::throw_exception(
1284 invalid_result() );
1285 return * val_;
1286 }
1287
1288 pointer_t operator->() const
1289 {
1290 if ( ! val_)
1291 boost::throw_exception(
1292 invalid_result() );
1293 return val_;
1294 }
1295 };
1296
1297 class const_iterator
1298 {
1299 private:
1300 pull_coroutine< R & > * c_;
1301 R * val_;
1302
1303 void fetch_()
1304 {
1305 BOOST_ASSERT( c_);
1306
1307 if ( ! ( * c_) )
1308 {
1309 c_ = 0;
1310 val_ = 0;
1311 return;
1312 }
1313 val_ = c_->impl_->get_pointer();
1314 }
1315
1316 void increment_()
1317 {
1318 BOOST_ASSERT( c_);
1319 BOOST_ASSERT( * c_);
1320
1321 ( * c_)();
1322 fetch_();
1323 }
1324
1325 public:
1326 typedef std::input_iterator_tag iterator_category;
1327 typedef const typename remove_reference< R >::type value_type;
1328 typedef std::ptrdiff_t difference_type;
1329 typedef value_type * pointer;
1330 typedef value_type & reference;
1331
1332 typedef pointer pointer_t;
1333 typedef reference reference_t;
1334
1335 const_iterator() :
1336 c_( 0), val_( 0)
1337 {}
1338
1339 explicit const_iterator( pull_coroutine< R & > const* c) :
1340 c_( const_cast< pull_coroutine< R & > * >( c) ),
1341 val_( 0)
1342 { fetch_(); }
1343
1344 const_iterator( const_iterator const& other) :
1345 c_( other.c_), val_( other.val_)
1346 {}
1347
1348 const_iterator & operator=( const_iterator const& other)
1349 {
1350 if ( this == & other) return * this;
1351 c_ = other.c_;
1352 val_ = other.val_;
1353 return * this;
1354 }
1355
1356 bool operator==( const_iterator const& other) const
1357 { return other.c_ == c_ && other.val_ == val_; }
1358
1359 bool operator!=( const_iterator const& other) const
1360 { return other.c_ != c_ || other.val_ != val_; }
1361
1362 const_iterator & operator++()
1363 {
1364 increment_();
1365 return * this;
1366 }
1367
1368 const_iterator operator++( int);
1369
1370 reference_t operator*() const
1371 {
1372 if ( ! val_)
1373 boost::throw_exception(
1374 invalid_result() );
1375 return * val_;
1376 }
1377
1378 pointer_t operator->() const
1379 {
1380 if ( ! val_)
1381 boost::throw_exception(
1382 invalid_result() );
1383 return val_;
1384 }
1385 };
1386
1387 friend class iterator;
1388 friend class const_iterator;
1389 };
1390
1391 template<>
1392 class pull_coroutine< void >
1393 {
1394 private:
1395 template< typename V, typename X, typename Y, typename Z >
1396 friend class detail::push_coroutine_object;
1397
1398 typedef detail::pull_coroutine_impl< void > impl_type;
1399 typedef detail::pull_coroutine_synthesized< void > synth_type;
1400 typedef detail::parameters< void > param_type;
1401
1402 struct dummy {};
1403
1404 impl_type * impl_;
1405
1406 BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
1407
1408 explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
1409 impl_( & impl)
1410 { BOOST_ASSERT( impl_); }
1411
1412 public:
1413 pull_coroutine() BOOST_NOEXCEPT :
1414 impl_( 0)
1415 {}
1416
1417 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1418 # ifdef BOOST_MSVC
1419 typedef void ( * coroutine_fn)( push_coroutine< void > &);
1420
1421 explicit pull_coroutine( coroutine_fn fn,
1422 attributes const& attrs = attributes() ) :
1423 impl_( 0)
1424 {
1425 // create a stack-context
1426 stack_context stack_ctx;
1427 stack_allocator stack_alloc;
1428 // allocate the coroutine-stack
1429 stack_alloc.allocate( stack_ctx, attrs.size);
1430 BOOST_ASSERT( 0 != stack_ctx.sp);
1431 // typedef of internal coroutine-type
1432 typedef detail::pull_coroutine_object<
1433 push_coroutine< void >, void, coroutine_fn, stack_allocator
1434 > object_t;
1435 // reserve space on top of coroutine-stack for internal coroutine-type
1436 std::size_t size = stack_ctx.size - sizeof( object_t);
1437 BOOST_ASSERT( 0 != size);
1438 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1439 BOOST_ASSERT( 0 != sp);
1440 // placement new for internal coroutine
1441 impl_ = new ( sp) object_t(
1442 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1443 BOOST_ASSERT( impl_);
1444 impl_->pull();
1445 }
1446
1447 template< typename StackAllocator >
1448 explicit pull_coroutine( coroutine_fn fn,
1449 attributes const& attrs,
1450 StackAllocator stack_alloc) :
1451 impl_( 0)
1452 {
1453 // create a stack-context
1454 stack_context stack_ctx;
1455 // allocate the coroutine-stack
1456 stack_alloc.allocate( stack_ctx, attrs.size);
1457 BOOST_ASSERT( 0 != stack_ctx.sp);
1458 // typedef of internal coroutine-type
1459 typedef detail::pull_coroutine_object<
1460 push_coroutine< void >, void, coroutine_fn, StackAllocator
1461 > object_t;
1462 // reserve space on top of coroutine-stack for internal coroutine-type
1463 std::size_t size = stack_ctx.size - sizeof( object_t);
1464 BOOST_ASSERT( 0 != size);
1465 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1466 BOOST_ASSERT( 0 != sp);
1467 // placement new for internal coroutine
1468 impl_ = new ( sp) object_t(
1469 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1470 BOOST_ASSERT( impl_);
1471 impl_->pull();
1472 }
1473 # endif
1474 template< typename Fn >
1475 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1476 attributes const& attrs = attributes() ) :
1477 impl_( 0)
1478 {
1479 // create a stack-context
1480 stack_context stack_ctx;
1481 stack_allocator stack_alloc;
1482 // allocate the coroutine-stack
1483 stack_alloc.allocate( stack_ctx, attrs.size);
1484 BOOST_ASSERT( 0 != stack_ctx.sp);
1485 // typedef of internal coroutine-type
1486 typedef detail::pull_coroutine_object<
1487 push_coroutine< void >, void, Fn, stack_allocator
1488 > object_t;
1489 // reserve space on top of coroutine-stack for internal coroutine-type
1490 std::size_t size = stack_ctx.size - sizeof( object_t);
1491 BOOST_ASSERT( 0 != size);
1492 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1493 BOOST_ASSERT( 0 != sp);
1494 // placement new for internal coroutine
1495 impl_ = new ( sp) object_t(
1496 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1497 BOOST_ASSERT( impl_);
1498 impl_->pull();
1499 }
1500
1501 template< typename Fn, typename StackAllocator >
1502 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1503 attributes const& attrs,
1504 StackAllocator stack_alloc) :
1505 impl_( 0)
1506 {
1507 // create a stack-context
1508 stack_context stack_ctx;
1509 // allocate the coroutine-stack
1510 stack_alloc.allocate( stack_ctx, attrs.size);
1511 BOOST_ASSERT( 0 != stack_ctx.sp);
1512 // typedef of internal coroutine-type
1513 typedef detail::pull_coroutine_object<
1514 push_coroutine< void >, void, Fn, StackAllocator
1515 > object_t;
1516 // reserve space on top of coroutine-stack for internal coroutine-type
1517 std::size_t size = stack_ctx.size - sizeof( object_t);
1518 BOOST_ASSERT( 0 != size);
1519 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1520 BOOST_ASSERT( 0 != sp);
1521 // placement new for internal coroutine
1522 impl_ = new ( sp) object_t(
1523 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1524 BOOST_ASSERT( impl_);
1525 impl_->pull();
1526 }
1527 #else
1528 template< typename Fn >
1529 explicit pull_coroutine( Fn fn,
1530 attributes const& attrs = attributes() ) :
1531 impl_( 0)
1532 {
1533 // create a stack-context
1534 stack_context stack_ctx;
1535 stack_allocator stack_alloc;
1536 // allocate the coroutine-stack
1537 stack_alloc.allocate( stack_ctx, attrs.size);
1538 BOOST_ASSERT( 0 != stack_ctx.sp);
1539 // typedef of internal coroutine-type
1540 typedef detail::pull_coroutine_object<
1541 push_coroutine< void >, void, Fn, stack_allocator
1542 > object_t;
1543 // reserve space on top of coroutine-stack for internal coroutine-type
1544 std::size_t size = stack_ctx.size - sizeof( object_t);
1545 BOOST_ASSERT( 0 != size);
1546 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1547 BOOST_ASSERT( 0 != sp);
1548 // placement new for internal coroutine
1549 impl_ = new ( sp) object_t(
1550 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1551 BOOST_ASSERT( impl_);
1552 impl_->pull();
1553 }
1554
1555 template< typename Fn, typename StackAllocator >
1556 explicit pull_coroutine( Fn fn,
1557 attributes const& attrs,
1558 StackAllocator stack_alloc) :
1559 impl_( 0)
1560 {
1561 // create a stack-context
1562 stack_context stack_ctx;
1563 // allocate the coroutine-stack
1564 stack_alloc.allocate( stack_ctx, attrs.size);
1565 BOOST_ASSERT( 0 != stack_ctx.sp);
1566 // typedef of internal coroutine-type
1567 typedef detail::pull_coroutine_object<
1568 push_coroutine< void >, void, Fn, StackAllocator
1569 > object_t;
1570 // reserve space on top of coroutine-stack for internal coroutine-type
1571 std::size_t size = stack_ctx.size - sizeof( object_t);
1572 BOOST_ASSERT( 0 != size);
1573 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1574 BOOST_ASSERT( 0 != sp);
1575 // placement new for internal coroutine
1576 impl_ = new ( sp) object_t(
1577 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1578 BOOST_ASSERT( impl_);
1579 impl_->pull();
1580 }
1581
1582 template< typename Fn >
1583 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1584 attributes const& attrs = attributes() ) :
1585 impl_( 0)
1586 {
1587 // create a stack-context
1588 stack_context stack_ctx;
1589 stack_allocator stack_alloc;
1590 // allocate the coroutine-stack
1591 stack_alloc.allocate( stack_ctx, attrs.size);
1592 BOOST_ASSERT( 0 != stack_ctx.sp);
1593 // typedef of internal coroutine-type
1594 typedef detail::pull_coroutine_object<
1595 push_coroutine< void >, void, Fn, stack_allocator
1596 > object_t;
1597 // reserve space on top of coroutine-stack for internal coroutine-type
1598 std::size_t size = stack_ctx.size - sizeof( object_t);
1599 BOOST_ASSERT( 0 != size);
1600 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1601 BOOST_ASSERT( 0 != sp);
1602 // placement new for internal coroutine
1603 impl_ = new ( sp) object_t(
1604 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1605 BOOST_ASSERT( impl_);
1606 impl_->pull();
1607 }
1608
1609 template< typename Fn, typename StackAllocator >
1610 explicit pull_coroutine( BOOST_RV_REF( Fn) fn,
1611 attributes const& attrs,
1612 StackAllocator stack_alloc) :
1613 impl_( 0)
1614 {
1615 // create a stack-context
1616 stack_context stack_ctx;
1617 // allocate the coroutine-stack
1618 stack_alloc.allocate( stack_ctx, attrs.size);
1619 BOOST_ASSERT( 0 != stack_ctx.sp);
1620 // typedef of internal coroutine-type
1621 typedef detail::pull_coroutine_object<
1622 push_coroutine< void >, void, Fn, StackAllocator
1623 > object_t;
1624 // reserve space on top of coroutine-stack for internal coroutine-type
1625 std::size_t size = stack_ctx.size - sizeof( object_t);
1626 BOOST_ASSERT( 0 != size);
1627 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1628 BOOST_ASSERT( 0 != sp);
1629 // placement new for internal coroutine
1630 impl_ = new ( sp) object_t(
1631 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1632 BOOST_ASSERT( impl_);
1633 impl_->pull();
1634 }
1635 #endif
1636
1637 ~pull_coroutine()
1638 {
1639 if ( 0 != impl_)
1640 {
1641 impl_->destroy();
1642 impl_ = 0;
1643 }
1644 }
1645
1646 inline pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
1647 impl_( 0)
1648 { swap( other); }
1649
1650 inline pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
1651 {
1652 pull_coroutine tmp( boost::move( other) );
1653 swap( tmp);
1654 return * this;
1655 }
1656
1657 BOOST_EXPLICIT_OPERATOR_BOOL();
1658
1659 inline bool operator!() const BOOST_NOEXCEPT
1660 { return 0 == impl_ || impl_->is_complete(); }
1661
1662 inline void swap( pull_coroutine & other) BOOST_NOEXCEPT
1663 { std::swap( impl_, other.impl_); }
1664
1665 inline pull_coroutine & operator()()
1666 {
1667 BOOST_ASSERT( * this);
1668
1669 impl_->pull();
1670 return * this;
1671 }
1672
1673 struct iterator;
1674 struct const_iterator;
1675 };
1676
1677 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1678 # ifdef BOOST_MSVC
1679 template< typename Arg >
1680 push_coroutine< Arg >::push_coroutine( coroutine_fn fn,
1681 attributes const& attrs) :
1682 impl_( 0)
1683 {
1684 // create a stack-context
1685 stack_context stack_ctx;
1686 stack_allocator stack_alloc;
1687 // allocate the coroutine-stack
1688 stack_alloc.allocate( stack_ctx, attrs.size);
1689 BOOST_ASSERT( 0 != stack_ctx.sp);
1690 // typedef of internal coroutine-type
1691 typedef detail::push_coroutine_object<
1692 pull_coroutine< Arg >, Arg, coroutine_fn, stack_allocator
1693 > object_t;
1694 // reserve space on top of coroutine-stack for internal coroutine-type
1695 std::size_t size = stack_ctx.size - sizeof( object_t);
1696 BOOST_ASSERT( 0 != size);
1697 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1698 BOOST_ASSERT( 0 != sp);
1699 // placement new for internal coroutine
1700 impl_ = new ( sp) object_t(
1701 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1702 BOOST_ASSERT( impl_);
1703 }
1704
1705 template< typename Arg >
1706 template< typename StackAllocator >
1707 push_coroutine< Arg >::push_coroutine( coroutine_fn fn,
1708 attributes const& attrs,
1709 StackAllocator stack_alloc) :
1710 impl_( 0)
1711 {
1712 // create a stack-context
1713 stack_context stack_ctx;
1714 // allocate the coroutine-stack
1715 stack_alloc.allocate( stack_ctx, attrs.size);
1716 BOOST_ASSERT( 0 != stack_ctx.sp);
1717 // typedef of internal coroutine-type
1718 typedef detail::push_coroutine_object<
1719 pull_coroutine< Arg >, Arg, coroutine_fn, StackAllocator
1720 > object_t;
1721 // reserve space on top of coroutine-stack for internal coroutine-type
1722 std::size_t size = stack_ctx.size - sizeof( object_t);
1723 BOOST_ASSERT( 0 != size);
1724 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1725 BOOST_ASSERT( 0 != sp);
1726 // placement new for internal coroutine
1727 impl_ = new ( sp) object_t(
1728 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1729 BOOST_ASSERT( impl_);
1730 }
1731
1732 template< typename Arg >
1733 push_coroutine< Arg & >::push_coroutine( coroutine_fn fn,
1734 attributes const& attrs) :
1735 impl_( 0)
1736 {
1737 // create a stack-context
1738 stack_context stack_ctx;
1739 stack_allocator stack_alloc;
1740 // allocate the coroutine-stack
1741 stack_alloc.allocate( stack_ctx, attrs.size);
1742 BOOST_ASSERT( 0 != stack_ctx.sp);
1743 // typedef of internal coroutine-type
1744 typedef detail::push_coroutine_object<
1745 pull_coroutine< Arg & >, Arg &, coroutine_fn, stack_allocator
1746 > object_t;
1747 // reserve space on top of coroutine-stack for internal coroutine-type
1748 std::size_t size = stack_ctx.size - sizeof( object_t);
1749 BOOST_ASSERT( 0 != size);
1750 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1751 BOOST_ASSERT( 0 != sp);
1752 // placement new for internal coroutine
1753 impl_ = new ( sp) object_t(
1754 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1755 BOOST_ASSERT( impl_);
1756 }
1757
1758 template< typename Arg >
1759 template< typename StackAllocator >
1760 push_coroutine< Arg & >::push_coroutine( coroutine_fn fn,
1761 attributes const& attrs,
1762 StackAllocator stack_alloc) :
1763 impl_( 0)
1764 {
1765 // create a stack-context
1766 stack_context stack_ctx;
1767 // allocate the coroutine-stack
1768 stack_alloc.allocate( stack_ctx, attrs.size);
1769 BOOST_ASSERT( 0 != stack_ctx.sp);
1770 // typedef of internal coroutine-type
1771 typedef detail::push_coroutine_object<
1772 pull_coroutine< Arg & >, Arg &, coroutine_fn, StackAllocator
1773 > object_t;
1774 // reserve space on top of coroutine-stack for internal coroutine-type
1775 std::size_t size = stack_ctx.size - sizeof( object_t);
1776 BOOST_ASSERT( 0 != size);
1777 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1778 BOOST_ASSERT( 0 != sp);
1779 // placement new for internal coroutine
1780 impl_ = new ( sp) object_t(
1781 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1782 BOOST_ASSERT( impl_);
1783 }
1784
1785 inline push_coroutine< void >::push_coroutine( coroutine_fn fn,
1786 attributes const& attrs) :
1787 impl_( 0)
1788 {
1789 // create a stack-context
1790 stack_context stack_ctx;
1791 stack_allocator stack_alloc;
1792 // allocate the coroutine-stack
1793 stack_alloc.allocate( stack_ctx, attrs.size);
1794 BOOST_ASSERT( 0 != stack_ctx.sp);
1795 // typedef of internal coroutine-type
1796 typedef detail::push_coroutine_object<
1797 pull_coroutine< void >, void, coroutine_fn, stack_allocator
1798 > object_t;
1799 // reserve space on top of coroutine-stack for internal coroutine-type
1800 std::size_t size = stack_ctx.size - sizeof( object_t);
1801 BOOST_ASSERT( 0 != size);
1802 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1803 BOOST_ASSERT( 0 != sp);
1804 // placement new for internal coroutine
1805 impl_ = new ( sp) object_t(
1806 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1807 BOOST_ASSERT( impl_);
1808 }
1809
1810 template< typename StackAllocator >
1811 push_coroutine< void >::push_coroutine( coroutine_fn fn,
1812 attributes const& attrs,
1813 StackAllocator stack_alloc) :
1814 impl_( 0)
1815 {
1816 // create a stack-context
1817 stack_context stack_ctx;
1818 // allocate the coroutine-stack
1819 stack_alloc.allocate( stack_ctx, attrs.size);
1820 BOOST_ASSERT( 0 != stack_ctx.sp);
1821 // typedef of internal coroutine-type
1822 typedef detail::push_coroutine_object<
1823 pull_coroutine< void >, void, coroutine_fn, StackAllocator
1824 > object_t;
1825 // reserve space on top of coroutine-stack for internal coroutine-type
1826 std::size_t size = stack_ctx.size - sizeof( object_t);
1827 BOOST_ASSERT( 0 != size);
1828 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1829 BOOST_ASSERT( 0 != sp);
1830 // placement new for internal coroutine
1831 impl_ = new ( sp) object_t(
1832 boost::forward< coroutine_fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1833 BOOST_ASSERT( impl_);
1834 }
1835 # endif
1836 template< typename Arg >
1837 template< typename Fn >
1838 push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
1839 attributes const& attrs) :
1840 impl_( 0)
1841 {
1842 // create a stack-context
1843 stack_context stack_ctx;
1844 stack_allocator stack_alloc;
1845 // allocate the coroutine-stack
1846 stack_alloc.allocate( stack_ctx, attrs.size);
1847 BOOST_ASSERT( 0 != stack_ctx.sp);
1848 // typedef of internal coroutine-type
1849 typedef detail::push_coroutine_object<
1850 pull_coroutine< Arg >, Arg, Fn, stack_allocator
1851 > object_t;
1852 // reserve space on top of coroutine-stack for internal coroutine-type
1853 std::size_t size = stack_ctx.size - sizeof( object_t);
1854 BOOST_ASSERT( 0 != size);
1855 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1856 BOOST_ASSERT( 0 != sp);
1857 // placement new for internal coroutine
1858 impl_ = new ( sp) object_t(
1859 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1860 BOOST_ASSERT( impl_);
1861 }
1862
1863 template< typename Arg >
1864 template< typename Fn, typename StackAllocator >
1865 push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
1866 attributes const& attrs,
1867 StackAllocator stack_alloc) :
1868 impl_( 0)
1869 {
1870 // create a stack-context
1871 stack_context stack_ctx;
1872 // allocate the coroutine-stack
1873 stack_alloc.allocate( stack_ctx, attrs.size);
1874 BOOST_ASSERT( 0 != stack_ctx.sp);
1875 // typedef of internal coroutine-type
1876 typedef detail::push_coroutine_object<
1877 pull_coroutine< Arg >, Arg, Fn, StackAllocator
1878 > object_t;
1879 // reserve space on top of coroutine-stack for internal coroutine-type
1880 std::size_t size = stack_ctx.size - sizeof( object_t);
1881 BOOST_ASSERT( 0 != size);
1882 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1883 BOOST_ASSERT( 0 != sp);
1884 // placement new for internal coroutine
1885 impl_ = new ( sp) object_t(
1886 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1887 BOOST_ASSERT( impl_);
1888 }
1889
1890 template< typename Arg >
1891 template< typename Fn >
1892 push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
1893 attributes const& attrs) :
1894 impl_( 0)
1895 {
1896 // create a stack-context
1897 stack_context stack_ctx;
1898 stack_allocator stack_alloc;
1899 // allocate the coroutine-stack
1900 stack_alloc.allocate( stack_ctx, attrs.size);
1901 BOOST_ASSERT( 0 != stack_ctx.sp);
1902 // typedef of internal coroutine-type
1903 typedef detail::push_coroutine_object<
1904 pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
1905 > object_t;
1906 // reserve space on top of coroutine-stack for internal coroutine-type
1907 std::size_t size = stack_ctx.size - sizeof( object_t);
1908 BOOST_ASSERT( 0 != size);
1909 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1910 BOOST_ASSERT( 0 != sp);
1911 // placement new for internal coroutine
1912 impl_ = new ( sp) object_t(
1913 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1914 BOOST_ASSERT( impl_);
1915 }
1916
1917 template< typename Arg >
1918 template< typename Fn, typename StackAllocator >
1919 push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
1920 attributes const& attrs,
1921 StackAllocator stack_alloc) :
1922 impl_( 0)
1923 {
1924 // create a stack-context
1925 stack_context stack_ctx;
1926 // allocate the coroutine-stack
1927 stack_alloc.allocate( stack_ctx, attrs.size);
1928 BOOST_ASSERT( 0 != stack_ctx.sp);
1929 // typedef of internal coroutine-type
1930 typedef detail::push_coroutine_object<
1931 pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
1932 > object_t;
1933 // reserve space on top of coroutine-stack for internal coroutine-type
1934 std::size_t size = stack_ctx.size - sizeof( object_t);
1935 BOOST_ASSERT( 0 != size);
1936 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1937 BOOST_ASSERT( 0 != sp);
1938 // placement new for internal coroutine
1939 impl_ = new ( sp) object_t(
1940 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1941 BOOST_ASSERT( impl_);
1942 }
1943
1944 template< typename Fn >
1945 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
1946 attributes const& attrs) :
1947 impl_( 0)
1948 {
1949 // create a stack-context
1950 stack_context stack_ctx;
1951 stack_allocator stack_alloc;
1952 // allocate the coroutine-stack
1953 stack_alloc.allocate( stack_ctx, attrs.size);
1954 BOOST_ASSERT( 0 != stack_ctx.sp);
1955 // typedef of internal coroutine-type
1956 typedef detail::push_coroutine_object<
1957 pull_coroutine< void >, void, Fn, stack_allocator
1958 > object_t;
1959 // reserve space on top of coroutine-stack for internal coroutine-type
1960 std::size_t size = stack_ctx.size - sizeof( object_t);
1961 BOOST_ASSERT( 0 != size);
1962 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1963 BOOST_ASSERT( 0 != sp);
1964 // placement new for internal coroutine
1965 impl_ = new ( sp) object_t(
1966 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1967 BOOST_ASSERT( impl_);
1968 }
1969
1970 template< typename Fn, typename StackAllocator >
1971 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
1972 attributes const& attrs,
1973 StackAllocator stack_alloc) :
1974 impl_( 0)
1975 {
1976 // create a stack-context
1977 stack_context stack_ctx;
1978 // allocate the coroutine-stack
1979 stack_alloc.allocate( stack_ctx, attrs.size);
1980 BOOST_ASSERT( 0 != stack_ctx.sp);
1981 // typedef of internal coroutine-type
1982 typedef detail::push_coroutine_object<
1983 pull_coroutine< void >, void, Fn, StackAllocator
1984 > object_t;
1985 // reserve space on top of coroutine-stack for internal coroutine-type
1986 std::size_t size = stack_ctx.size - sizeof( object_t);
1987 BOOST_ASSERT( 0 != size);
1988 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
1989 BOOST_ASSERT( 0 != sp);
1990 // placement new for internal coroutine
1991 impl_ = new ( sp) object_t(
1992 boost::forward< Fn >( fn), attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
1993 BOOST_ASSERT( impl_);
1994 }
1995 #else
1996 template< typename Arg >
1997 template< typename Fn >
1998 push_coroutine< Arg >::push_coroutine( Fn fn,
1999 attributes const& attrs) :
2000 impl_( 0)
2001 {
2002 // create a stack-context
2003 stack_context stack_ctx;
2004 stack_allocator stack_alloc;
2005 // allocate the coroutine-stack
2006 stack_alloc.allocate( stack_ctx, attrs.size);
2007 BOOST_ASSERT( 0 != stack_ctx.sp);
2008 // typedef of internal coroutine-type
2009 typedef detail::push_coroutine_object<
2010 pull_coroutine< Arg >, Arg, Fn, stack_allocator
2011 > object_t;
2012 // reserve space on top of coroutine-stack for internal coroutine-type
2013 std::size_t size = stack_ctx.size - sizeof( object_t);
2014 BOOST_ASSERT( 0 != size);
2015 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2016 BOOST_ASSERT( 0 != sp);
2017 // placement new for internal coroutine
2018 impl_ = new ( sp) object_t(
2019 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2020 BOOST_ASSERT( impl_);
2021 }
2022
2023 template< typename Arg >
2024 template< typename Fn, typename StackAllocator >
2025 push_coroutine< Arg >::push_coroutine( Fn fn,
2026 attributes const& attrs,
2027 StackAllocator stack_alloc) :
2028 impl_( 0)
2029 {
2030 // create a stack-context
2031 stack_context stack_ctx;
2032 // allocate the coroutine-stack
2033 stack_alloc.allocate( stack_ctx, attrs.size);
2034 BOOST_ASSERT( 0 != stack_ctx.sp);
2035 // typedef of internal coroutine-type
2036 typedef detail::push_coroutine_object<
2037 pull_coroutine< Arg >, Arg, Fn, StackAllocator
2038 > object_t;
2039 // reserve space on top of coroutine-stack for internal coroutine-type
2040 std::size_t size = stack_ctx.size - sizeof( object_t);
2041 BOOST_ASSERT( 0 != size);
2042 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2043 BOOST_ASSERT( 0 != sp);
2044 // placement new for internal coroutine
2045 impl_ = new ( sp) object_t(
2046 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2047 BOOST_ASSERT( impl_);
2048 }
2049
2050 template< typename Arg >
2051 template< typename Fn >
2052 push_coroutine< Arg & >::push_coroutine( Fn fn,
2053 attributes const& attrs) :
2054 impl_( 0)
2055 {
2056 // create a stack-context
2057 stack_context stack_ctx;
2058 stack_allocator stack_alloc;
2059 // allocate the coroutine-stack
2060 stack_alloc.allocate( stack_ctx, attrs.size);
2061 BOOST_ASSERT( 0 != stack_ctx.sp);
2062 // typedef of internal coroutine-type
2063 typedef detail::push_coroutine_object<
2064 pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
2065 > object_t;
2066 // reserve space on top of coroutine-stack for internal coroutine-type
2067 std::size_t size = stack_ctx.size - sizeof( object_t);
2068 BOOST_ASSERT( 0 != size);
2069 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2070 BOOST_ASSERT( 0 != sp);
2071 // placement new for internal coroutine
2072 impl_ = new ( sp) object_t(
2073 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2074 BOOST_ASSERT( impl_);
2075 }
2076
2077 template< typename Arg >
2078 template< typename Fn, typename StackAllocator >
2079 push_coroutine< Arg & >::push_coroutine( Fn fn,
2080 attributes const& attrs,
2081 StackAllocator stack_alloc) :
2082 impl_( 0)
2083 {
2084 // create a stack-context
2085 stack_context stack_ctx;
2086 // allocate the coroutine-stack
2087 stack_alloc.allocate( stack_ctx, attrs.size);
2088 BOOST_ASSERT( 0 != stack_ctx.sp);
2089 // typedef of internal coroutine-type
2090 typedef detail::push_coroutine_object<
2091 pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
2092 > object_t;
2093 // reserve space on top of coroutine-stack for internal coroutine-type
2094 std::size_t size = stack_ctx.size - sizeof( object_t);
2095 BOOST_ASSERT( 0 != size);
2096 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2097 BOOST_ASSERT( 0 != sp);
2098 // placement new for internal coroutine
2099 impl_ = new ( sp) object_t(
2100 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2101 BOOST_ASSERT( impl_);
2102 }
2103
2104 template< typename Fn >
2105 push_coroutine< void >::push_coroutine( Fn fn,
2106 attributes const& attrs) :
2107 impl_( 0)
2108 {
2109 // create a stack-context
2110 stack_context stack_ctx;
2111 stack_allocator stack_alloc;
2112 // allocate the coroutine-stack
2113 stack_alloc.allocate( stack_ctx, attrs.size);
2114 BOOST_ASSERT( 0 != stack_ctx.sp);
2115 // typedef of internal coroutine-type
2116 typedef detail::push_coroutine_object<
2117 pull_coroutine< void >, void, Fn, stack_allocator
2118 > object_t;
2119 // reserve space on top of coroutine-stack for internal coroutine-type
2120 std::size_t size = stack_ctx.size - sizeof( object_t);
2121 BOOST_ASSERT( 0 != size);
2122 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2123 BOOST_ASSERT( 0 != sp);
2124 // placement new for internal coroutine
2125 impl_ = new ( sp) object_t(
2126 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2127 BOOST_ASSERT( impl_);
2128 }
2129
2130 template< typename Fn, typename StackAllocator >
2131 push_coroutine< void >::push_coroutine( Fn fn,
2132 attributes const& attrs,
2133 StackAllocator stack_alloc) :
2134 impl_( 0)
2135 {
2136 // create a stack-context
2137 stack_context stack_ctx;
2138 // allocate the coroutine-stack
2139 stack_alloc.allocate( stack_ctx, attrs.size);
2140 BOOST_ASSERT( 0 != stack_ctx.sp);
2141 // typedef of internal coroutine-type
2142 typedef detail::push_coroutine_object<
2143 pull_coroutine< void >, void, Fn, StackAllocator
2144 > object_t;
2145 // reserve space on top of coroutine-stack for internal coroutine-type
2146 std::size_t size = stack_ctx.size - sizeof( object_t);
2147 BOOST_ASSERT( 0 != size);
2148 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2149 BOOST_ASSERT( 0 != sp);
2150 // placement new for internal coroutine
2151 impl_ = new ( sp) object_t(
2152 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2153 BOOST_ASSERT( impl_);
2154 }
2155
2156 template< typename Arg >
2157 template< typename Fn >
2158 push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
2159 attributes const& attrs) :
2160 impl_( 0)
2161 {
2162 // create a stack-context
2163 stack_context stack_ctx;
2164 stack_allocator stack_alloc;
2165 // allocate the coroutine-stack
2166 stack_alloc.allocate( stack_ctx, attrs.size);
2167 BOOST_ASSERT( 0 != stack_ctx.sp);
2168 // typedef of internal coroutine-type
2169 typedef detail::push_coroutine_object<
2170 pull_coroutine< Arg >, Arg, Fn, stack_allocator
2171 > object_t;
2172 // reserve space on top of coroutine-stack for internal coroutine-type
2173 std::size_t size = stack_ctx.size - sizeof( object_t);
2174 BOOST_ASSERT( 0 != size);
2175 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2176 BOOST_ASSERT( 0 != sp);
2177 // placement new for internal coroutine
2178 impl_ = new ( sp) object_t(
2179 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2180 BOOST_ASSERT( impl_);
2181 }
2182
2183 template< typename Arg >
2184 template< typename Fn, typename StackAllocator >
2185 push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn,
2186 attributes const& attrs,
2187 StackAllocator stack_alloc) :
2188 impl_( 0)
2189 {
2190 // create a stack-context
2191 stack_context stack_ctx;
2192 // allocate the coroutine-stack
2193 stack_alloc.allocate( stack_ctx, attrs.size);
2194 BOOST_ASSERT( 0 != stack_ctx.sp);
2195 // typedef of internal coroutine-type
2196 typedef detail::push_coroutine_object<
2197 pull_coroutine< Arg >, Arg, Fn, StackAllocator
2198 > object_t;
2199 // reserve space on top of coroutine-stack for internal coroutine-type
2200 std::size_t size = stack_ctx.size - sizeof( object_t);
2201 BOOST_ASSERT( 0 != size);
2202 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2203 BOOST_ASSERT( 0 != sp);
2204 // placement new for internal coroutine
2205 impl_ = new ( sp) object_t(
2206 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2207 BOOST_ASSERT( impl_);
2208 }
2209
2210 template< typename Arg >
2211 template< typename Fn >
2212 push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
2213 attributes const& attrs) :
2214 impl_( 0)
2215 {
2216 // create a stack-context
2217 stack_context stack_ctx;
2218 stack_allocator stack_alloc;
2219 // allocate the coroutine-stack
2220 stack_alloc.allocate( stack_ctx, attrs.size);
2221 BOOST_ASSERT( 0 != stack_ctx.sp);
2222 // typedef of internal coroutine-type
2223 typedef detail::push_coroutine_object<
2224 pull_coroutine< Arg & >, Arg &, Fn, stack_allocator
2225 > object_t;
2226 // reserve space on top of coroutine-stack for internal coroutine-type
2227 std::size_t size = stack_ctx.size - sizeof( object_t);
2228 BOOST_ASSERT( 0 != size);
2229 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2230 BOOST_ASSERT( 0 != sp);
2231 // placement new for internal coroutine
2232 impl_ = new ( sp) object_t(
2233 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2234 BOOST_ASSERT( impl_);
2235 }
2236
2237 template< typename Arg >
2238 template< typename Fn, typename StackAllocator >
2239 push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn,
2240 attributes const& attrs,
2241 StackAllocator stack_alloc) :
2242 impl_( 0)
2243 {
2244 // create a stack-context
2245 stack_context stack_ctx;
2246 // allocate the coroutine-stack
2247 stack_alloc.allocate( stack_ctx, attrs.size);
2248 BOOST_ASSERT( 0 != stack_ctx.sp);
2249 // typedef of internal coroutine-type
2250 typedef detail::push_coroutine_object<
2251 pull_coroutine< Arg & >, Arg &, Fn, StackAllocator
2252 > object_t;
2253 // reserve space on top of coroutine-stack for internal coroutine-type
2254 std::size_t size = stack_ctx.size - sizeof( object_t);
2255 BOOST_ASSERT( 0 != size);
2256 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2257 BOOST_ASSERT( 0 != sp);
2258 // placement new for internal coroutine
2259 impl_ = new ( sp) object_t(
2260 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2261 BOOST_ASSERT( impl_);
2262 }
2263
2264 template< typename Fn >
2265 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
2266 attributes const& attrs) :
2267 impl_( 0)
2268 {
2269 // create a stack-context
2270 stack_context stack_ctx;
2271 stack_allocator stack_alloc;
2272 // allocate the coroutine-stack
2273 stack_alloc.allocate( stack_ctx, attrs.size);
2274 BOOST_ASSERT( 0 != stack_ctx.sp);
2275 // typedef of internal coroutine-type
2276 typedef detail::push_coroutine_object<
2277 pull_coroutine< void >, void, Fn, stack_allocator
2278 > object_t;
2279 // reserve space on top of coroutine-stack for internal coroutine-type
2280 std::size_t size = stack_ctx.size - sizeof( object_t);
2281 BOOST_ASSERT( 0 != size);
2282 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2283 BOOST_ASSERT( 0 != sp);
2284 // placement new for internal coroutine
2285 impl_ = new ( sp) object_t(
2286 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2287 BOOST_ASSERT( impl_);
2288 }
2289
2290 template< typename Fn, typename StackAllocator >
2291 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn,
2292 attributes const& attrs,
2293 StackAllocator stack_alloc) :
2294 impl_( 0)
2295 {
2296 // create a stack-context
2297 stack_context stack_ctx;
2298 // allocate the coroutine-stack
2299 stack_alloc.allocate( stack_ctx, attrs.size);
2300 BOOST_ASSERT( 0 != stack_ctx.sp);
2301 // typedef of internal coroutine-type
2302 typedef detail::push_coroutine_object<
2303 pull_coroutine< void >, void, Fn, StackAllocator
2304 > object_t;
2305 // reserve space on top of coroutine-stack for internal coroutine-type
2306 std::size_t size = stack_ctx.size - sizeof( object_t);
2307 BOOST_ASSERT( 0 != size);
2308 void * sp = static_cast< char * >( stack_ctx.sp) - sizeof( object_t);
2309 BOOST_ASSERT( 0 != sp);
2310 // placement new for internal coroutine
2311 impl_ = new ( sp) object_t(
2312 fn, attrs, detail::preallocated( sp, size, stack_ctx), stack_alloc);
2313 BOOST_ASSERT( impl_);
2314 }
2315 #endif
2316
2317 template< typename R >
2318 void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
2319 { l.swap( r); }
2320
2321 template< typename Arg >
2322 void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
2323 { l.swap( r); }
2324
2325 template< typename R >
2326 typename pull_coroutine< R >::iterator
2327 range_begin( pull_coroutine< R > & c)
2328 { return typename pull_coroutine< R >::iterator( & c); }
2329
2330 template< typename R >
2331 typename pull_coroutine< R >::const_iterator
2332 range_begin( pull_coroutine< R > const& c)
2333 { return typename pull_coroutine< R >::const_iterator( & c); }
2334
2335 template< typename R >
2336 typename pull_coroutine< R >::iterator
2337 range_end( pull_coroutine< R > &)
2338 { return typename pull_coroutine< R >::iterator(); }
2339
2340 template< typename R >
2341 typename pull_coroutine< R >::const_iterator
2342 range_end( pull_coroutine< R > const&)
2343 { return typename pull_coroutine< R >::const_iterator(); }
2344
2345 template< typename Arg >
2346 typename push_coroutine< Arg >::iterator
2347 range_begin( push_coroutine< Arg > & c)
2348 { return typename push_coroutine< Arg >::iterator( & c); }
2349
2350 template< typename Arg >
2351 typename push_coroutine< Arg >::iterator
2352 range_end( push_coroutine< Arg > &)
2353 { return typename push_coroutine< Arg >::iterator(); }
2354
2355 template< typename T >
2356 struct asymmetric_coroutine
2357 {
2358 typedef push_coroutine< T > push_type;
2359 typedef pull_coroutine< T > pull_type;
2360 };
2361
2362 // deprecated
2363 template< typename T >
2364 struct coroutine
2365 {
2366 typedef push_coroutine< T > push_type;
2367 typedef pull_coroutine< T > pull_type;
2368 };
2369
2370 template< typename R >
2371 typename pull_coroutine< R >::iterator
2372 begin( pull_coroutine< R > & c)
2373 { return boost::begin( c); }
2374
2375 template< typename R >
2376 typename pull_coroutine< R >::const_iterator
2377 begin( pull_coroutine< R > const& c)
2378 { return boost::begin( c); }
2379
2380 template< typename R >
2381 typename pull_coroutine< R >::iterator
2382 end( pull_coroutine< R > & c)
2383 { return boost::end( c); }
2384
2385 template< typename R >
2386 typename pull_coroutine< R >::const_iterator
2387 end( pull_coroutine< R > const& c)
2388 { return boost::end( c); }
2389
2390 template< typename R >
2391 typename push_coroutine< R >::iterator
2392 begin( push_coroutine< R > & c)
2393 { return boost::begin( c); }
2394
2395 template< typename R >
2396 typename push_coroutine< R >::iterator
2397 end( push_coroutine< R > & c)
2398 { return boost::end( c); }
2399
2400 }
2401
2402 template< typename Arg >
2403 struct range_mutable_iterator< coroutines::push_coroutine< Arg > >
2404 { typedef typename coroutines::push_coroutine< Arg >::iterator type; };
2405
2406 template< typename R >
2407 struct range_mutable_iterator< coroutines::pull_coroutine< R > >
2408 { typedef typename coroutines::pull_coroutine< R >::iterator type; };
2409
2410 }
2411
2412 #ifdef BOOST_HAS_ABI_HEADERS
2413 # include BOOST_ABI_SUFFIX
2414 #endif
2415
2416 #endif // BOOST_COROUTINES_ASYMMETRIC_COROUTINE_H