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