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