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