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