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