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 #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>
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 
38 namespace boost {
39 namespace coroutines {
40 
41 template< typename R >
42 class pull_coroutine;
43 
44 template< typename Arg >
45 class push_coroutine
46 {
47 private:
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 
push_coroutine(detail::synthesized_t::flag_t,impl_type & impl)61     explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
62         impl_( & impl)
63     { BOOST_ASSERT( impl_); }
64 
65 public:
push_coroutine()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 
~push_coroutine()110     ~push_coroutine()
111     {
112         if ( 0 != impl_)
113         {
114             impl_->destroy();
115             impl_ = 0;
116         }
117     }
118 
push_coroutine(BOOST_RV_REF (push_coroutine)other)119     push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
120         impl_( 0)
121     { swap( other); }
122 
operator =(BOOST_RV_REF (push_coroutine)other)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 
operator !() const132     bool operator!() const BOOST_NOEXCEPT
133     { return 0 == impl_ || impl_->is_complete(); }
134 
swap(push_coroutine & other)135     void swap( push_coroutine & other) BOOST_NOEXCEPT
136     { std::swap( impl_, other.impl_); }
137 
operator ()(Arg arg)138     push_coroutine & operator()( Arg arg)
139     {
140         BOOST_ASSERT( * this);
141 
142         impl_->push( arg);
143         return * this;
144     }
145 
146     class iterator
147     {
148     private:
149        push_coroutine< Arg >    *   c_;
150 
151     public:
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 
iterator()158         iterator() :
159            c_( 0)
160         {}
161 
iterator(push_coroutine<Arg> * c)162         explicit iterator( push_coroutine< Arg > * c) :
163             c_( c)
164         {}
165 
operator =(Arg a)166         iterator & operator=( Arg a)
167         {
168             BOOST_ASSERT( c_);
169             if ( ! ( * c_)( a) ) c_ = 0;
170             return * this;
171         }
172 
operator ==(iterator const & other) const173         bool operator==( iterator const& other) const
174         { return other.c_ == c_; }
175 
operator !=(iterator const & other) const176         bool operator!=( iterator const& other) const
177         { return other.c_ != c_; }
178 
operator *()179         iterator & operator*()
180         { return * this; }
181 
operator ++()182         iterator & operator++()
183         { return * this; }
184     };
185 
186     struct const_iterator;
187 };
188 
189 template< typename Arg >
190 class push_coroutine< Arg & >
191 {
192 private:
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 
push_coroutine(detail::synthesized_t::flag_t,impl_type & impl)206     explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
207         impl_( & impl)
208     { BOOST_ASSERT( impl_); }
209 
210 public:
push_coroutine()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 
~push_coroutine()255     ~push_coroutine()
256     {
257         if ( 0 != impl_)
258         {
259             impl_->destroy();
260             impl_ = 0;
261         }
262     }
263 
push_coroutine(BOOST_RV_REF (push_coroutine)other)264     push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
265         impl_( 0)
266     { swap( other); }
267 
operator =(BOOST_RV_REF (push_coroutine)other)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 
operator !() const277     bool operator!() const BOOST_NOEXCEPT
278     { return 0 == impl_ || impl_->is_complete(); }
279 
swap(push_coroutine & other)280     void swap( push_coroutine & other) BOOST_NOEXCEPT
281     { std::swap( impl_, other.impl_); }
282 
operator ()(Arg & arg)283     push_coroutine & operator()( Arg & arg)
284     {
285         BOOST_ASSERT( * this);
286 
287         impl_->push( arg);
288         return * this;
289     }
290 
291     class iterator
292     {
293     private:
294        push_coroutine< Arg & >  *   c_;
295 
296     public:
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 
iterator()303         iterator() :
304            c_( 0)
305         {}
306 
iterator(push_coroutine<Arg &> * c)307         explicit iterator( push_coroutine< Arg & > * c) :
308             c_( c)
309         {}
310 
operator =(Arg & a)311         iterator & operator=( Arg & a)
312         {
313             BOOST_ASSERT( c_);
314             if ( ! ( * c_)( a) ) c_ = 0;
315             return * this;
316         }
317 
operator ==(iterator const & other) const318         bool operator==( iterator const& other) const
319         { return other.c_ == c_; }
320 
operator !=(iterator const & other) const321         bool operator!=( iterator const& other) const
322         { return other.c_ != c_; }
323 
operator *()324         iterator & operator*()
325         { return * this; }
326 
operator ++()327         iterator & operator++()
328         { return * this; }
329     };
330 
331     struct const_iterator;
332 };
333 
334 template<>
335 class push_coroutine< void >
336 {
337 private:
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 
push_coroutine(detail::synthesized_t::flag_t,impl_type & impl)351     explicit push_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
352         impl_( & impl)
353     { BOOST_ASSERT( impl_); }
354 
355 public:
push_coroutine()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 
~push_coroutine()400     ~push_coroutine()
401     {
402         if ( 0 != impl_)
403         {
404             impl_->destroy();
405             impl_ = 0;
406         }
407     }
408 
push_coroutine(BOOST_RV_REF (push_coroutine)other)409     inline push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
410         impl_( 0)
411     { swap( other); }
412 
operator =(BOOST_RV_REF (push_coroutine)other)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 
operator !() const422     inline bool operator!() const BOOST_NOEXCEPT
423     { return 0 == impl_ || impl_->is_complete(); }
424 
swap(push_coroutine & other)425     inline void swap( push_coroutine & other) BOOST_NOEXCEPT
426     { std::swap( impl_, other.impl_); }
427 
operator ()()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 
442 template< typename R >
443 class pull_coroutine
444 {
445 private:
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 
pull_coroutine(detail::synthesized_t::flag_t,impl_type & impl)459     explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
460         impl_( & impl)
461     { BOOST_ASSERT( impl_); }
462 
463 public:
pull_coroutine()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 
pull_coroutine(coroutine_fn fn,attributes const & attrs=attributes ())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 >
pull_coroutine(coroutine_fn fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs=attributes ())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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(Fn fn,attributes const & attrs=attributes ())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 >
pull_coroutine(Fn fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs=attributes ())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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)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 
~pull_coroutine()688     ~pull_coroutine()
689     {
690         if ( 0 != impl_)
691         {
692             impl_->destroy();
693             impl_ = 0;
694         }
695     }
696 
pull_coroutine(BOOST_RV_REF (pull_coroutine)other)697     pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
698         impl_( 0)
699     { swap( other); }
700 
operator =(BOOST_RV_REF (pull_coroutine)other)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 
operator !() const710     bool operator!() const BOOST_NOEXCEPT
711     { return 0 == impl_ || impl_->is_complete(); }
712 
swap(pull_coroutine & other)713     void swap( pull_coroutine & other) BOOST_NOEXCEPT
714     { std::swap( impl_, other.impl_); }
715 
operator ()()716     pull_coroutine & operator()()
717     {
718         BOOST_ASSERT( * this);
719 
720         impl_->pull();
721         return * this;
722     }
723 
get() const724     R get() const
725     {
726         BOOST_ASSERT( 0 != impl_);
727 
728         return impl_->get();
729     }
730 
731     class iterator
732     {
733     private:
734         pull_coroutine< R > *   c_;
735         R                   *   val_;
736 
fetch_()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 
increment_()750         void increment_()
751         {
752             BOOST_ASSERT( c_);
753             BOOST_ASSERT( * c_);
754 
755             ( * c_)();
756             fetch_();
757         }
758 
759     public:
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;
768 
iterator()769         iterator() :
770             c_( 0), val_( 0)
771         {}
772 
iterator(pull_coroutine<R> * c)773         explicit iterator( pull_coroutine< R > * c) :
774             c_( c), val_( 0)
775         { fetch_(); }
776 
iterator(iterator const & other)777         iterator( iterator const& other) :
778             c_( other.c_), val_( other.val_)
779         {}
780 
operator =(iterator const & other)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 
operator ==(iterator const & other) const789         bool operator==( iterator const& other) const
790         { return other.c_ == c_ && other.val_ == val_; }
791 
operator !=(iterator const & other) const792         bool operator!=( iterator const& other) const
793         { return other.c_ != c_ || other.val_ != val_; }
794 
operator ++()795         iterator & operator++()
796         {
797             increment_();
798             return * this;
799         }
800 
801         iterator operator++( int);
802 
operator *() const803         reference_t operator*() const
804         {
805             if ( ! val_)
806                 boost::throw_exception(
807                     invalid_result() );
808             return * val_;
809         }
810 
operator ->() const811         pointer_t operator->() const
812         {
813             if ( ! val_)
814                 boost::throw_exception(
815                     invalid_result() );
816             return val_;
817         }
818     };
819 
820     class const_iterator
821     {
822     private:
823         pull_coroutine< R > *   c_;
824         R                   *   val_;
825 
fetch_()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 
increment_()839         void increment_()
840         {
841             BOOST_ASSERT( c_);
842             BOOST_ASSERT( * c_);
843 
844             ( * c_)();
845             fetch_();
846         }
847 
848     public:
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;
857 
const_iterator()858         const_iterator() :
859             c_( 0), val_( 0)
860         {}
861 
const_iterator(pull_coroutine<R> const * c)862         explicit const_iterator( pull_coroutine< R > const* c) :
863             c_( const_cast< pull_coroutine< R > * >( c) ),
864             val_( 0)
865         { fetch_(); }
866 
const_iterator(const_iterator const & other)867         const_iterator( const_iterator const& other) :
868             c_( other.c_), val_( other.val_)
869         {}
870 
operator =(const_iterator const & other)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 
operator ==(const_iterator const & other) const879         bool operator==( const_iterator const& other) const
880         { return other.c_ == c_ && other.val_ == val_; }
881 
operator !=(const_iterator const & other) const882         bool operator!=( const_iterator const& other) const
883         { return other.c_ != c_ || other.val_ != val_; }
884 
operator ++()885         const_iterator & operator++()
886         {
887             increment_();
888             return * this;
889         }
890 
891         const_iterator operator++( int);
892 
operator *() const893         reference_t operator*() const
894         {
895             if ( ! val_)
896                 boost::throw_exception(
897                     invalid_result() );
898             return * val_;
899         }
900 
operator ->() const901         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 
914 template< typename R >
915 class pull_coroutine< R & >
916 {
917 private:
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 
pull_coroutine(detail::synthesized_t::flag_t,impl_type & impl)931     explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
932         impl_( & impl)
933     { BOOST_ASSERT( impl_); }
934 
935 public:
pull_coroutine()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 
pull_coroutine(coroutine_fn fn,attributes const & attrs=attributes ())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 >
pull_coroutine(coroutine_fn fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs=attributes ())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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(Fn fn,attributes const & attrs=attributes ())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 >
pull_coroutine(Fn fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs=attributes ())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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)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 
~pull_coroutine()1160     ~pull_coroutine()
1161     {
1162         if ( 0 != impl_)
1163         {
1164             impl_->destroy();
1165             impl_ = 0;
1166         }
1167     }
1168 
pull_coroutine(BOOST_RV_REF (pull_coroutine)other)1169     pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
1170         impl_( 0)
1171     { swap( other); }
1172 
operator =(BOOST_RV_REF (pull_coroutine)other)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 
operator !() const1182     bool operator!() const BOOST_NOEXCEPT
1183     { return 0 == impl_ || impl_->is_complete(); }
1184 
swap(pull_coroutine & other)1185     void swap( pull_coroutine & other) BOOST_NOEXCEPT
1186     { std::swap( impl_, other.impl_); }
1187 
operator ()()1188     pull_coroutine & operator()()
1189     {
1190         BOOST_ASSERT( * this);
1191 
1192         impl_->pull();
1193         return * this;
1194     }
1195 
get() const1196     R & get() const
1197     { return impl_->get(); }
1198 
1199     class iterator
1200     {
1201     private:
1202         pull_coroutine< R & >   *   c_;
1203         R                       *   val_;
1204 
fetch_()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 
increment_()1218         void increment_()
1219         {
1220             BOOST_ASSERT( c_);
1221             BOOST_ASSERT( * c_);
1222 
1223             ( * c_)();
1224             fetch_();
1225         }
1226 
1227     public:
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;
1236 
iterator()1237         iterator() :
1238             c_( 0), val_( 0)
1239         {}
1240 
iterator(pull_coroutine<R &> * c)1241         explicit iterator( pull_coroutine< R & > * c) :
1242             c_( c), val_( 0)
1243         { fetch_(); }
1244 
iterator(iterator const & other)1245         iterator( iterator const& other) :
1246             c_( other.c_), val_( other.val_)
1247         {}
1248 
operator =(iterator const & other)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 
operator ==(iterator const & other) const1257         bool operator==( iterator const& other) const
1258         { return other.c_ == c_ && other.val_ == val_; }
1259 
operator !=(iterator const & other) const1260         bool operator!=( iterator const& other) const
1261         { return other.c_ != c_ || other.val_ != val_; }
1262 
operator ++()1263         iterator & operator++()
1264         {
1265             increment_();
1266             return * this;
1267         }
1268 
1269         iterator operator++( int);
1270 
operator *() const1271         reference_t operator*() const
1272         {
1273             if ( ! val_)
1274                 boost::throw_exception(
1275                     invalid_result() );
1276             return * val_;
1277         }
1278 
operator ->() const1279         pointer_t operator->() const
1280         {
1281             if ( ! val_)
1282                 boost::throw_exception(
1283                     invalid_result() );
1284             return val_;
1285         }
1286     };
1287 
1288     class const_iterator
1289     {
1290     private:
1291         pull_coroutine< R & >   *   c_;
1292         R                       *   val_;
1293 
fetch_()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 
increment_()1307         void increment_()
1308         {
1309             BOOST_ASSERT( c_);
1310             BOOST_ASSERT( * c_);
1311 
1312             ( * c_)();
1313             fetch_();
1314         }
1315 
1316     public:
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;
1325 
const_iterator()1326         const_iterator() :
1327             c_( 0), val_( 0)
1328         {}
1329 
const_iterator(pull_coroutine<R &> const * c)1330         explicit const_iterator( pull_coroutine< R & > const* c) :
1331             c_( const_cast< pull_coroutine< R & > * >( c) ),
1332             val_( 0)
1333         { fetch_(); }
1334 
const_iterator(const_iterator const & other)1335         const_iterator( const_iterator const& other) :
1336             c_( other.c_), val_( other.val_)
1337         {}
1338 
operator =(const_iterator const & other)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 
operator ==(const_iterator const & other) const1347         bool operator==( const_iterator const& other) const
1348         { return other.c_ == c_ && other.val_ == val_; }
1349 
operator !=(const_iterator const & other) const1350         bool operator!=( const_iterator const& other) const
1351         { return other.c_ != c_ || other.val_ != val_; }
1352 
operator ++()1353         const_iterator & operator++()
1354         {
1355             increment_();
1356             return * this;
1357         }
1358 
1359         const_iterator operator++( int);
1360 
operator *() const1361         reference_t operator*() const
1362         {
1363             if ( ! val_)
1364                 boost::throw_exception(
1365                     invalid_result() );
1366             return * val_;
1367         }
1368 
operator ->() const1369         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 
1382 template<>
1383 class pull_coroutine< void >
1384 {
1385 private:
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 
pull_coroutine(detail::synthesized_t::flag_t,impl_type & impl)1399     explicit pull_coroutine( detail::synthesized_t::flag_t, impl_type & impl) :
1400         impl_( & impl)
1401     { BOOST_ASSERT( impl_); }
1402 
1403 public:
pull_coroutine()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 
pull_coroutine(coroutine_fn fn,attributes const & attrs=attributes ())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 >
pull_coroutine(coroutine_fn fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs=attributes ())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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(Fn fn,attributes const & attrs=attributes ())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 >
pull_coroutine(Fn fn,attributes const & attrs,StackAllocator stack_alloc)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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs=attributes ())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 >
pull_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)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 
~pull_coroutine()1628     ~pull_coroutine()
1629     {
1630         if ( 0 != impl_)
1631         {
1632             impl_->destroy();
1633             impl_ = 0;
1634         }
1635     }
1636 
pull_coroutine(BOOST_RV_REF (pull_coroutine)other)1637     inline pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
1638         impl_( 0)
1639     { swap( other); }
1640 
operator =(BOOST_RV_REF (pull_coroutine)other)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 
operator !() const1650     inline bool operator!() const BOOST_NOEXCEPT
1651     { return 0 == impl_ || impl_->is_complete(); }
1652 
swap(pull_coroutine & other)1653     inline void swap( pull_coroutine & other) BOOST_NOEXCEPT
1654     { std::swap( impl_, other.impl_); }
1655 
operator ()()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
1670 template< typename Arg >
push_coroutine(coroutine_fn fn,attributes const & attrs)1671 push_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 
1696 template< typename Arg >
1697 template< typename StackAllocator >
push_coroutine(coroutine_fn fn,attributes const & attrs,StackAllocator stack_alloc)1698 push_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 
1723 template< typename Arg >
push_coroutine(coroutine_fn fn,attributes const & attrs)1724 push_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 
1749 template< typename Arg >
1750 template< typename StackAllocator >
push_coroutine(coroutine_fn fn,attributes const & attrs,StackAllocator stack_alloc)1751 push_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 
push_coroutine(coroutine_fn fn,attributes const & attrs)1776 inline 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 
1801 template< typename StackAllocator >
push_coroutine(coroutine_fn fn,attributes const & attrs,StackAllocator stack_alloc)1802 push_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
1827 template< typename Arg >
1828 template< typename Fn >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs)1829 push_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 
1854 template< typename Arg >
1855 template< typename Fn, typename StackAllocator >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)1856 push_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 
1881 template< typename Arg >
1882 template< typename Fn >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs)1883 push_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 
1908 template< typename Arg >
1909 template< typename Fn, typename StackAllocator >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)1910 push_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 
1935 template< typename Fn >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs)1936 push_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 
1961 template< typename Fn, typename StackAllocator >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)1962 push_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
1987 template< typename Arg >
1988 template< typename Fn >
push_coroutine(Fn fn,attributes const & attrs)1989 push_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 
2014 template< typename Arg >
2015 template< typename Fn, typename StackAllocator >
push_coroutine(Fn fn,attributes const & attrs,StackAllocator stack_alloc)2016 push_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 
2041 template< typename Arg >
2042 template< typename Fn >
push_coroutine(Fn fn,attributes const & attrs)2043 push_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 
2068 template< typename Arg >
2069 template< typename Fn, typename StackAllocator >
push_coroutine(Fn fn,attributes const & attrs,StackAllocator stack_alloc)2070 push_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 
2095 template< typename Fn >
push_coroutine(Fn fn,attributes const & attrs)2096 push_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 
2121 template< typename Fn, typename StackAllocator >
push_coroutine(Fn fn,attributes const & attrs,StackAllocator stack_alloc)2122 push_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 
2147 template< typename Arg >
2148 template< typename Fn >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs)2149 push_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 
2174 template< typename Arg >
2175 template< typename Fn, typename StackAllocator >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)2176 push_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 
2201 template< typename Arg >
2202 template< typename Fn >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs)2203 push_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 
2228 template< typename Arg >
2229 template< typename Fn, typename StackAllocator >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)2230 push_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 
2255 template< typename Fn >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs)2256 push_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 
2281 template< typename Fn, typename StackAllocator >
push_coroutine(BOOST_RV_REF (Fn)fn,attributes const & attrs,StackAllocator stack_alloc)2282 push_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 
2308 template< typename R >
swap(pull_coroutine<R> & l,pull_coroutine<R> & r)2309 void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
2310 { l.swap( r); }
2311 
2312 template< typename Arg >
swap(push_coroutine<Arg> & l,push_coroutine<Arg> & r)2313 void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
2314 { l.swap( r); }
2315 
2316 template< typename R >
2317 typename pull_coroutine< R >::iterator
range_begin(pull_coroutine<R> & c)2318 range_begin( pull_coroutine< R > & c)
2319 { return typename pull_coroutine< R >::iterator( & c); }
2320 
2321 template< typename R >
2322 typename pull_coroutine< R >::const_iterator
range_begin(pull_coroutine<R> const & c)2323 range_begin( pull_coroutine< R > const& c)
2324 { return typename pull_coroutine< R >::const_iterator( & c); }
2325 
2326 template< typename R >
2327 typename pull_coroutine< R >::iterator
range_end(pull_coroutine<R> &)2328 range_end( pull_coroutine< R > &)
2329 { return typename pull_coroutine< R >::iterator(); }
2330 
2331 template< typename R >
2332 typename pull_coroutine< R >::const_iterator
range_end(pull_coroutine<R> const &)2333 range_end( pull_coroutine< R > const&)
2334 { return typename pull_coroutine< R >::const_iterator(); }
2335 
2336 template< typename Arg >
2337 typename push_coroutine< Arg >::iterator
range_begin(push_coroutine<Arg> & c)2338 range_begin( push_coroutine< Arg > & c)
2339 { return typename push_coroutine< Arg >::iterator( & c); }
2340 
2341 template< typename Arg >
2342 typename push_coroutine< Arg >::iterator
range_end(push_coroutine<Arg> &)2343 range_end( push_coroutine< Arg > &)
2344 { return typename push_coroutine< Arg >::iterator(); }
2345 
2346 template< typename T >
2347 struct asymmetric_coroutine
2348 {
2349     typedef push_coroutine< T > push_type;
2350     typedef pull_coroutine< T > pull_type;
2351 };
2352 
2353 // deprecated
2354 template< typename T >
2355 struct coroutine
2356 {
2357     typedef push_coroutine< T > push_type;
2358     typedef pull_coroutine< T > pull_type;
2359 };
2360 
2361 template< typename R >
2362 typename pull_coroutine< R >::iterator
begin(pull_coroutine<R> & c)2363 begin( pull_coroutine< R > & c)
2364 { return boost::begin( c); }
2365 
2366 template< typename R >
2367 typename pull_coroutine< R >::const_iterator
begin(pull_coroutine<R> const & c)2368 begin( pull_coroutine< R > const& c)
2369 { return boost::begin( c); }
2370 
2371 template< typename R >
2372 typename pull_coroutine< R >::iterator
end(pull_coroutine<R> & c)2373 end( pull_coroutine< R > & c)
2374 { return boost::end( c); }
2375 
2376 template< typename R >
2377 typename pull_coroutine< R >::const_iterator
end(pull_coroutine<R> const & c)2378 end( pull_coroutine< R > const& c)
2379 { return boost::end( c); }
2380 
2381 template< typename R >
2382 typename push_coroutine< R >::iterator
begin(push_coroutine<R> & c)2383 begin( push_coroutine< R > & c)
2384 { return boost::begin( c); }
2385 
2386 template< typename R >
2387 typename push_coroutine< R >::iterator
end(push_coroutine<R> & c)2388 end( push_coroutine< R > & c)
2389 { return boost::end( c); }
2390 
2391 }
2392 
2393 // forward declaration of Boost.Range traits to break dependency on it
2394 template<typename C, typename Enabler>
2395 struct range_mutable_iterator;
2396 
2397 template<typename C, typename Enabler>
2398 struct range_const_iterator;
2399 
2400 template< typename Arg >
2401 struct range_mutable_iterator< coroutines::push_coroutine< Arg >, void >
2402 { typedef typename coroutines::push_coroutine< Arg >::iterator type; };
2403 
2404 template< typename R >
2405 struct range_mutable_iterator< coroutines::pull_coroutine< R >, void >
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
2415