$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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