Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85105 - in trunk: boost/coroutine/v2 boost/coroutine/v2/detail libs/coroutine/example/cpp03 libs/coroutine/example/cpp11
From: oliver.kowalke_at_[hidden]
Date: 2013-07-22 11:03:42


Author: olli
Date: 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013)
New Revision: 85105
URL: http://svn.boost.org/trac/boost/changeset/85105

Log:
coroutine: update of interface

Added:
   trunk/libs/coroutine/example/cpp03/chaining.cpp (contents, props changed)
   trunk/libs/coroutine/example/cpp03/layout.cpp (contents, props changed)
   trunk/libs/coroutine/example/cpp11/layout.cpp (contents, props changed)
Text files modified:
   trunk/boost/coroutine/v2/coroutine.hpp | 1157 ++++++++++++++++++++-------------------
   trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp | 102 +++
   trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp | 27
   trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp | 356 ++++++++++++
   trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp | 97 ---
   trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp | 385 +++++++++++++
   trunk/libs/coroutine/example/cpp03/Jamfile.v2 | 8
   trunk/libs/coroutine/example/cpp03/chaining.cpp | 203 +++++++
   trunk/libs/coroutine/example/cpp03/layout.cpp | 71 ++
   trunk/libs/coroutine/example/cpp03/same_fringe.cpp | 204 ++++--
   trunk/libs/coroutine/example/cpp11/Jamfile.v2 | 4
   trunk/libs/coroutine/example/cpp11/await_emu.cpp | 2
   trunk/libs/coroutine/example/cpp11/layout.cpp | 50 +
   trunk/libs/coroutine/example/cpp11/same_fringe.cpp | 239 +++++---
   14 files changed, 2070 insertions(+), 835 deletions(-)

Modified: trunk/boost/coroutine/v2/coroutine.hpp
==============================================================================
--- trunk/boost/coroutine/v2/coroutine.hpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/boost/coroutine/v2/coroutine.hpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -249,7 +249,7 @@
         return * this;
     }
 #else
- push_coroutine & operator()( Arg arg)
+ push_coroutine & operator()( Arg const& arg)
     {
         BOOST_ASSERT( * this);
 
@@ -537,240 +537,6 @@
     struct const_iterator;
 };
 
-template< typename Arg >
-class push_coroutine< Arg const& >
-{
-private:
- template<
- typename X, typename Y, typename Z, typename V, typename W
- >
- friend class detail::pull_coroutine_object;
-
- typedef detail::push_coroutine_base< Arg const& > base_t;
- typedef typename base_t::ptr_t ptr_t;
-
- struct dummy
- { void nonnull() {} };
-
- typedef void ( dummy::*safe_bool)();
-
- ptr_t impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
-
- template< typename Allocator >
- push_coroutine( detail::coroutine_context const& callee,
- bool unwind, bool preserve_fpu,
- Allocator const& alloc) :
- impl_()
- {
- typedef detail::push_coroutine_caller<
- Arg const&, Allocator
- > caller_t;
- typename caller_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) caller_t(
- callee, unwind, preserve_fpu, a) );
- }
-
-public:
- push_coroutine() BOOST_NOEXCEPT :
- impl_()
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-#ifdef BOOST_MSVC
- typedef void ( * coroutine_fn) ( pull_coroutine< Arg const& > &);
-
- explicit push_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< coroutine_fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-
- template< typename StackAllocator >
- explicit push_coroutine( coroutine_fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< coroutine_fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-
- template< typename StackAllocator, typename Allocator >
- explicit push_coroutine( coroutine_fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< coroutine_fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-#endif
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-#else
- template< typename Fn >
- explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0);
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0);
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit push_coroutine( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0);
-
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0);
-#endif
-
- push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
- impl_()
- { swap( other); }
-
- push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
- {
- push_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- bool empty() const BOOST_NOEXCEPT
- { return ! impl_; }
-
- operator safe_bool() const BOOST_NOEXCEPT
- { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
-
- bool operator!() const BOOST_NOEXCEPT
- { return empty() || impl_->is_complete(); }
-
- void swap( push_coroutine & other) BOOST_NOEXCEPT
- { impl_.swap( other.impl_); }
-
- push_coroutine & operator()( Arg const& arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->push( arg);
- return * this;
- }
-
- class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void >
- {
- private:
- push_coroutine< Arg const& > * c_;
-
- public:
- iterator() :
- c_( 0)
- {}
-
- explicit iterator( push_coroutine< Arg const& > * c) :
- c_( c)
- {}
-
- iterator & operator=( Arg const& a)
- {
- BOOST_ASSERT( c_);
- if ( ! ( * c_)( a) ) c_ = 0;
- return * this;
- }
-
- bool operator==( iterator const& other)
- { return other.c_ == c_; }
-
- bool operator!=( iterator const& other)
- { return other.c_ != c_; }
-
- iterator & operator*()
- { return * this; }
-
- iterator & operator++()
- { return * this; }
- };
-
- struct const_iterator;
-};
-
 template<>
 class push_coroutine< void >
 {
@@ -1475,8 +1241,8 @@
     };
 };
 
-template<>
-class pull_coroutine< void >
+template< typename R >
+class pull_coroutine< R & >
 {
 private:
     template<
@@ -1484,8 +1250,8 @@
>
     friend class detail::push_coroutine_object;
 
- typedef detail::pull_coroutine_base< void > base_t;
- typedef base_t::ptr_t ptr_t;
+ typedef detail::pull_coroutine_base< R & > base_t;
+ typedef typename base_t::ptr_t ptr_t;
 
     struct dummy
     { void nonnull() {} };
@@ -1499,17 +1265,18 @@
     template< typename Allocator >
     pull_coroutine( detail::coroutine_context const& callee,
                     bool unwind, bool preserve_fpu,
- Allocator const& alloc) :
+ Allocator const& alloc,
+ optional< R * > const& result) :
         impl_()
     {
         typedef detail::pull_coroutine_caller<
- void, Allocator
+ R &, Allocator
> caller_t;
         typename caller_t::allocator_t a( alloc);
         impl_ = ptr_t(
             // placement new
             ::new( a.allocate( 1) ) caller_t(
- callee, unwind, preserve_fpu, a) );
+ callee, unwind, preserve_fpu, a, result) );
     }
 
 public:
@@ -1519,24 +1286,24 @@
 
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
 #ifdef BOOST_MSVC
- typedef void ( * coroutine_fn) ( push_coroutine< void > &);
+ typedef void ( * coroutine_fn) ( push_coroutine< R & > &);
 
     explicit pull_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
                stack_allocator const& stack_alloc =
                     stack_allocator(),
                std::allocator< pull_coroutine > const& alloc =
                     std::allocator< pull_coroutine >(),
- disable_if<
+ typename disable_if<
                    is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
                    dummy *
>::type = 0) :
         impl_()
     {
         typedef detail::pull_coroutine_object<
- void, coroutine_fn, stack_allocator, std::allocator< pull_coroutine >,
- push_coroutine< void >
+ R &, coroutine_fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
> object_t;
- object_t::allocator_t a( alloc);
+ typename object_t::allocator_t a( alloc);
         impl_ = ptr_t(
             // placement new
             ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
@@ -1547,17 +1314,17 @@
                StackAllocator const& stack_alloc,
                std::allocator< pull_coroutine > const& alloc =
                     std::allocator< pull_coroutine >(),
- disable_if<
+ typename disable_if<
                    is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
                    dummy *
>::type = 0) :
         impl_()
     {
         typedef detail::pull_coroutine_object<
- void, coroutine_fn, StackAllocator, std::allocator< pull_coroutine >,
- push_coroutine< void >
+ R &, coroutine_fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
> object_t;
- object_t::allocator_t a( alloc);
+ typename object_t::allocator_t a( alloc);
         impl_ = ptr_t(
             // placement new
             ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
@@ -1567,15 +1334,515 @@
     explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
                StackAllocator const& stack_alloc,
                Allocator const& alloc,
- disable_if<
+ typename disable_if<
                    is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
                    dummy *
>::type = 0) :
         impl_()
     {
         typedef detail::pull_coroutine_object<
- void, coroutine_fn, StackAllocator, Allocator,
- push_coroutine< void >
+ R &, coroutine_fn, StackAllocator, Allocator,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+#endif
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+#else
+ template< typename Fn >
+ explicit pull_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+#endif
+
+ pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
+ {
+ pull_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( pull_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ pull_coroutine & operator()()
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->pull();
+ return * this;
+ }
+
+ bool has_result() const
+ {
+ BOOST_ASSERT( ! empty() );
+
+ return impl_->has_result();
+ }
+
+ R & get() const
+ {
+ BOOST_ASSERT( has_result() );
+
+ return impl_->get();
+ }
+
+ class iterator : public std::iterator< std::input_iterator_tag, R >
+ {
+ private:
+ pull_coroutine< R & > * c_;
+ optional< R & > val_;
+
+ void fetch_()
+ {
+ BOOST_ASSERT( c_);
+
+ if ( ! c_->has_result() )
+ {
+ c_ = 0;
+ val_ = none;
+ return;
+ }
+ val_ = c_->get();
+ }
+
+ void increment_()
+ {
+ BOOST_ASSERT( c_);
+ BOOST_ASSERT( * c_);
+
+ ( * c_)();
+ fetch_();
+ }
+
+ public:
+ typedef typename iterator::pointer pointer_t;
+ typedef typename iterator::reference reference_t;
+
+ iterator() :
+ c_( 0), val_()
+ {}
+
+ explicit iterator( pull_coroutine< R & > * c) :
+ c_( c), val_()
+ { fetch_(); }
+
+ iterator( iterator const& other) :
+ c_( other.c_), val_( other.val_)
+ {}
+
+ iterator & operator=( iterator const& other)
+ {
+ if ( this == & other) return * this;
+ c_ = other.c_;
+ val_ = other.val_;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_ && other.val_ == val_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_ || other.val_ != val_; }
+
+ iterator & operator++()
+ {
+ increment_();
+ return * this;
+ }
+
+ iterator operator++( int)
+ {
+ iterator tmp( * this);
+ ++*this;
+ return tmp;
+ }
+
+ reference_t operator*() const
+ { return const_cast< optional< R & > & >( val_).get(); }
+
+ pointer_t operator->() const
+ { return const_cast< optional< R & > & >( val_).get_ptr(); }
+ };
+
+ class const_iterator : public std::iterator< std::input_iterator_tag, R >
+ {
+ private:
+ pull_coroutine< R & > * c_;
+ optional< R & > val_;
+
+ void fetch_()
+ {
+ BOOST_ASSERT( c_);
+
+ if ( ! c_->has_result() )
+ {
+ c_ = 0;
+ val_ = none;
+ return;
+ }
+ val_ = c_->get();
+ }
+
+ void increment_()
+ {
+ BOOST_ASSERT( c_);
+ BOOST_ASSERT( * c_);
+
+ ( * c_)();
+ fetch_();
+ }
+
+ public:
+ typedef typename const_iterator::pointer pointer_t;
+ typedef typename const_iterator::reference reference_t;
+
+ const_iterator() :
+ c_( 0), val_()
+ {}
+
+ explicit const_iterator( pull_coroutine< R & > const* c) :
+ c_( const_cast< pull_coroutine< R & > * >( c) ), val_()
+ { fetch_(); }
+
+ const_iterator( const_iterator const& other) :
+ c_( other.c_), val_( other.val_)
+ {}
+
+ const_iterator & operator=( const_iterator const& other)
+ {
+ if ( this == & other) return * this;
+ c_ = other.c_;
+ val_ = other.val_;
+ return * this;
+ }
+
+ bool operator==( const_iterator const& other)
+ { return other.c_ == c_ && other.val_ == val_; }
+
+ bool operator!=( const_iterator const& other)
+ { return other.c_ != c_ || other.val_ != val_; }
+
+ const_iterator & operator++()
+ {
+ increment_();
+ return * this;
+ }
+
+ const_iterator operator++( int)
+ {
+ const_iterator tmp( * this);
+ ++*this;
+ return tmp;
+ }
+
+ reference_t operator*() const
+ { return val_.get(); }
+
+ pointer_t operator->() const
+ { return val_.get_ptr(); }
+ };
+};
+
+template<>
+class pull_coroutine< void >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::push_coroutine_object;
+
+ typedef detail::pull_coroutine_base< void > base_t;
+ typedef base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
+
+ template< typename Allocator >
+ pull_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_caller<
+ void, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ pull_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+ typedef void ( * coroutine_fn) ( push_coroutine< void > &);
+
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, coroutine_fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename StackAllocator >
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, coroutine_fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, coroutine_fn, StackAllocator, Allocator,
+ push_coroutine< void >
> object_t;
         object_t::allocator_t a( alloc);
         impl_ = ptr_t(
@@ -1843,70 +2110,8 @@
     impl_()
 {
     typedef detail::push_coroutine_object<
- Arg, coroutine_fn, StackAllocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename StackAllocator, typename Allocator >
-push_coroutine< Arg >::push_coroutine( coroutine_fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< coroutine_fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg, coroutine_fn, StackAllocator, Allocator,
- pull_coroutine< Arg >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
- stack_allocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc,
- typename disable_if<
- is_same< typename decay< coroutine_fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg &, coroutine_fn, stack_allocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg & >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename StackAllocator >
-push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc,
- typename disable_if<
- is_same< typename decay< coroutine_fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg &, coroutine_fn, StackAllocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg & >
+ Arg, coroutine_fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
> object_t;
     typename object_t::allocator_t a( alloc);
     impl_ = ptr_t(
@@ -1916,7 +2121,7 @@
 
 template< typename Arg >
 template< typename StackAllocator, typename Allocator >
-push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
+push_coroutine< Arg >::push_coroutine( coroutine_fn fn, attributes const& attr,
            StackAllocator const& stack_alloc,
            Allocator const& alloc,
            typename disable_if<
@@ -1926,8 +2131,8 @@
     impl_()
 {
     typedef detail::push_coroutine_object<
- Arg &, coroutine_fn, StackAllocator, Allocator,
- pull_coroutine< Arg & >
+ Arg, coroutine_fn, StackAllocator, Allocator,
+ pull_coroutine< Arg >
> object_t;
     typename object_t::allocator_t a( alloc);
     impl_ = ptr_t(
@@ -1936,7 +2141,7 @@
 }
 
 template< typename Arg >
-push_coroutine< Arg const& >::push_coroutine( coroutine_fn fn, attributes const& attr,
+push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
            stack_allocator const& stack_alloc,
            std::allocator< push_coroutine > const& alloc,
            typename disable_if<
@@ -1946,8 +2151,8 @@
     impl_()
 {
     typedef detail::push_coroutine_object<
- Arg const&, coroutine_fn, stack_allocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg const& >
+ Arg &, coroutine_fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
> object_t;
     typename object_t::allocator_t a( alloc);
     impl_ = ptr_t(
@@ -1957,7 +2162,7 @@
 
 template< typename Arg >
 template< typename StackAllocator >
-push_coroutine< Arg const& >::push_coroutine( coroutine_fn fn, attributes const& attr,
+push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
            StackAllocator const& stack_alloc,
            std::allocator< push_coroutine > const& alloc,
            typename disable_if<
@@ -1967,8 +2172,8 @@
     impl_()
 {
     typedef detail::push_coroutine_object<
- Arg const&, coroutine_fn, StackAllocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg const& >
+ Arg &, coroutine_fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
> object_t;
     typename object_t::allocator_t a( alloc);
     impl_ = ptr_t(
@@ -1978,7 +2183,7 @@
 
 template< typename Arg >
 template< typename StackAllocator, typename Allocator >
-push_coroutine< Arg const& >::push_coroutine( coroutine_fn fn, attributes const& attr,
+push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
            StackAllocator const& stack_alloc,
            Allocator const& alloc,
            typename disable_if<
@@ -1988,8 +2193,8 @@
     impl_()
 {
     typedef detail::push_coroutine_object<
- Arg const&, coroutine_fn, StackAllocator, Allocator,
- pull_coroutine< Arg const& >
+ Arg &, coroutine_fn, StackAllocator, Allocator,
+ pull_coroutine< Arg & >
> object_t;
     typename object_t::allocator_t a( alloc);
     impl_ = ptr_t(
@@ -2182,69 +2387,6 @@
         ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
 }
 
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- stack_allocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, stack_allocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, StackAllocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator, typename Allocator >
-push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, StackAllocator, Allocator,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
-}
-
 template< typename Fn >
 push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
            stack_allocator const& stack_alloc,
@@ -2538,7 +2680,7 @@
 
 template< typename Arg >
 template< typename Fn, typename StackAllocator, typename Allocator >
-push_coroutine<Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
            StackAllocator const& stack_alloc,
            Allocator const& alloc,
            typename disable_if<
@@ -2557,132 +2699,6 @@
         ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
 }
 
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg const& >::push_coroutine( Fn fn, attributes const& attr,
- stack_allocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc,
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, stack_allocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg const& >::push_coroutine( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc,
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, StackAllocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator, typename Allocator >
-push_coroutine< Arg const& >::push_coroutine( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, StackAllocator, Allocator,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename Fn >
-push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- stack_allocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, stack_allocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator >
-push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, StackAllocator, std::allocator< push_coroutine >,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
-}
-
-template< typename Arg >
-template< typename Fn, typename StackAllocator, typename Allocator >
-push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type) :
- impl_()
-{
- typedef detail::push_coroutine_object<
- Arg const&, Fn, StackAllocator, Allocator,
- pull_coroutine< Arg const& >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
-}
-
 template< typename Fn >
 push_coroutine< void >::push_coroutine( Fn fn, attributes const& attr,
            stack_allocator const& stack_alloc,
@@ -2836,30 +2852,6 @@
 range_end( pull_coroutine< R > const&)
 { return typename pull_coroutine< R >::const_iterator(); }
 
-template< typename R >
-inline
-typename pull_coroutine< R >::iterator
-begin( pull_coroutine< R > & c)
-{ return boost::begin( c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::iterator
-end( pull_coroutine< R > & c)
-{ return boost::end( c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::const_iterator
-begin( pull_coroutine< R > const& c)
-{ return boost::const_begin( c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::const_iterator
-end( pull_coroutine< R > const& c)
-{ return boost::const_end( c); }
-
 template< typename Arg >
 inline
 typename push_coroutine< Arg >::iterator
@@ -2884,31 +2876,6 @@
 range_end( push_coroutine< Arg > const&)
 { return typename push_coroutine< Arg >::const_iterator(); }
 
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::iterator
-begin( push_coroutine< Arg > & c)
-{ return boost::begin( c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::iterator
-end( push_coroutine< Arg > & c)
-{ return boost::end( c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::const_iterator
-begin( push_coroutine< Arg > const& c)
-{ return boost::const_begin( c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::const_iterator
-end( push_coroutine< Arg > const& c)
-{ return boost::const_end( c); }
-
-
 template< typename T >
 struct coroutine
 {
@@ -2936,6 +2903,58 @@
 
 }
 
+namespace std {
+
+template< typename R >
+inline
+typename boost::coroutines::pull_coroutine< R >::iterator
+begin( boost::coroutines::pull_coroutine< R > & c)
+{ return boost::begin( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::pull_coroutine< R >::iterator
+end( boost::coroutines::pull_coroutine< R > & c)
+{ return boost::end( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::pull_coroutine< R >::const_iterator
+begin( boost::coroutines::pull_coroutine< R > const& c)
+{ return boost::const_begin( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::pull_coroutine< R >::const_iterator
+end( boost::coroutines::pull_coroutine< R > const& c)
+{ return boost::const_end( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::push_coroutine< R >::iterator
+begin( boost::coroutines::push_coroutine< R > & c)
+{ return boost::begin( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::push_coroutine< R >::iterator
+end( boost::coroutines::push_coroutine< R > & c)
+{ return boost::end( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::push_coroutine< R >::const_iterator
+begin( boost::coroutines::push_coroutine< R > const& c)
+{ return boost::const_begin( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::push_coroutine< R >::const_iterator
+end( boost::coroutines::push_coroutine< R > const& c)
+{ return boost::const_end( c); }
+
+}
+
 #ifdef BOOST_HAS_ABI_HEADERS
 # include BOOST_ABI_SUFFIX
 #endif

Modified: trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -136,6 +136,108 @@
     }
 };
 
+template< typename R >
+class pull_coroutine_base< R & > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< pull_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class push_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+ optional< R * > result_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ pull_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx),
+ result_()
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ pull_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ optional< R * > const& result) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee),
+ result_( result)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void pull()
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< R & > hldr_to( & caller_);
+ holder< R & > * hldr_from(
+ reinterpret_cast< holder< R & > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ result_ = hldr_from->data;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ bool has_result() const
+ { return result_; }
+
+ R & get() const
+ {
+ BOOST_ASSERT( has_result() );
+
+ return * result_.get();
+ }
+};
+
 template<>
 class pull_coroutine_base< void > : private noncopyable
 {

Modified: trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -48,6 +48,33 @@
     }
 };
 
+template< typename R, typename Allocator >
+class pull_coroutine_caller< R &, Allocator > : public pull_coroutine_base< R & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_caller< R &, Allocator >
+ >::other allocator_t;
+
+ pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu,
+ allocator_t const& alloc, optional< R * > const& data) BOOST_NOEXCEPT :
+ pull_coroutine_base< R & >( callee, unwind, preserve_fpu, data),
+ alloc_( alloc)
+ {}
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+
+private:
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_caller * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+};
+
 template< typename Allocator >
 class pull_coroutine_caller< void, Allocator > : public pull_coroutine_base< void >
 {

Modified: trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -400,6 +400,362 @@
 };
 
 template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R &, Fn, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R * > * hldr_from(
+ reinterpret_cast< holder< R * > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ this->result_ = hldr_from->data;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ pull_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ pull_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create push_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R &, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R * > * hldr_from(
+ reinterpret_cast< holder< R * > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R &, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R * > * hldr_from(
+ reinterpret_cast< holder< R * > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
     typename Fn,
     typename StackAllocator, typename Allocator,
     typename Caller

Modified: trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -122,7 +122,7 @@
     {
         BOOST_ASSERT( ! is_complete() );
 
- holder< Arg > hldr_to( & caller_, arg);
+ holder< Arg > hldr_to( & caller_, boost::forward( arg) );
         holder< Arg > * hldr_from(
             reinterpret_cast< holder< Arg > * >(
                 hldr_to.ctx->jump(
@@ -135,7 +135,7 @@
         if ( except_) rethrow_exception( except_);
     }
 #else
- void push( Arg arg)
+ void push( Arg const& arg)
     {
         BOOST_ASSERT( ! is_complete() );
 
@@ -244,96 +244,9 @@
     {
         BOOST_ASSERT( ! is_complete() );
 
- holder< Arg & > hldr_to( & caller_, arg);
- holder< Arg & > * hldr_from(
- reinterpret_cast< holder< Arg & > * >(
- hldr_to.ctx->jump(
- callee_,
- reinterpret_cast< intptr_t >( & hldr_to),
- preserve_fpu() ) ) );
- BOOST_ASSERT( hldr_from->ctx);
- callee_ = * hldr_from->ctx;
- if ( hldr_from->force_unwind) throw forced_unwind();
- if ( except_) rethrow_exception( except_);
- }
-};
-
-template< typename Arg >
-class push_coroutine_base< Arg const& > : private noncopyable
-{
-public:
- typedef intrusive_ptr< push_coroutine_base > ptr_t;
-
-private:
- template<
- typename X, typename Y, typename Z, typename V, typename W
- >
- friend class pull_coroutine_object;
-
- unsigned int use_count_;
-
-protected:
- int flags_;
- exception_ptr except_;
- coroutine_context caller_;
- coroutine_context callee_;
-
- virtual void deallocate_object() = 0;
-
-public:
- push_coroutine_base( coroutine_context::ctx_fn fn,
- stack_context * stack_ctx,
- bool unwind, bool preserve_fpu) :
- use_count_( 0),
- flags_( 0),
- except_(),
- caller_(),
- callee_( fn, stack_ctx)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
- }
-
- push_coroutine_base( coroutine_context const& callee,
- bool unwind, bool preserve_fpu) :
- use_count_( 0),
- flags_( 0),
- except_(),
- caller_(),
- callee_( callee)
- {
- if ( unwind) flags_ |= flag_force_unwind;
- if ( preserve_fpu) flags_ |= flag_preserve_fpu;
- }
-
- virtual ~push_coroutine_base()
- {}
-
- bool force_unwind() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_force_unwind); }
-
- bool unwind_requested() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_unwind_stack); }
-
- bool preserve_fpu() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_preserve_fpu); }
-
- bool is_complete() const BOOST_NOEXCEPT
- { return 0 != ( flags_ & flag_complete); }
-
- friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT
- { ++p->use_count_; }
-
- friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT
- { if ( --p->use_count_ == 0) p->deallocate_object(); }
-
- void push( Arg const& arg)
- {
- BOOST_ASSERT( ! is_complete() );
-
- holder< Arg const& > hldr_to( & caller_, arg);
- holder< Arg const& > * hldr_from(
- reinterpret_cast< holder< Arg const& > * >(
+ holder< Arg * > hldr_to( & caller_, & arg);
+ holder< Arg * > * hldr_from(
+ reinterpret_cast< holder< Arg * > * >(
                 hldr_to.ctx->jump(
                     callee_,
                     reinterpret_cast< intptr_t >( & hldr_to),

Modified: trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -429,6 +429,391 @@
 };
 
 template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg &, Fn, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ push_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ push_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg * > * hldr_from(
+ reinterpret_cast< holder< Arg * > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg &, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg * > * hldr_from(
+ reinterpret_cast< holder< Arg * > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg &, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg * > * hldr_from(
+ reinterpret_cast< holder< Arg * > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
     typename Fn,
     typename StackAllocator, typename Allocator,
     typename Caller

Modified: trunk/libs/coroutine/example/cpp03/Jamfile.v2
==============================================================================
--- trunk/libs/coroutine/example/cpp03/Jamfile.v2 Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/libs/coroutine/example/cpp03/Jamfile.v2 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -68,3 +68,11 @@
 exe same_fringe
     : same_fringe.cpp
     ;
+
+exe layout
+ : layout.cpp
+ ;
+
+exe chaining
+ : chaining.cpp
+ ;

Added: trunk/libs/coroutine/example/cpp03/chaining.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/coroutine/example/cpp03/chaining.cpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -0,0 +1,203 @@
+
+// Copyright Nat Goodspeed 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <cctype>
+#include <sstream>
+
+#include <boost/bind.hpp>
+#include <boost/coroutine/all.hpp>
+#include <boost/foreach.hpp>
+
+typedef boost::coroutines::coroutine<std::string> coro_t;
+
+// deliver each line of input stream to sink as a separate string
+void readlines(coro_t::push_type& sink, std::istream& in)
+{
+ std::string line;
+ while (std::getline(in, line))
+ sink(line);
+}
+
+void tokenize(coro_t::push_type& sink, coro_t::pull_type& source)
+{
+ // This tokenizer doesn't happen to be stateful: you could reasonably
+ // implement it with a single call to push each new token downstream. But
+ // I've worked with stateful tokenizers, in which the meaning of input
+ // characters depends in part on their position within the input line. At
+ // the time, I wished for a way to resume at the suspend point!
+ BOOST_FOREACH(std::string line, source)
+ {
+ std::string::size_type pos = 0;
+ while (pos < line.length())
+ {
+ if (line[pos] == '"')
+ {
+ std::string token;
+ ++pos; // skip open quote
+ while (pos < line.length() && line[pos] != '"')
+ token += line[pos++];
+ ++pos; // skip close quote
+ sink(token); // pass token downstream
+ }
+ else if (std::isspace(line[pos]))
+ {
+ ++pos; // outside quotes, ignore whitespace
+ }
+ else if (std::isalpha(line[pos]))
+ {
+ std::string token;
+ while (pos < line.length() && std::isalpha(line[pos]))
+ token += line[pos++];
+ sink(token); // pass token downstream
+ }
+ else // punctuation
+ {
+ sink(std::string(1, line[pos++]));
+ }
+ }
+ }
+}
+
+void only_words(coro_t::push_type& sink, coro_t::pull_type& source)
+{
+ BOOST_FOREACH(std::string token, source)
+ {
+ if (! token.empty() && std::isalpha(token[0]))
+ sink(token);
+ }
+}
+
+void trace(coro_t::push_type& sink, coro_t::pull_type& source)
+{
+ BOOST_FOREACH(std::string token, source)
+ {
+ std::cout << "trace: '" << token << "'\n";
+ sink(token);
+ }
+}
+
+struct FinalEOL
+{
+ ~FinalEOL() { std::cout << std::endl; }
+};
+
+void layout(coro_t::pull_type& source, int num, int width)
+{
+ // Finish the last line when we leave by whatever means
+ FinalEOL eol;
+
+ // Pull values from upstream, lay them out 'num' to a line
+ for (;;)
+ {
+ for (int i = 0; i < num; ++i)
+ {
+ // when we exhaust the input, stop
+ if (! source)
+ return;
+
+ std::cout << std::setw(width) << source.get();
+ // now that we've handled this item, advance to next
+ source();
+ }
+ // after 'num' items, line break
+ std::cout << std::endl;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ // For example purposes, instead of having a separate text file in the
+ // local filesystem, construct an istringstream to read.
+ std::string data(
+ "This is the first line.\n"
+ "This, the second.\n"
+ "The third has \"a phrase\"!\n"
+ );
+
+ {
+ std::cout << "\nreadlines:\n";
+ std::istringstream infile(data);
+ // Each coroutine-function has a small, specific job to do. Instead of
+ // adding conditional logic to a large, complex input function, the
+ // caller composes smaller functions into the desired processing
+ // chain.
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tracer(boost::bind(trace, _1, boost::ref(reader)));
+ BOOST_FOREACH(std::string line, tracer)
+ {
+ std::cout << "got: " << line << "\n";
+ }
+ }
+
+ {
+ std::cout << "\ncompose a chain:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::pull_type tracer(boost::bind(trace, _1, boost::ref(tokenizer)));
+ BOOST_FOREACH(std::string token, tracer)
+ {
+ // just iterate, we're already pulling through tracer
+ }
+ }
+
+ {
+ std::cout << "\nfilter:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::pull_type filter(boost::bind(only_words, _1, boost::ref(tokenizer)));
+ coro_t::pull_type tracer(boost::bind(trace, _1, boost::ref(filter)));
+ BOOST_FOREACH(std::string token, tracer)
+ {
+ // just iterate, we're already pulling through tracer
+ }
+ }
+
+ {
+ std::cout << "\nlayout() as coroutine::push_type:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::pull_type filter(boost::bind(only_words, _1, boost::ref(tokenizer)));
+ coro_t::push_type writer(boost::bind(layout, _1, 5, 15));
+ BOOST_FOREACH(std::string token, filter)
+ {
+ writer(token);
+ }
+ }
+
+ {
+ std::cout << "\ncalling layout() directly:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::pull_type filter(boost::bind(only_words, _1, boost::ref(tokenizer)));
+ // Because of the symmetry of the API, we can directly call layout()
+ // instead of using it as a coroutine-function.
+ layout(filter, 5, 15);
+ }
+
+ {
+ std::cout << "\nfiltering output:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::push_type writer(boost::bind(layout, _1, 5, 15));
+ // Because of the symmetry of the API, we can use any of these
+ // chaining functions in a push_type coroutine chain as well.
+ coro_t::push_type filter(boost::bind(only_words, boost::ref(writer), _1));
+ BOOST_FOREACH(std::string token, tokenizer)
+ {
+ filter(token);
+ }
+ }
+
+ return 0;
+}

Added: trunk/libs/coroutine/example/cpp03/layout.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/coroutine/example/cpp03/layout.cpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -0,0 +1,71 @@
+
+// Copyright Nat Goodspeed 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <string>
+#include <utility>
+
+#include <boost/assign/list_of.hpp>
+#include <boost/bind.hpp>
+#include <boost/coroutine/all.hpp>
+#include <boost/range.hpp>
+
+struct FinalEOL
+{
+ ~FinalEOL() { std::cout << std::endl; }
+};
+
+void layout(boost::coroutines::coroutine<std::string>::pull_type& in, int num, int width)
+{
+ // Finish the last line when we leave by whatever means
+ FinalEOL eol;
+
+ // Pull values from upstream, lay them out 'num' to a line
+ for (;;)
+ {
+ for (int i = 0; i < num; ++i)
+ {
+ // when we exhaust the input, stop
+ if (! in)
+ return;
+
+ std::cout << std::setw(width) << in.get();
+ // now that we've handled this item, advance to next
+ in();
+ }
+ // after 'num' items, line break
+ std::cout << std::endl;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ std::vector<std::string> words = boost::assign::list_of
+ ("peas")
+ ("porridge")
+ ("hot")
+ ("peas")
+ ("porridge")
+ ("cold")
+ ("peas")
+ ("porridge")
+ ("in")
+ ("the")
+ ("pot")
+ ("nine")
+ ("days")
+ ("old")
+ ;
+
+ boost::coroutines::coroutine<std::string>::push_type writer(
+ boost::bind(layout, _1, 5, 15));
+
+ std::copy(boost::begin(words), boost::end(words), boost::begin(writer));
+
+ return 0;
+}

Modified: trunk/libs/coroutine/example/cpp03/same_fringe.cpp
==============================================================================
--- trunk/libs/coroutine/example/cpp03/same_fringe.cpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/libs/coroutine/example/cpp03/same_fringe.cpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -1,5 +1,5 @@
 
-// Copyright Oliver Kowalke 2009.
+// Copyright Nat Goodspeed 2013.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -7,109 +7,155 @@
 #include <cstddef>
 #include <cstdlib>
 #include <iostream>
+#include <iterator>
 #include <string>
 #include <utility>
 
 #include <boost/bind.hpp>
 #include <boost/range.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/coroutine/all.hpp>
 
-#include "tree.h"
-
-std::pair< node::ptr_t, node::ptr_t > create_eq_trees()
-{
- branch::ptr_t tree1 = branch::create(
- leaf::create( "A"),
- branch::create(
- leaf::create( "B"),
- leaf::create( "C") ) );
-
- branch::ptr_t tree2 = branch::create(
- branch::create(
- leaf::create( "A"),
- leaf::create( "B") ),
- leaf::create( "C") );
-
- return std::make_pair( tree1, tree2);
-}
-
-std::pair< node::ptr_t, node::ptr_t > create_diff_trees()
+struct node
 {
- branch::ptr_t tree1 = branch::create(
- leaf::create( "A"),
- branch::create(
- leaf::create( "B"),
- leaf::create( "C") ) );
-
- branch::ptr_t tree2 = branch::create(
- branch::create(
- leaf::create( "A"),
- leaf::create( "X") ),
- leaf::create( "C") );
+ typedef boost::shared_ptr< node > ptr_t;
 
- return std::make_pair( tree1, tree2);
-}
+ // Each tree node has an optional left subtree, an optional right subtree
+ // and a value of its own. The value is considered to be between the left
+ // subtree and the right.
+ ptr_t left, right;
+ std::string value;
+
+ // construct leaf
+ node(const std::string& v):
+ left(), right(), value(v)
+ {}
+ // construct nonleaf
+ node(ptr_t l, const std::string& v, ptr_t r):
+ left(l), right(r), value(v)
+ {}
 
-#ifdef BOOST_COROUTINES_UNIDIRECT
-bool match_trees( boost::coroutines::coroutine< leaf & >::pull_type & c1,
- boost::coroutines::coroutine< leaf & >::pull_type & c2)
-{
- typedef boost::range_iterator< boost::coroutines::coroutine< leaf & >::pull_type >::type iterator_t;
- iterator_t i1( boost::begin( c1) );
- iterator_t e1( boost::end( c1) );
- iterator_t i2( boost::begin( c2) );
- return std::equal( i1, e1, i2);
-}
-
-int main()
-{
+ static ptr_t create(const std::string& v)
     {
- std::pair< node::ptr_t, node::ptr_t > pt = create_eq_trees();
- boost::coroutines::coroutine< leaf & >::pull_type te1( boost::bind( enumerate_leafs, _1, pt.first) );
- boost::coroutines::coroutine< leaf & >::pull_type te2( boost::bind( enumerate_leafs, _1, pt.second) );
- bool result = match_trees( te1, te2);
- std::cout << std::boolalpha << "eq. trees matched == " << result << std::endl;
+ return ptr_t(new node(v));
     }
+
+ static ptr_t create(ptr_t l, const std::string& v, ptr_t r)
     {
- std::pair< node::ptr_t, node::ptr_t > pt = create_diff_trees();
- boost::coroutines::coroutine< leaf & >::pull_type te1( boost::bind( enumerate_leafs, _1, pt.first) );
- boost::coroutines::coroutine< leaf & >::pull_type te2( boost::bind( enumerate_leafs, _1, pt.second) );
- bool result = match_trees( te1, te2);
- std::cout << std::boolalpha << "diff. trees matched == " << result << std::endl;
+ return ptr_t(new node(l, v, r));
     }
+};
 
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
-}
-#else
-bool match_trees( coro_t & c1, coro_t & c2)
+node::ptr_t create_left_tree_from(const std::string& root)
 {
- typedef boost::range_iterator< coro_t >::type iterator_t;
- iterator_t i1( boost::begin( c1) );
- iterator_t e1( boost::end( c1) );
- iterator_t i2( boost::begin( c2) );
- return std::equal( i1, e1, i2);
+ /* --------
+ root
+ / \
+ b e
+ / \
+ a c
+ -------- */
+ return node::create(
+ node::create(
+ node::create("a"),
+ "b",
+ node::create("c")),
+ root,
+ node::create("e"));
+}
+
+node::ptr_t create_right_tree_from(const std::string& root)
+{
+ /* --------
+ root
+ / \
+ a d
+ / \
+ c e
+ -------- */
+ return node::create(
+ node::create("a"),
+ root,
+ node::create(
+ node::create("c"),
+ "d",
+ node::create("e")));
+}
+
+// recursively walk the tree, delivering values in order
+void traverse(node::ptr_t n,boost::coroutines::coroutine<std::string>::push_type& out)
+{
+ if (n->left) traverse(n->left,out);
+ out(n->value);
+ if (n->right) traverse(n->right,out);
 }
 
 int main()
 {
     {
- std::pair< node::ptr_t, node::ptr_t > pt = create_eq_trees();
- coro_t te1( boost::bind( enumerate_leafs, _1, pt.first) );
- coro_t te2( boost::bind( enumerate_leafs, _1, pt.second) );
- bool result = match_trees( te1, te2);
- std::cout << std::boolalpha << "eq. trees matched == " << result << std::endl;
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ boost::bind(traverse, left_d, _1));
+ std::cout << "left tree from d:\n";
+ std::copy(boost::begin(left_d_reader),
+ boost::end(left_d_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ boost::bind(traverse, right_b, _1));
+ std::cout << "right tree from b:\n";
+ std::copy(boost::begin(right_b_reader),
+ boost::end(right_b_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ boost::bind(traverse, right_x, _1));
+ std::cout << "right tree from x:\n";
+ std::copy(boost::begin(right_x_reader),
+ boost::end(right_x_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
     }
+
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ boost::bind(traverse, left_d, _1));
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ boost::bind(traverse, right_b, _1));
+
+ std::cout << "left tree from d == right tree from b? "
+ << std::boolalpha
+ << std::equal(boost::begin(left_d_reader),
+ boost::end(left_d_reader),
+ boost::begin(right_b_reader))
+ << std::endl;
+ }
+
     {
- std::pair< node::ptr_t, node::ptr_t > pt = create_diff_trees();
- coro_t te1( boost::bind( enumerate_leafs, _1, pt.first) );
- coro_t te2( boost::bind( enumerate_leafs, _1, pt.second) );
- bool result = match_trees( te1, te2);
- std::cout << std::boolalpha << "diff. trees matched == " << result << std::endl;
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ boost::bind(traverse, left_d, _1));
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ boost::bind(traverse, right_x, _1));
+
+ std::cout << "left tree from d == right tree from x? "
+ << std::boolalpha
+ << std::equal(boost::begin(left_d_reader),
+ boost::end(left_d_reader),
+ boost::begin(right_x_reader))
+ << std::endl;
     }
 
     std::cout << "Done" << std::endl;
 
     return EXIT_SUCCESS;
 }
-#endif

Modified: trunk/libs/coroutine/example/cpp11/Jamfile.v2
==============================================================================
--- trunk/libs/coroutine/example/cpp11/Jamfile.v2 Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/libs/coroutine/example/cpp11/Jamfile.v2 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -52,3 +52,7 @@
 exe await_emu
     : await_emu.cpp
     ;
+
+exe layout
+ : layout.cpp
+ ;

Modified: trunk/libs/coroutine/example/cpp11/await_emu.cpp
==============================================================================
--- trunk/libs/coroutine/example/cpp11/await_emu.cpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/libs/coroutine/example/cpp11/await_emu.cpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -192,6 +192,6 @@
     for(auto i=0; i!=5; ++i)
         fs.push_back( asynchronous([i]{ return foo(i+1); }) );
 
- BOOST_FOREACH(auto &&f, fs)
+ for(auto &&f : fs)
         cout << await f << ":\tafter end" << endl;
 }

Added: trunk/libs/coroutine/example/cpp11/layout.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/coroutine/example/cpp11/layout.cpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -0,0 +1,50 @@
+
+// Copyright Nat Goodspeed 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <string>
+#include <utility>
+
+#include <boost/coroutine/all.hpp>
+
+struct FinalEOL{
+ ~FinalEOL(){
+ std::cout << std::endl;
+ }
+};
+
+int main(int argc,char* argv[]){
+ std::vector<std::string> words{
+ "peas", "porridge", "hot", "peas",
+ "porridge", "cold", "peas", "porridge",
+ "in", "the", "pot", "nine",
+ "days", "old" };
+
+ int num=5,width=15;
+ boost::coroutines::coroutine<std::string>::push_type writer(
+ [&](boost::coroutines::coroutine<std::string>::pull_type& in){
+ // finish the last line when we leave by whatever means
+ FinalEOL eol;
+ // pull values from upstream, lay them out 'num' to a line
+ for (;;){
+ for(int i=0;i<num;++i){
+ // when we exhaust the input, stop
+ if(!in) return;
+ std::cout << std::setw(width) << in.get();
+ // now that we've handled this item, advance to next
+ in();
+ }
+ // after 'num' items, line break
+ std::cout << std::endl;
+ }
+ });
+
+ std::copy(std::begin(words),std::end(words),std::begin(writer));
+
+ return 0;
+}

Modified: trunk/libs/coroutine/example/cpp11/same_fringe.cpp
==============================================================================
--- trunk/libs/coroutine/example/cpp11/same_fringe.cpp Mon Jul 22 08:51:09 2013 (r85104)
+++ trunk/libs/coroutine/example/cpp11/same_fringe.cpp 2013-07-22 11:03:42 EDT (Mon, 22 Jul 2013) (r85105)
@@ -1,125 +1,176 @@
 
-// Copyright Oliver Kowalke 2009.
+// Copyright Nat Goodspeed 2013.
 // Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
+// (See accompanying file LICENSEstd::placeholders::_1_0.txt or copy at
+// http://www.boost.org/LICENSEstd::placeholders::_1_0.txt)
 
 #include <cstddef>
 #include <cstdlib>
 #include <iostream>
+#include <iterator>
+#include <string>
+#include <utility>
 
 #include <boost/coroutine/all.hpp>
 
-#include "tree.h"
-
-node::ptr_t create_tree1()
-{
- return branch::create(
- leaf::create( "A"),
- branch::create(
- leaf::create( "B"),
- leaf::create( "C") ) );
-}
-
-node::ptr_t create_tree2()
-{
- return branch::create(
- branch::create(
- leaf::create( "A"),
- leaf::create( "B") ),
- leaf::create( "C") );
-}
-
-#ifdef BOOST_COROUTINES_UNIDIRECT
-class coro_visitor : public visitor
+struct node
 {
-private:
- boost::coroutines::coroutine< leaf& >::push_type & c_;
+ typedef std::shared_ptr< node > ptr_t;
 
-public:
- coro_visitor( boost::coroutines::coroutine< leaf& >::push_type & c) :
- c_( c)
+ // Each tree node has an optional left subtree, an optional right subtree
+ // and a value of its own. The value is considered to be between the left
+ // subtree and the right.
+ ptr_t left, right;
+ std::string value;
+
+ // construct leaf
+ node(const std::string& v):
+ left(),right(),value(v)
+ {}
+ // construct nonleaf
+ node(ptr_t l, const std::string& v, ptr_t r):
+ left(l),right(r),value(v)
     {}
 
- void visit( branch & b)
+ static ptr_t create(const std::string& v)
     {
- if ( b.left) b.left->accept( * this);
- if ( b.right) b.right->accept( * this);
+ return ptr_t(new node(v));
     }
 
- void visit( leaf & l)
- { c_( l); }
+ static ptr_t create(ptr_t l, const std::string& v, ptr_t r)
+ {
+ return ptr_t(new node(l, v, r));
+ }
 };
 
-int main()
+node::ptr_t create_left_tree_from(const std::string& root)
 {
- node::ptr_t t1 = create_tree1();
- boost::coroutines::coroutine< leaf& >::pull_type c1(
- [&]( boost::coroutines::coroutine< leaf & >::push_type & c) {
- coro_visitor v( c);
- t1->accept( v);
- });
-
- node::ptr_t t2 = create_tree2();
- boost::coroutines::coroutine< leaf& >::pull_type c2(
- [&]( boost::coroutines::coroutine< leaf & >::push_type & c) {
- coro_visitor v( c);
- t2->accept( v);
- });
-
- bool result = std::equal(
- boost::begin( c1),
- boost::end( c1),
- boost::begin( c2) );
-
- std::cout << std::boolalpha << "same fringe == " << result << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
+ /* --------
+ root
+ / \
+ b e
+ / \
+ a c
+ -------- */
+
+ return node::create(
+ node::create(
+ node::create("a"),
+ "b",
+ node::create("c")),
+ root,
+ node::create("e"));
 }
-#else
-class coro_visitor : public visitor
+
+node::ptr_t create_right_tree_from(const std::string& root)
 {
-private:
- boost::coroutines::coroutine< void( leaf&) > & c_;
+ /* --------
+ root
+ / \
+ a d
+ / \
+ c e
+ -------- */
+
+ return node::create(
+ node::create("a"),
+ root,
+ node::create(
+ node::create("c"),
+ "d",
+ node::create("e")));
+}
 
-public:
- coro_visitor( boost::coroutines::coroutine< void( leaf&) > & c) :
- c_( c)
- {}
+// recursively walk the tree, delivering values in order
+void traverse(node::ptr_t n, boost::coroutines::coroutine<std::string>::push_type& out)
+{
+ if (n->left)
+ traverse(n->left,out);
+ out(n->value);
+ if (n->right)
+ traverse(n->right,out);
+}
 
- void visit( branch & b)
+int main()
+{
     {
- if ( b.left) b.left->accept( * this);
- if ( b.right) b.right->accept( * this);
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(left_d,out);
+ });
+ std::cout << "left tree from d:\n";
+ std::copy(std::begin(left_d_reader),
+ std::end(left_d_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(right_b,out);
+ });
+ std::cout << "right tree from b:\n";
+ std::copy(std::begin(right_b_reader),
+ std::end(right_b_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(right_x,out);
+ });
+ std::cout << "right tree from x:\n";
+ std::copy(std::begin(right_x_reader),
+ std::end(right_x_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
     }
 
- void visit( leaf & l)
- { c_( l); }
-};
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(left_d,out);
+ });
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(right_b,out);
+ });
+
+ std::cout << "left tree from d == right tree from b? "
+ << std::boolalpha
+ << std::equal(std::begin(left_d_reader),
+ std::end(left_d_reader),
+ std::begin(right_b_reader))
+ << std::endl;
+ }
 
-int main()
-{
- node::ptr_t t1 = create_tree1();
- boost::coroutines::coroutine< leaf&() > c1(
- [&]( boost::coroutines::coroutine< void( leaf &) > & c) {
- coro_visitor v( c);
- t1->accept( v);
- });
-
- node::ptr_t t2 = create_tree2();
- boost::coroutines::coroutine< leaf&() > c2(
- [&]( boost::coroutines::coroutine< void( leaf &) > & c) {
- coro_visitor v( c);
- t2->accept( v);
- });
-
- bool result = std::equal(
- boost::begin( c1),
- boost::end( c1),
- boost::begin( c2) );
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(left_d,out);
+ });
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(right_x,out);
+ });
+
+ std::cout << "left tree from d == right tree from x? "
+ << std::boolalpha
+ << std::equal(std::begin(left_d_reader),
+ std::end(left_d_reader),
+ std::begin(right_x_reader))
+ << std::endl;
+ }
 
- std::cout << std::boolalpha << "same fringe == " << result << "\nDone" << std::endl;
+ std::cout << "Done" << std::endl;
 
     return EXIT_SUCCESS;
 }
-#endif


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk