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