Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84657 - in trunk: boost/coroutine boost/coroutine/detail boost/coroutine/v1 boost/coroutine/v1/detail boost/coroutine/v2 boost/coroutine/v2/detail libs/coroutine/doc libs/coroutine/example libs/coroutine/example/c++11 libs/coroutine/performance libs/coroutine/test
From: oliver.kowalke_at_[hidden]
Date: 2013-06-06 13:26:46


Author: olli
Date: 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013)
New Revision: 84657
URL: http://svn.boost.org/trac/boost/changeset/84657

Log:
coroutine: new push/pull interface

Added:
   trunk/libs/coroutine/doc/old.qbk (contents, props changed)
   trunk/libs/coroutine/doc/unidirect.qbk (contents, props changed)
Deleted:
   trunk/boost/coroutine/v2/detail/coroutine_object.hpp
   trunk/boost/coroutine/v2/pull_corotuine.hpp
   trunk/boost/coroutine/v2/push_coroutine.hpp
Text files modified:
   trunk/boost/coroutine/coroutine.hpp | 2
   trunk/boost/coroutine/detail/config.hpp | 4
   trunk/boost/coroutine/v1/coroutine.hpp | 6
   trunk/boost/coroutine/v1/detail/arg.hpp | 6
   trunk/boost/coroutine/v1/detail/coroutine_base.hpp | 6
   trunk/boost/coroutine/v1/detail/coroutine_base_resume.hpp | 6
   trunk/boost/coroutine/v1/detail/coroutine_caller.hpp | 6
   trunk/boost/coroutine/v1/detail/coroutine_get.hpp | 6
   trunk/boost/coroutine/v1/detail/coroutine_object.hpp | 6
   trunk/boost/coroutine/v1/detail/coroutine_op.hpp | 6
   trunk/boost/coroutine/v2/coroutine.hpp | 6
   /dev/null | 423 -------------------
   trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp | 6
   trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp | 6
   trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp | 6
   trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp | 6
   trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp | 6
   trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp | 6
   /dev/null | 355 ----------------
   /dev/null | 357 ----------------
   trunk/libs/coroutine/doc/coro.qbk | 5
   trunk/libs/coroutine/doc/coroutine.qbk | 798 ------------------------------------
   trunk/libs/coroutine/doc/old.qbk | 809 ++++++++++++++++++++++++++++++++++++
   trunk/libs/coroutine/doc/unidirect.qbk | 878 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/coroutine/example/c++11/fibonacci.cpp | 2
   trunk/libs/coroutine/example/c++11/same_fringe.cpp | 2
   trunk/libs/coroutine/example/echo.cpp | 2
   trunk/libs/coroutine/example/fibonacci.cpp | 2
   trunk/libs/coroutine/example/parallel.cpp | 2
   trunk/libs/coroutine/example/power.cpp | 2
   trunk/libs/coroutine/example/same_fringe.cpp | 2
   trunk/libs/coroutine/example/segmented_stack.cpp | 2
   trunk/libs/coroutine/example/tree.h | 2
   trunk/libs/coroutine/example/unwind.cpp | 2
   trunk/libs/coroutine/performance/performance.cpp | 2
   trunk/libs/coroutine/test/test_coroutine.cpp | 4
   36 files changed, 1757 insertions(+), 1990 deletions(-)

Modified: trunk/boost/coroutine/coroutine.hpp
==============================================================================
--- trunk/boost/coroutine/coroutine.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/coroutine.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -7,7 +7,7 @@
 #ifndef BOOST_COROUTINES_COROUTINE_H
 #define BOOST_COROUTINES_COROUTINE_H
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 #include <boost/coroutine/v2/coroutine.hpp>
 #else
 #include <boost/coroutine/v1/coroutine.hpp>

Modified: trunk/boost/coroutine/detail/config.hpp
==============================================================================
--- trunk/boost/coroutine/detail/config.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/detail/config.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -46,8 +46,8 @@
 # define BOOST_COROUTINES_SEGMENTS 10
 #endif
 
-#ifndef BOOST_COROUTINES_V1
-# define BOOST_COROUTINES_V2
+#ifndef BOOST_COROUTINES_OLD
+# define BOOST_COROUTINES_UNIDIRECT
 #endif
 
 #endif // BOOST_COROUTINES_DETAIL_CONFIG_H

Modified: trunk/boost/coroutine/v1/coroutine.hpp
==============================================================================
--- trunk/boost/coroutine/v1/coroutine.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v1/coroutine.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V1_COROUTINE_H
-#define BOOST_COROUTINES_V1_COROUTINE_H
+#ifndef BOOST_COROUTINES_OLD_COROUTINE_H
+#define BOOST_COROUTINES_OLD_COROUTINE_H
 
 #include <cstddef>
 #include <memory>
@@ -1427,4 +1427,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V1_COROUTINE_H
+#endif // BOOST_COROUTINES_OLD_COROUTINE_H

Modified: trunk/boost/coroutine/v1/detail/arg.hpp
==============================================================================
--- trunk/boost/coroutine/v1/detail/arg.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v1/detail/arg.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V1_DETAIL_ARG_H
-#define BOOST_COROUTINES_V1_DETAIL_ARG_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_ARG_H
+#define BOOST_COROUTINES_OLD_DETAIL_ARG_H
 
 #include <boost/config.hpp>
 #include <boost/preprocessor/arithmetic/add.hpp>
@@ -59,4 +59,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V1_DETAIL_ARG_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_ARG_H

Modified: trunk/boost/coroutine/v1/detail/coroutine_base.hpp
==============================================================================
--- trunk/boost/coroutine/v1/detail/coroutine_base.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v1/detail/coroutine_base.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_H
 
 #include <boost/assert.hpp>
 #include <boost/config.hpp>
@@ -122,4 +122,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_H

Modified: trunk/boost/coroutine/v1/detail/coroutine_base_resume.hpp
==============================================================================
--- trunk/boost/coroutine/v1/detail/coroutine_base_resume.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v1/detail/coroutine_base_resume.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_RESUME_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_RESUME_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_RESUME_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_RESUME_H
 
 #include <iterator>
 
@@ -234,4 +234,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V1_DETAIL_coroutine_base_resume_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_coroutine_base_resume_H

Modified: trunk/boost/coroutine/v1/detail/coroutine_caller.hpp
==============================================================================
--- trunk/boost/coroutine/v1/detail/coroutine_caller.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v1/detail/coroutine_caller.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_CALLER_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_CALLER_H
 
 #include <boost/config.hpp>
 #include <boost/context/fcontext.hpp>
@@ -54,4 +54,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_CALLER_H

Modified: trunk/boost/coroutine/v1/detail/coroutine_get.hpp
==============================================================================
--- trunk/boost/coroutine/v1/detail/coroutine_get.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v1/detail/coroutine_get.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_GET_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_GET_H
 
 #include <boost/assert.hpp>
 #include <boost/config.hpp>
@@ -51,4 +51,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_GET_H

Modified: trunk/boost/coroutine/v1/detail/coroutine_object.hpp
==============================================================================
--- trunk/boost/coroutine/v1/detail/coroutine_object.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v1/detail/coroutine_object.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OBJECT_H
 
 #include <cstddef>
 
@@ -71,4 +71,4 @@
  #pragma warning (pop)
 #endif
 
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OBJECT_H

Modified: trunk/boost/coroutine/v1/detail/coroutine_op.hpp
==============================================================================
--- trunk/boost/coroutine/v1/detail/coroutine_op.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v1/detail/coroutine_op.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OP_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OP_H
 
 #include <iterator>
 
@@ -323,4 +323,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OP_H

Modified: trunk/boost/coroutine/v2/coroutine.hpp
==============================================================================
--- trunk/boost/coroutine/v2/coroutine.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v2/coroutine.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V2_COROUTINE_H
-#define BOOST_COROUTINES_V2_COROUTINE_H
+#ifndef BOOST_COROUTINES_UNIDIRECT_COROUTINE_H
+#define BOOST_COROUTINES_UNIDIRECT_COROUTINE_H
 
 #include <cstddef>
 #include <iterator>
@@ -2932,4 +2932,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V2_COROUTINE_H
+#endif // BOOST_COROUTINES_UNIDIRECT_COROUTINE_H

Deleted: trunk/boost/coroutine/v2/detail/coroutine_object.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/coroutine_object.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84656)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,423 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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)
-
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
-
-#include <cstddef>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/exception_ptr.hpp>
-#include <boost/move/move.hpp>
-#include <boost/ref.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <boost/type_traits/function_traits.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/exceptions.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/holder.hpp>
-#include <boost/coroutine/detail/param.hpp>
-#include <boost/coroutine/flags.hpp>
-#include <boost/coroutine/stack_context.hpp>
-#include <boost/coroutine/v2/detail/arg.hpp>
-#include <boost/coroutine/v2/detail/coroutine_base.hpp>
-
-template<
- typename Arg,
- typename Fn, typename StackAllocator, typename Allocator
->
-class coroutine_object< Arg, Fn, StackAllocator, Allocator > :
- private stack_tuple< StackAllocator >,
- public coroutine_base
-{
-public:
- typedef typename Allocator::template rebind<
- coroutine_object<
- Arg, Fn, StackAllocator, Allocator
- >
- >::other allocator_t;
-
-private:
- typedef stack_tuple< StackAllocator > pbase_type;
- typedef coroutine_base base_type;
-
- Fn fn_;
- allocator_t alloc_;
-
- static void destroy_( allocator_t & alloc, coroutine_object * p)
- {
- alloc.destroy( p);
- alloc.deallocate( p, 1);
- }
-
- coroutine_object( coroutine_object const&);
- coroutine_object & operator=( 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;
- this->result_ = hldr_from->data;
- if ( this->except_) rethrow_exception( this->except_);
- }
-
- void run_( Caller & c)
- {
- coroutine_context callee;
- coroutine_context caller;
- try
- {
- fn_( c);
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< void > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { this->except_ = current_exception(); }
-
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< void > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void unwind_stack_() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! this->is_complete() );
-
- this->flags_ |= flag_unwind_stack;
- holder< void > 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
- 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< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( forward< Fn >( fn) ),
- alloc_( alloc)
- { enter_(); }
-#else
- coroutine_object( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- allocator_t const& alloc) :
- pbase_type( stack_alloc, attr.size),
- base_type(
- trampoline1< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( fn),
- alloc_( alloc)
- { enter_(); }
-
- 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< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( fn),
- alloc_( alloc)
- { enter_(); }
-#endif
-
- ~coroutine_object()
- {
- if ( ! this->is_complete() && this->force_unwind() )
- unwind_stack_();
- }
-
- void run()
- {
- Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
- run_( c);
- }
-
- void deallocate_object()
- { destroy_( alloc_, this); }
-};
-
-template<
- typename Arg,
- typename Fn, typename StackAllocator, typename Allocator,
- typename Caller,
- typename Result
->
-class coroutine_object< Arg, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > :
- private stack_tuple< StackAllocator >,
- public coroutine_base< Arg >
-{
-public:
- typedef typename Allocator::template rebind<
- coroutine_object<
- Arg, Fn, StackAllocator, Allocator, Caller, Result, 0
- >
- >::other allocator_t;
-
-private:
- typedef stack_tuple< StackAllocator > pbase_type;
- typedef coroutine_base< Arg > base_type;
-
- Fn fn_;
- allocator_t alloc_;
-
- static void destroy_( allocator_t & alloc, coroutine_object * p)
- {
- alloc.destroy( p);
- alloc.deallocate( p, 1);
- }
-
- coroutine_object( coroutine_object const&);
- coroutine_object & operator=( coroutine_object const&);
-
- void enter_()
- {
- holder< Result > * hldr_from(
- reinterpret_cast< holder< Result > * >(
- 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 run_( Caller & c)
- {
- coroutine_context callee;
- coroutine_context caller;
- try
- {
- fn_( c);
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< Result > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { this->except_ = current_exception(); }
-
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< Result > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void unwind_stack_() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! this->is_complete() );
-
- this->flags_ |= flag_unwind_stack;
- holder< void > 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:
- 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< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( fn),
- alloc_( alloc)
- { enter_(); }
-
- ~coroutine_object()
- {
- if ( ! this->is_complete() && this->force_unwind() )
- unwind_stack_();
- }
-
- void run()
- {
- Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
- run_( c);
- }
-
- void deallocate_object()
- { destroy_( alloc_, this); }
-};
-
-template<
- typename Arg,
- typename Fn, typename StackAllocator, typename Allocator,
- typename Caller,
- typename Result
->
-class coroutine_object< Arg, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > :
- private stack_tuple< StackAllocator >,
- public coroutine_base< Arg >
-{
-public:
- typedef typename Allocator::template rebind<
- coroutine_object<
- Arg, Fn, StackAllocator, Allocator, Caller, Result, 0
- >
- >::other allocator_t;
-
-private:
- typedef stack_tuple< StackAllocator > pbase_type;
- typedef coroutine_base< Arg > base_type;
-
- Fn fn_;
- allocator_t alloc_;
-
- static void destroy_( allocator_t & alloc, coroutine_object * p)
- {
- alloc.destroy( p);
- alloc.deallocate( p, 1);
- }
-
- coroutine_object( coroutine_object const&);
- coroutine_object & operator=( coroutine_object const&);
-
- void enter_()
- {
- holder< Result > * hldr_from(
- reinterpret_cast< holder< Result > * >(
- 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 run_( Caller & c)
- {
- coroutine_context callee;
- coroutine_context caller;
- try
- {
- fn_( c);
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< Result > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { this->except_ = current_exception(); }
-
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< Result > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void unwind_stack_() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! this->is_complete() );
-
- this->flags_ |= flag_unwind_stack;
- holder< void > 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:
- 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< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( fn),
- alloc_( alloc)
- { enter_(); }
-
- ~coroutine_object()
- {
- if ( ! this->is_complete() && this->force_unwind() )
- unwind_stack_();
- }
-
- void run()
- {
- Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
- run_( c);
- }
-
- void deallocate_object()
- { destroy_( alloc_, this); }
-};

Modified: trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_BASE_H
-#define BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_BASE_H
+#ifndef BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_BASE_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_BASE_H
 
 #include <boost/assert.hpp>
 #include <boost/config.hpp>
@@ -229,4 +229,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_BASE_H
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_BASE_H

Modified: trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -3,8 +3,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_CALLER_H
-#define BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_CALLER_H
+#ifndef BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_CALLER_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_CALLER_H
 
 #include <boost/config.hpp>
 #include <boost/context/fcontext.hpp>
@@ -81,4 +81,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_CALLER_H
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_CALLER_H

Modified: trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_OBJECT_H
+#ifndef BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_OBJECT_H
 
 #include <cstddef>
 
@@ -765,4 +765,4 @@
  #pragma warning (pop)
 #endif
 
-#endif // BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_OBJECT_H
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_OBJECT_H

Modified: trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_BASE_H
-#define BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_BASE_H
+#ifndef BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_BASE_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_BASE_H
 
 #include <boost/assert.hpp>
 #include <boost/config.hpp>
@@ -438,4 +438,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_BASE_H
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_BASE_H

Modified: trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -3,8 +3,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_CALLER_H
-#define BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_CALLER_H
+#ifndef BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_CALLER_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_CALLER_H
 
 #include <boost/config.hpp>
 #include <boost/context/fcontext.hpp>
@@ -53,4 +53,4 @@
 # include BOOST_ABI_SUFFIX
 #endif
 
-#endif // BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_CALLER_H
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_CALLER_H

Modified: trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp
==============================================================================
--- trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -4,8 +4,8 @@
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_OBJECT_H
+#ifndef BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_OBJECT_H
 
 #include <cstddef>
 
@@ -820,4 +820,4 @@
  #pragma warning (pop)
 #endif
 
-#endif // BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_OBJECT_H
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_OBJECT_H

Deleted: trunk/boost/coroutine/v2/pull_corotuine.hpp
==============================================================================
--- trunk/boost/coroutine/v2/pull_corotuine.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84656)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,355 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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)
-
-#ifndef BOOST_COROUTINES_V2_PULL_COROUTINE_H
-#define BOOST_COROUTINES_V2_PULL_COROUTINE_H
-
-#include <cstddef>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/range.hpp>
-#include <boost/type_traits/decay.hpp>
-#include <boost/type_traits/function_traits.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/utility/result_of.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/stack_allocator.hpp>
-#include <boost/coroutine/v2/pull_coroutine_base.hpp.hpp>
-#include <boost/coroutine/v2/pull_coroutine_object.hpp.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename R >
-class pull_coroutine
-{
-private:
- typedef detail::pull_coroutine_base< R > 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( pull_coroutine)
-
-public:
- pull_coroutine() BOOST_NOEXCEPT :
- impl_()
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- 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 >
- > 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 >
- > 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
- > 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 >
- > 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 >
- > 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
- > 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 >
- > 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 >
- > 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
- > 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_); }
-
- void operator()()
- {
- BOOST_ASSERT( * this);
-
- impl_->resume();
- }
-
- bool has_result() const
- {
- BOOST_ASSERT( * this);
-
- return impl_->has_result();
- }
-
- R get() const
- {
- BOOST_ASSERT( * this);
-
- return impl_->get();
- }
-};
-
-template< typename R >
-void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
-{ l.swap( r); }
-#if 0
-template< typename R >
-inline
-typename pull_coroutine< R >::iterator
-range_begin( pull_coroutine< R > & c)
-{ return typename pull_coroutine< R >::iterator( & c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::const_iterator
-range_begin( pull_coroutine< R > const& c)
-{ return typename pull_coroutine< R >::const_iterator( & c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::iterator
-range_end( pull_coroutine< R > &)
-{ return typename pull_coroutine< R >::iterator(); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::const_iterator
-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 R >
-struct range_mutable_iterator< coroutines::coroutine< R > >
-{ typedef typename coroutines::coroutine< R >::iterator type; };
-
-template< typename R >
-struct range_const_iterator< coroutines::coroutine< R > >
-{ typedef typename coroutines::coroutine< R >::const_iterator type; };
-#endif
-}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_V2_PULL_COROUTINE_H

Deleted: trunk/boost/coroutine/v2/push_coroutine.hpp
==============================================================================
--- trunk/boost/coroutine/v2/push_coroutine.hpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84656)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,357 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// 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)
-
-#ifndef BOOST_COROUTINES_V2_PUSH_COROUTINE_H
-#define BOOST_COROUTINES_V2_PUSH_COROUTINE_H
-
-#include <cstddef>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/range.hpp>
-#include <boost/type_traits/decay.hpp>
-#include <boost/type_traits/function_traits.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/utility/result_of.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/stack_allocator.hpp>
-#include <boost/coroutine/v2/push_coroutine_base.hpp>
-#include <boost/coroutine/v2/push_coroutine_object.hpp.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename Arg >
-class push_coroutine
-{
-private:
- typedef detail::push_coroutine_base< Arg > 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)
-
-public:
- push_coroutine() BOOST_NOEXCEPT :
- impl_()
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, stack_allocator, std::allocator< push_coroutine >
- > 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 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, std::allocator< push_coroutine >
- > 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 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, Allocator
- > 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 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, stack_allocator, std::allocator< push_coroutine >
- > 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 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, std::allocator< push_coroutine >
- > 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 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, Allocator
- > 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 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, stack_allocator, std::allocator< push_coroutine >
- > 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 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, std::allocator< push_coroutine >
- > 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 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) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, Allocator
- > 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
-
- 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_); }
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- void operator()( Arg && arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->resume( boost::forward< Arg >( arg) );
- }
-#else
- void operator()( BOOST_RV_REF( Arg) arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->resume( boost::forward< Arg >( arg) );
- }
-#endif
-
- void operator()( Arg arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->resume( arg);
- }
-};
-
-template< typename Arg >
-void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
-{ l.swap( r); }
-#if 0
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::iterator
-range_begin( push_coroutine< Arg > & c)
-{ return typename push_coroutine< Arg >::iterator( & c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::const_iterator
-range_begin( push_coroutine< Arg > const& c)
-{ return typename push_coroutine< Arg >::const_iterator( & c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::iterator
-range_end( push_coroutine< Arg > &)
-{ return typename push_coroutine< Arg >::iterator(); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::const_iterator
-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 Arg >
-struct range_mutable_iterator< coroutines::coroutine< Arg > >
-{ typedef typename coroutines::coroutine< Arg >::iterator type; };
-
-template< typename Arg >
-struct range_const_iterator< coroutines::coroutine< Arg > >
-{ typedef typename coroutines::coroutine< Arg >::const_iterator type; };
-#endif
-}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_V2_PUSH_COROUTINE_H

Modified: trunk/libs/coroutine/doc/coro.qbk
==============================================================================
--- trunk/libs/coroutine/doc/coro.qbk Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/doc/coro.qbk 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -39,6 +39,8 @@
 
 [def __ctx__ ['context]]
 [def __coro__ ['coroutine]]
+[def __push_coro__ ['push_coroutine]]
+[def __pull_coro__ ['pull_coroutine]]
 [def __coro_fn__ ['coroutine-function]]
 [def __coros__ ['coroutines]]
 [def __not_a_coro__ ['not-a-coroutine]]
@@ -66,6 +68,9 @@
 [def __getline__ ['std::getline()]]
 [def __handle_read__ ['session::handle_read()]]
 [def __io_service__ ['boost::asio::io_sevice]]
+[def __pull_coro_get__ ['boost::coroutines::pull_coroutine<>::get()]]
+[def __pull_coro_op__ ['boost::coroutines::push_coroutine<>::operator()]]
+[def __push_coro_op__ ['boost::coroutines::push_coroutine<>::operator()]]
 [def __server__ ['server]]
 [def __session__ ['session]]
 [def __stack_context__ ['boost::coroutines::stack_context]]

Modified: trunk/libs/coroutine/doc/coroutine.qbk
==============================================================================
--- trunk/libs/coroutine/doc/coroutine.qbk Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/doc/coroutine.qbk 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -7,800 +7,10 @@
 
 [section:coroutine Coroutine]
 
-Each instance of __coro__ has its own context of execution (CPU registers and
-stack space) or represents __not_a_coro__ (similar to __thread__).
-Objects of type __coro__ are moveable but not copyable and can be returned by a
-function.
+__boost_coroutine__ provides two interfaces - one with uni- and one with bidirectional
+data transfer.
 
- boost::coroutines::coroutine< void() > f();
-
- void g()
- {
- boost::coroutines::coroutine< void() > c( f() );
- c();
- }
-
-[note __boost_move__ is used to emulate rvalue references.]
-
-
-[heading Creating a coroutine]
-
-A new __coro__ is created from a __coro_fn__ (function or functor) which will be
-executed in a new __ctx__ (CPU registers and stack space).
-
-[note __coro_fn__ is required to return ['void] and accept a reference of type
-__coro_caller__.]
-
-The template argument __signature__ determines the data-types transferred to
-__coro_fn__ and from __coro_fn__ by calling __coro_op__ and __coro_get__.
-
- typedef boost::coroutines::coroutine< int( std::string const&) > coro_t;
-
- // void f( boost::coroutine< std::string const&( int) > & ca)
- void f( coro_t::caller_type & ca)
- {
- ...
- // access argument
- std::string str( ca.get() );
- ...
- ca( 7);
- ...
- }
-
- std::string str;
- ...
- coro_t c( f);
- // pass argument
- c( str);
- // returned value
- int res = c.get();
-
-
-The __coro_fn__ is started at __coro__ construction (similar to __thread__)
-in a newly created __coro__ complete with registers, flags, stack and
-instruction pointer.
-If __coro_fn__ requires some arguments (types defined by __signature__)
-on start-up those parameters must be applied to the __coro__ constructor.
-A single arguments can be passed as it is:
-
- typedef boost::coroutines::coroutine< int( std::string const&) > coro_t;
-
- // void f( boost::coroutine< std::string const&( int) > & ca)
- void f( coro_t::caller_type & ca);
-
- std::string str("abc");
- coro_t c( f, str);
-
-
-For multiple arguments __args__ must be used (it is a typedef of __tuple__):
-
- typedef boost::coroutines::coroutine< int( int, std::string const&) > coro_t;
-
- // void f( boost::coroutine< boost::tuple< int, std::string const& >( int) > & ca)
- void f( coro_t::caller_type & ca);
-
- std::string str("abc");
- coro_t c( f, coro_t::arguments( 7, str) );
-
-
-[note The maximum number of arguments is limited to 10 (limit defined by
-__boost_tuple__).]
-
-[note Parameters bound with __bind__ to __coro_fn__ will not be part of the
-__coro_op__ signature.]
-
-__attrs__, an additional constructor argument of __coro__, defines the stack
-size, stack unwinding and floating-point preserving behaviour used for __ctx__
-construction.
-
-The __coro__ constructor uses the __stack_allocator_concept__ to allocate an
-associated stack, and the destructor uses the same __stack_allocator_concept__
-to deallocate the stack. The default __stack_allocator_concept__ is
-__stack_allocator__, but a custom stack-allocator can be passed to the
-constructor.
-
-
-[heading Calling a coroutine]
-
-The execution control is transferred to __coro__ at construction (__coro_fn__
-entered) - when control should be returned to the original calling routine,
-invoke __coro_op__ on the first argument of type __coro_caller__ inside
-__coro_fn__. __coro_caller__ is a typedef of __coro__ with an inverted
-__signature__. Inverted __signature__ means that the return type becomes an
-argument and vice versa. Multiple arguments are wrapped into __tuple__.
-
- void f( boost::coroutines::coroutine< std::string const&( int) & ca);
- boost::coroutines::coroutine< int( std::string const&) > c1( f);
-
- void g( boost::coroutines::coroutine< boost::tuple< X, Y >( int) & ca);
- boost::coroutines::coroutine< int( X, X) > c2( g);
-
-
-The current coroutine information (registers, flags, and stack and instruction
-pointer) is saved and the original context information is restored. Calling
-__coro_op__ resumes execution in the coroutine after saving the new state of the
-original routine.
-
- typedef boost::coroutines::coroutine< void() > coro_t;
-
- // void fn( boost::coroutines::coroutine< void() > & ca, int j)
- void fn( coro_t::caller_type & ca, int j)
- {
- for( int i = 0; i < j; ++i)
- {
- std::cout << "fn(): local variable i == " << i << std::endl;
-
- // save current coroutine
- // value of local variable is preserved
- // transfer execution control back to main()
- ca();
-
- // coroutine<>::operator()() was called
- // execution control transferred back from main()
- }
- }
-
- int main( int argc, char * argv[])
- {
- // bind parameter '7' to coroutine-fn
- coro_t c( boost::bind( fn, _1, 7) );
-
- std::cout << "main() starts coroutine c" << std::endl;
-
- while ( c)
- {
- std::cout << "main() calls coroutine c" << std::endl;
- // execution control is transferred to c
- c();
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main() starts coroutine c
- fn(): local variable i == 0
- main() calls coroutine c
- fn(): local variable i == 1
- main() calls coroutine c
- fn(): local variable i == 2
- main() calls coroutine c
- fn(): local variable i == 3
- main() calls coroutine c
- fn(): local variable i == 4
- main() calls coroutine c
- fn(): local variable i == 5
- main() calls coroutine c
- fn(): local variable i == 6
- main() calls coroutine c
- Done
-
-[warning Calling __coro_op__ from inside the [_same] coroutine results in
-undefined behaviour.]
-
-
-[heading Transfer of data]
-
-__signature__, the template argument of __coro__, defines the types transferred
-to and returned from the __coro_fn__, e.g. it determines the signature of
-__coro_op__ and the return-type of __coro_get__.
-
-[note __coro_caller__ is not part of __signature__ and __coro_fn__ is required
-to return void and accept __coro_caller__ as argument.]
-
-__coro_op__ accepts arguments as defined in __signature__ and returns a
-reference to __coro__. The arguments passed to __coro_op__, in one coroutine,
-is returned (as a __tuple__) by __coro_get__ in the other coroutine.
-If __coro__ is constructed and arguments are passed to the constructor, the
-__coro_fn__ will be entered and the arguments are accessed thorough __coro_get__
-in __coro_fn__ on entry.
-
-The value given to __coro_op__ of __coro_caller__, in one coroutine, is returned by
-__coro_get__ in the other routine.
-
- typedef boost::coroutines::coroutine< int( int) > coro_t;
-
- // void fn( boost::coroutines::coroutine< int( int) > & ca)
- void fn( coro_t::caller_type & ca)
- {
- // access the integer argument given to coroutine ctor
- int i = ca.get();
- std::cout << "fn(): local variable i == " << i << std::endl;
-
- // save current coroutine context and
- // transfer execution control back to caller
- // pass content of variable 'i' to caller
- // after execution control is returned back coroutine<>::operator()
- // returns and the transferred integer s accessed via coroutine<>::get()
- i = ca( i).get();
-
- // i == 10 because c( 10) in main()
- std::cout << "fn(): local variable i == " << i << std::endl;
- ca( i);
- }
-
- int main( int argc, char * argv[])
- {
- std::cout << "main(): call coroutine c" << std::endl;
- coro_t c( fn, 7);
-
- int x = c.get();
- std::cout << "main(): transferred value: " << x << std::endl;
-
- x = c( 10).get();
- std::cout << "main(): transferred value: " << x << std::endl;
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main(): call coroutine c
- fn(): local variable i == 7
- main(): transferred value: 7
- fn(): local variable i == 10
- main(): transferred value: 10
- Done
-
-
-[heading __coro_fn__ with multiple arguments]
-
-If __coro_fn__ has more than one argument __coro_op__ has the same size of
-arguments and __coro_get__ from __coro_caller__ returns a __tuple__ corresponding
-to the arguments of __signature__. __tie__ helps to access the values stored in
-the __tuple__ returned by __coro_get__.
-
- typedef boost::coroutines::coroutine< int(int,int) > coro_t;
-
- // void fn( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca)
- void fn( coro_t::caller_type & ca)
- {
- int a, b;
- boost::tie( a, b) = ca.get();
- boost::tie( a, b) = ca( a + b).get();
- ca( a + b);
- }
-
- int main( int argc, char * argv[])
- {
- std::cout << "main(): call coroutine c" << std::endl;
- coro_t coro( fn, coro_t::arguments( 3, 7) );
-
- int res = coro.get();
- std::cout << "main(): 3 + 7 == " << res << std::endl;
-
- res = coro( 5, 7).get();
- std::cout << "main(): 5 + 7 == " << res << std::endl;
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main(): call coroutine c
- main(): 3 + 7 == 10
- main(): 5 + 7 == 12
- Done
-
-
-[heading Transfer of pointers and references]
-
-You can transfer references and pointers from and to coroutines but as usual
-you must take care (scope, no re-assignment of const references etc.).
-In the following code `x` points to `local` which is allocated on stack of
-`c`. When `c` goes out of scope the stack becomes deallocated. Using `x`
-after `c` is gone will fail!
-
- struct X
- {
- void g();
- };
-
- typedef boost::coroutines::coroutine< X*() > coro_t;
-
- // void fn( boost::coroutines::coroutine< void( X*) > & ca)
- void fn( coro_t::caller_t & ca) {
- X local;
- ca( & local);
- }
-
- int main() {
- X * x = 0;
- {
- coro_t c( fn);
- x = c.get(); // let x point to X on stack owned by c
- // stack gets unwound -> X will be destructed
- }
- x->g(); // segmentation fault!
- return EXIT_SUCCESS;
- }
-
-
-[heading Range iterators]
-
-__boost_coroutine__ provides output- and input-iterators using __boost_range__.
-`coroutine< T() >` can be used via output-iterators using __begin__ and __end__.
-
- typedef boost::coroutines::coroutine< int() > coro_t;
- typedef boost::range_iterator< coro_t >::type iterator_t;
-
- // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent)
- void power( coro_t::caller_type & ca, int number, int exponent)
- {
- int counter = 0;
- int result = 1;
- while ( counter++ < exponent)
- {
- result = result * number;
- ca( result);
- }
- }
-
- int main()
- {
- coro_t c( boost::bind( power, _1, 2, 8) );
- iterator_t e( boost::end( c) );
- for ( iterator_t i( boost::begin( c) ); i != e; ++i)
- std::cout << * i << " ";
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- 2 4 8 16 32 64 128 256
- Done
-
-`BOOST_FOREACH` can be used to iterate over the coroutine range too.
-
- typedef boost::coroutines::coroutine< int() > coro_t;
- typedef boost::range_iterator< coro_t >::type iterator_t;
-
- // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent)
- void power( coro_t::caller_type & ca, int number, int exponent)
- {
- int counter = 0;
- int result = 1;
- while ( counter++ < exponent)
- {
- result = result * number;
- ca( result);
- }
- }
-
- int main()
- {
- coro_t c( boost::bind( power, _1, 2, 8) );
- BOOST_FOREACH( int i, c)
- { std::cout << i << " "; }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- 2 4 8 16 32 64 128 256
- Done
-
-
-Input iterators are created from coroutines of type `coroutine< void( T) >`.
-
-
-
-[heading Exit a __coro_fn__]
-
-__coro_fn__ is exited with a simple return statement jumping back to the calling
-routine. The __coro__ becomes complete, e.g. __coro_bool__ will return 'false'.
-
- typedef boost::coroutines::coroutine< int(int,int) > coro_t;
-
- // void power( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca, int number, int exponent)
- void fn( coro_t::caller_type & ca)
- {
- int a, b;
- boost::tie( a, b) = ca.get();
- boost::tie( a, b) = ca( a + b).get();
- ca( a + b);
- }
-
- int main( int argc, char * argv[])
- {
- std::cout << "main(): call coroutine c" << std::endl;
- coro_t coro( fn, coro_t::arguments( 3, 7) );
-
- BOOST_ASSERT( coro);
- int res = coro.get();
- std::cout << "main(): 3 + 7 == " << res << std::endl;
-
- res = coro( 5, 7).get();
- BOOST_ASSERT( ! coro);
- std::cout << "main(): 5 + 7 == " << res << std::endl;
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main(): call coroutine c
- main(): 3 + 7 == 10
- main(): 5 + 7 == 12
- Done
-
-[important After returning from __coro_fn__ the __coro__ is complete (can not
-resumed with __coro_op__).]
-
-
-[heading Exceptions in __coro_fn__]
-
-An exception thrown inside __coro_fn__ will transferred via exception-pointer
-(see __boost_exception__ for details) and re-thrown by constructor or
-__coro_op__.
-
- typedef boost::coroutines::coroutine< void() > coro_t;
-
- // void fn( boost::coroutines::coroutine< void() > & ca)
- void fn( coro_t::caller_type & ca)
- {
- ca();
- throw std::runtime_error("abc");
- }
-
- int main( int argc, char * argv[])
- {
- coro_t c( f);
- try
- {
- c();
- }
- catch ( std::exception const& e)
- {
- std::cout << "exception catched:" << e.what() << std::endl;
- return EXIT_FAILURE;
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- exception catched: abc
-
-[important Code executed by coroutine must not prevent the propagation of the
-__forced_unwind__ exception. Absorbing that exception will cause stack
-unwinding to fail. Thus, any code that catches all exceptions must re-throw the
-pending exception.]
-
- try
- {
- // code that might throw
- }
- catch( forced_unwind)
- {
- throw;
- }
- catch(...)
- {
- // possibly not re-throw pending exception
- }
-
-
-[heading Stack unwinding]
-
-Sometimes it is necessary to unwind the stack of an unfinished coroutine to
-destroy local stack variables so they can release allocated resources (RAII
-pattern). The third argument of the coroutine constructor, `do_unwind`,
-indicates whether the destructor should unwind the stack (stack is unwound by
-default).
-
-Stack unwinding assumes the following preconditions:
-
-* The coroutine is not __not_a_coro__
-* The coroutine is not complete
-* The coroutine is not running
-* The coroutine owns a stack
-
-After unwinding, a __coro__ is complete.
-
-
- typedef boost::coroutines::coroutine< void() > coro_t;
-
- struct X
- {
- X()
- { std::cout << "X()" << std::endl; }
-
- ~X()
- { std::cout << "~X()" << std::endl; }
- };
-
- // void fn( boost::coroutines::coroutine< void() > & ca)
- void fn( coro_t::caller_type & ca)
- {
- X x;
-
- for ( int = 0;; ++i)
- {
- std::cout << "fn(): " << i << std::endl;
- // transfer execution control back to main()
- ca();
- }
- }
-
- int main( int argc, char * argv[])
- {
- {
- coro_t c( fn,
- boost::coroutines::attributes(
- boost::ctx::default_stacksize(),
- boost::coroutines::stack_unwind) );
-
- c();
- c();
- c();
- c();
- c();
-
- std::cout << "c is complete: " << std::boolalpha << c.is_complete() << "\n";
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- X()
- fn(): 0
- fn(): 1
- fn(): 2
- fn(): 3
- fn(): 4
- fn(): 5
- c is complete: false
- ~X()
- Done
-
-[important You must not swallow __forced_unwind__ exceptions!]
-
-
-[heading FPU preserving]
-
-Some applications do not use floating-point registers and can disable preserving
-fpu registers for performance reasons.
-
-[note According to the calling convention the FPU registers are preserved by default.]
-
-
-[section:coroutine Class `coroutine`]
-
- #include <boost/coroutine/coroutine.hpp>
-
- template< typename Signature >
- class coroutine;
-
- template<
- typename R,
- typename ArgTypes...
- >
- class coroutine< R ( ArgTypes...) >
- {
- public:
- typedef unspec-type caller_type;
- typedef unspec-type arguments;
-
- coroutine();
-
- template<
- typename Fn,
- typename StackAllocator = stack_allocator,
- typename Allocator = std::allocator< coroutine >
- >
- coroutine( Fn fn, attributes const& attr = attributes(),
- StackAllocator const& stack_alloc = StackAllocator(),
- Allocator const& alloc = Allocator() );
-
- template<
- typename Fn,
- typename StackAllocator = stack_allocator,
- typename Allocator = std::allocator< coroutine >
- >
- coroutine( Fn fn, arguments const& args,
- attributes const& attr = attributes(),
- StackAllocator const& stack_alloc = StackAllocator(),
- Allocator const& alloc = Allocator() );
-
- template<
- typename Fn,
- typename StackAllocator = stack_allocator,
- typename Allocator = std::allocator< coroutine >
- >
- coroutine( Fn && fn, attributes const& attr = attributes(),
- StackAllocator stack_alloc = StackAllocator(),
- Allocator const& alloc = Allocator() );
-
- template<
- typename Fn,
- typename StackAllocator = stack_allocator,
- typename Allocator = std::allocator< coroutine >
- >
- coroutine( Fn && fn arguments const& args,
- attributes const& attr = attributes(),
- StackAllocator stack_alloc = StackAllocator(),
- Allocator const& alloc = Allocator() );
-
- coroutine( coroutine && other);
-
- coroutine & operator=( coroutine && other);
-
- operator unspecified-bool-type() const;
-
- bool operator!() const;
-
- void swap( coroutine & other);
-
- bool empty() const;
-
- coroutine & operator()(A0 a0, ..., A9 a9);
-
- R get() const;
- };
-
- template< typename Signature >
- void swap( coroutine< Signature > & l, coroutine< Signature > & r);
-
- template< typename T >
- range_iterator< coroutine< T() > >::type begin( coroutine< T() > &);
- template< typename T >
- range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &);
-
- template< typename T >
- range_iterator< coroutine< T() > >::type end( coroutine< T() > &);
- template< typename T >
- range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &);
-
-[heading `coroutine()`]
-[variablelist
-[[Effects:] [Creates a coroutine representing __not_a_coro__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `template< typename Fn, typename StackAllocator, typename Allocator >
- coroutine( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
-when ! is_stack_unbound().]]
-[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
-determines stack clean-up and preserving floating-point registers.
-For allocating/deallocating the stack `stack_alloc` is used and internal
-data are allocated by Allocator.]]
-]
-
-[heading `template< typename Fn, typename StackAllocator, typename Allocator >
- coroutine( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
-when ! is_stack_unbound().]]
-[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
-determines stack clean-up and preserving floating-point registers.
-For allocating/deallocating the stack `stack_alloc` is used and internal
-data are allocated by Allocator.]]
-]
-
-[heading `coroutine( coroutine && other)`]
-[variablelist
-[[Effects:] [Moves the internal data of `other` to `*this`.
-`other` becomes __not_a_coro__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `coroutine & operator=( coroutine && other)`]
-[variablelist
-[[Effects:] [Destroys the internal data of `*this` and moves the
-internal data of `other` to `*this`. `other` becomes __not_a_coro__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `operator unspecified-bool-type() const`]
-[variablelist
-[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
-has returned (completed), the function returns false. Otherwise true.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool operator!() const`]
-[variablelist
-[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
-has returned (completed), the function returns true. Otherwise false.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool empty()`]
-[variablelist
-[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true.
-Otherwise false.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `coroutine<> & operator()(A0 a0, A9 a9)`]
-[variablelist
-[[Preconditions:] [operator unspecified-bool-type() returns true for `*this`.]
-[[Effects:] [Execution control is transferred to __coro_fn__ and the arguments
-`a0`,..., are passed to the coroutine-function.]]
-[[Throws:] [Exceptions thrown inside __coro_fn__.]]
-]
-
-[heading `R get()()`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_coro__, `! is_complete()`.]]
-[[Returns:] [Returns data transferred from coroutine-function via __coro_op__
-of __coro_caller__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `void swap( coroutine & other)`]
-[variablelist
-[[Effects:] [Swaps the internal data from `*this` with the values
-of `other`.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `T caller_type::operator()( R)`]
-[variablelist
-[[Effects:] [Gives execution control back to calling context by returning
-a value of type R. The return type of this function is a __tuple__ containing
-the arguments passed to __coro_op__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading Non-member function `swap()`]
-
- template< typename Signature >
- void swap( coroutine< Signature > & l, coroutine< Signature > & r);
-
-[variablelist
-[[Effects:] [As if 'l.swap( r)'.]]
-]
-
-[heading Non-member function `begin( coroutine< T() > &)`]
- template< typename T >
- range_iterator< coroutine< T() > >::type begin( coroutine< T() > &);
-
-[variablelist
-[[Returns:] [Returns a range-iterator (input-iterator).]]
-]
-
-[heading Non-member function `begin( coroutine< void(T) > &)`]
- template< typename T >
- range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &);
-
-[variablelist
-[[Returns:] [Returns a range-iterator (output-iterator).]]
-]
-
-[heading Non-member function `end( coroutine< T() > &)`]
- template< typename T >
- range_iterator< coroutine< T() > >::type end( coroutine< T() > &);
-
-[variablelist
-[[Returns:] [Returns a end range-iterator (input-iterator).]]
-]
-
-[heading Non-member function `end( coroutine< void(T) > &)`]
- template< typename T >
- range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &);
-
-[variablelist
-[[Returns:] [Returns a end range-iterator (output-iterator).]]
-]
-
-[endsect]
+[include unidirect.qbk]
+[include old.qbk]
 
 [endsect]

Added: trunk/libs/coroutine/doc/old.qbk
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/coroutine/doc/old.qbk 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -0,0 +1,809 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ 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
+]
+
+[section:old Bidirectional coroutine (version 1)]
+
+[note This interface is deprecated but can be used by compiling the code with
+macro BOOST_COROUTINES_OLD.]
+
+Each instance of __coro__ has its own context of execution (CPU registers and
+stack space) or represents __not_a_coro__ (similar to __thread__).
+Objects of type __coro__ are moveable but not copyable and can be returned by a
+function.
+
+ boost::coroutines::coroutine< void() > f();
+
+ void g()
+ {
+ boost::coroutines::coroutine< void() > c( f() );
+ c();
+ }
+
+[note __boost_move__ is used to emulate rvalue references.]
+
+
+[heading Creating a coroutine]
+
+A new __coro__ is created from a __coro_fn__ (function or functor) which will be
+executed in a new __ctx__ (CPU registers and stack space).
+
+[note __coro_fn__ is required to return ['void] and accept a reference of type
+__coro_caller__.]
+
+The template argument __signature__ determines the data-types transferred to
+__coro_fn__ and from __coro_fn__ by calling __coro_op__ and __coro_get__.
+
+ typedef boost::coroutines::coroutine< int( std::string const&) > coro_t;
+
+ // void f( boost::coroutine< std::string const&( int) > & ca)
+ void f( coro_t::caller_type & ca)
+ {
+ ...
+ // access argument
+ std::string str( ca.get() );
+ ...
+ ca( 7);
+ ...
+ }
+
+ std::string str;
+ ...
+ coro_t c( f);
+ // pass argument
+ c( str);
+ // returned value
+ int res = c.get();
+
+
+The __coro_fn__ is started at __coro__ construction (similar to __thread__)
+in a newly created __coro__ complete with registers, flags, stack and
+instruction pointer.
+If __coro_fn__ requires some arguments (types defined by __signature__)
+on start-up those parameters must be applied to the __coro__ constructor.
+A single arguments can be passed as it is:
+
+ typedef boost::coroutines::coroutine< int( std::string const&) > coro_t;
+
+ // void f( boost::coroutine< std::string const&( int) > & ca)
+ void f( coro_t::caller_type & ca);
+
+ std::string str("abc");
+ coro_t c( f, str);
+
+
+For multiple arguments __args__ must be used (it is a typedef of __tuple__):
+
+ typedef boost::coroutines::coroutine< int( int, std::string const&) > coro_t;
+
+ // void f( boost::coroutine< boost::tuple< int, std::string const& >( int) > & ca)
+ void f( coro_t::caller_type & ca);
+
+ std::string str("abc");
+ coro_t c( f, coro_t::arguments( 7, str) );
+
+
+[note The maximum number of arguments is limited to 10 (limit defined by
+__boost_tuple__).]
+
+[note Parameters bound with __bind__ to __coro_fn__ will not be part of the
+__coro_op__ signature.]
+
+__attrs__, an additional constructor argument of __coro__, defines the stack
+size, stack unwinding and floating-point preserving behaviour used for __ctx__
+construction.
+
+The __coro__ constructor uses the __stack_allocator_concept__ to allocate an
+associated stack, and the destructor uses the same __stack_allocator_concept__
+to deallocate the stack. The default __stack_allocator_concept__ is
+__stack_allocator__, but a custom stack-allocator can be passed to the
+constructor.
+
+
+[heading Calling a coroutine]
+
+The execution control is transferred to __coro__ at construction (__coro_fn__
+entered) - when control should be returned to the original calling routine,
+invoke __coro_op__ on the first argument of type __coro_caller__ inside
+__coro_fn__. __coro_caller__ is a typedef of __coro__ with an inverted
+__signature__. Inverted __signature__ means that the return type becomes an
+argument and vice versa. Multiple arguments are wrapped into __tuple__.
+
+ void f( boost::coroutines::coroutine< std::string const&( int) & ca);
+ boost::coroutines::coroutine< int( std::string const&) > c1( f);
+
+ void g( boost::coroutines::coroutine< boost::tuple< X, Y >( int) & ca);
+ boost::coroutines::coroutine< int( X, X) > c2( g);
+
+
+The current coroutine information (registers, flags, and stack and instruction
+pointer) is saved and the original context information is restored. Calling
+__coro_op__ resumes execution in the coroutine after saving the new state of the
+original routine.
+
+ typedef boost::coroutines::coroutine< void() > coro_t;
+
+ // void fn( boost::coroutines::coroutine< void() > & ca, int j)
+ void fn( coro_t::caller_type & ca, int j)
+ {
+ for( int i = 0; i < j; ++i)
+ {
+ std::cout << "fn(): local variable i == " << i << std::endl;
+
+ // save current coroutine
+ // value of local variable is preserved
+ // transfer execution control back to main()
+ ca();
+
+ // coroutine<>::operator()() was called
+ // execution control transferred back from main()
+ }
+ }
+
+ int main( int argc, char * argv[])
+ {
+ // bind parameter '7' to coroutine-fn
+ coro_t c( boost::bind( fn, _1, 7) );
+
+ std::cout << "main() starts coroutine c" << std::endl;
+
+ while ( c)
+ {
+ std::cout << "main() calls coroutine c" << std::endl;
+ // execution control is transferred to c
+ c();
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main() starts coroutine c
+ fn(): local variable i == 0
+ main() calls coroutine c
+ fn(): local variable i == 1
+ main() calls coroutine c
+ fn(): local variable i == 2
+ main() calls coroutine c
+ fn(): local variable i == 3
+ main() calls coroutine c
+ fn(): local variable i == 4
+ main() calls coroutine c
+ fn(): local variable i == 5
+ main() calls coroutine c
+ fn(): local variable i == 6
+ main() calls coroutine c
+ Done
+
+[warning Calling __coro_op__ from inside the [_same] coroutine results in
+undefined behaviour.]
+
+
+[heading Transfer of data]
+
+__signature__, the template argument of __coro__, defines the types transferred
+to and returned from the __coro_fn__, e.g. it determines the signature of
+__coro_op__ and the return-type of __coro_get__.
+
+[note __coro_caller__ is not part of __signature__ and __coro_fn__ is required
+to return void and accept __coro_caller__ as argument.]
+
+__coro_op__ accepts arguments as defined in __signature__ and returns a
+reference to __coro__. The arguments passed to __coro_op__, in one coroutine,
+is returned (as a __tuple__) by __coro_get__ in the other coroutine.
+If __coro__ is constructed and arguments are passed to the constructor, the
+__coro_fn__ will be entered and the arguments are accessed thorough __coro_get__
+in __coro_fn__ on entry.
+
+The value given to __coro_op__ of __coro_caller__, in one coroutine, is returned by
+__coro_get__ in the other routine.
+
+ typedef boost::coroutines::coroutine< int( int) > coro_t;
+
+ // void fn( boost::coroutines::coroutine< int( int) > & ca)
+ void fn( coro_t::caller_type & ca)
+ {
+ // access the integer argument given to coroutine ctor
+ int i = ca.get();
+ std::cout << "fn(): local variable i == " << i << std::endl;
+
+ // save current coroutine context and
+ // transfer execution control back to caller
+ // pass content of variable 'i' to caller
+ // after execution control is returned back coroutine<>::operator()
+ // returns and the transferred integer s accessed via coroutine<>::get()
+ i = ca( i).get();
+
+ // i == 10 because c( 10) in main()
+ std::cout << "fn(): local variable i == " << i << std::endl;
+ ca( i);
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ coro_t c( fn, 7);
+
+ int x = c.get();
+ std::cout << "main(): transferred value: " << x << std::endl;
+
+ x = c( 10).get();
+ std::cout << "main(): transferred value: " << x << std::endl;
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ fn(): local variable i == 7
+ main(): transferred value: 7
+ fn(): local variable i == 10
+ main(): transferred value: 10
+ Done
+
+
+[heading __coro_fn__ with multiple arguments]
+
+If __coro_fn__ has more than one argument __coro_op__ has the same size of
+arguments and __coro_get__ from __coro_caller__ returns a __tuple__ corresponding
+to the arguments of __signature__. __tie__ helps to access the values stored in
+the __tuple__ returned by __coro_get__.
+
+ typedef boost::coroutines::coroutine< int(int,int) > coro_t;
+
+ // void fn( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca)
+ void fn( coro_t::caller_type & ca)
+ {
+ int a, b;
+ boost::tie( a, b) = ca.get();
+ boost::tie( a, b) = ca( a + b).get();
+ ca( a + b);
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ coro_t coro( fn, coro_t::arguments( 3, 7) );
+
+ int res = coro.get();
+ std::cout << "main(): 3 + 7 == " << res << std::endl;
+
+ res = coro( 5, 7).get();
+ std::cout << "main(): 5 + 7 == " << res << std::endl;
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ main(): 3 + 7 == 10
+ main(): 5 + 7 == 12
+ Done
+
+
+[heading Transfer of pointers and references]
+
+You can transfer references and pointers from and to coroutines but as usual
+you must take care (scope, no re-assignment of const references etc.).
+In the following code `x` points to `local` which is allocated on stack of
+`c`. When `c` goes out of scope the stack becomes deallocated. Using `x`
+after `c` is gone will fail!
+
+ struct X
+ {
+ void g();
+ };
+
+ typedef boost::coroutines::coroutine< X*() > coro_t;
+
+ // void fn( boost::coroutines::coroutine< void( X*) > & ca)
+ void fn( coro_t::caller_t & ca) {
+ X local;
+ ca( & local);
+ }
+
+ int main() {
+ X * x = 0;
+ {
+ coro_t c( fn);
+ x = c.get(); // let x point to X on stack owned by c
+ // stack gets unwound -> X will be destructed
+ }
+ x->g(); // segmentation fault!
+ return EXIT_SUCCESS;
+ }
+
+
+[heading Range iterators]
+
+__boost_coroutine__ provides output- and input-iterators using __boost_range__.
+`coroutine< T() >` can be used via output-iterators using __begin__ and __end__.
+
+ typedef boost::coroutines::coroutine< int() > coro_t;
+ typedef boost::range_iterator< coro_t >::type iterator_t;
+
+ // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent)
+ void power( coro_t::caller_type & ca, int number, int exponent)
+ {
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ ca( result);
+ }
+ }
+
+ int main()
+ {
+ coro_t c( boost::bind( power, _1, 2, 8) );
+ iterator_t e( boost::end( c) );
+ for ( iterator_t i( boost::begin( c) ); i != e; ++i)
+ std::cout << * i << " ";
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ 2 4 8 16 32 64 128 256
+ Done
+
+`BOOST_FOREACH` can be used to iterate over the coroutine range too.
+
+ typedef boost::coroutines::coroutine< int() > coro_t;
+ typedef boost::range_iterator< coro_t >::type iterator_t;
+
+ // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent)
+ void power( coro_t::caller_type & ca, int number, int exponent)
+ {
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ ca( result);
+ }
+ }
+
+ int main()
+ {
+ coro_t c( boost::bind( power, _1, 2, 8) );
+ BOOST_FOREACH( int i, c)
+ { std::cout << i << " "; }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ 2 4 8 16 32 64 128 256
+ Done
+
+
+Input iterators are created from coroutines of type `coroutine< void( T) >`.
+
+
+
+[heading Exit a __coro_fn__]
+
+__coro_fn__ is exited with a simple return statement jumping back to the calling
+routine. The __coro__ becomes complete, e.g. __coro_bool__ will return 'false'.
+
+ typedef boost::coroutines::coroutine< int(int,int) > coro_t;
+
+ // void power( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca, int number, int exponent)
+ void fn( coro_t::caller_type & ca)
+ {
+ int a, b;
+ boost::tie( a, b) = ca.get();
+ boost::tie( a, b) = ca( a + b).get();
+ ca( a + b);
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ coro_t coro( fn, coro_t::arguments( 3, 7) );
+
+ BOOST_ASSERT( coro);
+ int res = coro.get();
+ std::cout << "main(): 3 + 7 == " << res << std::endl;
+
+ res = coro( 5, 7).get();
+ BOOST_ASSERT( ! coro);
+ std::cout << "main(): 5 + 7 == " << res << std::endl;
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ main(): 3 + 7 == 10
+ main(): 5 + 7 == 12
+ Done
+
+[important After returning from __coro_fn__ the __coro__ is complete (can not
+resumed with __coro_op__).]
+
+
+[heading Exceptions in __coro_fn__]
+
+An exception thrown inside __coro_fn__ will transferred via exception-pointer
+(see __boost_exception__ for details) and re-thrown by constructor or
+__coro_op__.
+
+ typedef boost::coroutines::coroutine< void() > coro_t;
+
+ // void fn( boost::coroutines::coroutine< void() > & ca)
+ void fn( coro_t::caller_type & ca)
+ {
+ ca();
+ throw std::runtime_error("abc");
+ }
+
+ int main( int argc, char * argv[])
+ {
+ coro_t c( f);
+ try
+ {
+ c();
+ }
+ catch ( std::exception const& e)
+ {
+ std::cout << "exception catched:" << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ exception catched: abc
+
+[important Code executed by coroutine must not prevent the propagation of the
+__forced_unwind__ exception. Absorbing that exception will cause stack
+unwinding to fail. Thus, any code that catches all exceptions must re-throw the
+pending exception.]
+
+ try
+ {
+ // code that might throw
+ }
+ catch( forced_unwind)
+ {
+ throw;
+ }
+ catch(...)
+ {
+ // possibly not re-throw pending exception
+ }
+
+
+[heading Stack unwinding]
+
+Sometimes it is necessary to unwind the stack of an unfinished coroutine to
+destroy local stack variables so they can release allocated resources (RAII
+pattern). The third argument of the coroutine constructor, `do_unwind`,
+indicates whether the destructor should unwind the stack (stack is unwound by
+default).
+
+Stack unwinding assumes the following preconditions:
+
+* The coroutine is not __not_a_coro__
+* The coroutine is not complete
+* The coroutine is not running
+* The coroutine owns a stack
+
+After unwinding, a __coro__ is complete.
+
+
+ typedef boost::coroutines::coroutine< void() > coro_t;
+
+ struct X
+ {
+ X()
+ { std::cout << "X()" << std::endl; }
+
+ ~X()
+ { std::cout << "~X()" << std::endl; }
+ };
+
+ // void fn( boost::coroutines::coroutine< void() > & ca)
+ void fn( coro_t::caller_type & ca)
+ {
+ X x;
+
+ for ( int = 0;; ++i)
+ {
+ std::cout << "fn(): " << i << std::endl;
+ // transfer execution control back to main()
+ ca();
+ }
+ }
+
+ int main( int argc, char * argv[])
+ {
+ {
+ coro_t c( fn,
+ boost::coroutines::attributes(
+ boost::ctx::default_stacksize(),
+ boost::coroutines::stack_unwind) );
+
+ c();
+ c();
+ c();
+ c();
+ c();
+
+ std::cout << "c is complete: " << std::boolalpha << c.is_complete() << "\n";
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ X()
+ fn(): 0
+ fn(): 1
+ fn(): 2
+ fn(): 3
+ fn(): 4
+ fn(): 5
+ c is complete: false
+ ~X()
+ Done
+
+[important You must not swallow __forced_unwind__ exceptions!]
+
+
+[heading FPU preserving]
+
+Some applications do not use floating-point registers and can disable preserving
+fpu registers for performance reasons.
+
+[note According to the calling convention the FPU registers are preserved by default.]
+
+
+[section:coroutine Class `coroutine`]
+
+ #include <boost/coroutine/coroutine.hpp>
+
+ template< typename Signature >
+ class coroutine;
+
+ template<
+ typename R,
+ typename ArgTypes...
+ >
+ class coroutine< R ( ArgTypes...) >
+ {
+ public:
+ typedef unspec-type caller_type;
+ typedef unspec-type arguments;
+
+ coroutine();
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ coroutine( Fn fn, attributes const& attr = attributes(),
+ StackAllocator const& stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ coroutine( Fn fn, arguments const& args,
+ attributes const& attr = attributes(),
+ StackAllocator const& stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ coroutine( Fn && fn, attributes const& attr = attributes(),
+ StackAllocator stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ coroutine( Fn && fn arguments const& args,
+ attributes const& attr = attributes(),
+ StackAllocator stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ coroutine( coroutine && other);
+
+ coroutine & operator=( coroutine && other);
+
+ operator unspecified-bool-type() const;
+
+ bool operator!() const;
+
+ void swap( coroutine & other);
+
+ bool empty() const;
+
+ coroutine & operator()(A0 a0, ..., A9 a9);
+
+ R get() const;
+ };
+
+ template< typename Signature >
+ void swap( coroutine< Signature > & l, coroutine< Signature > & r);
+
+ template< typename T >
+ range_iterator< coroutine< T() > >::type begin( coroutine< T() > &);
+ template< typename T >
+ range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &);
+
+ template< typename T >
+ range_iterator< coroutine< T() > >::type end( coroutine< T() > &);
+ template< typename T >
+ range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &);
+
+[heading `coroutine()`]
+[variablelist
+[[Effects:] [Creates a coroutine representing __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ coroutine( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ coroutine( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+]
+
+[heading `coroutine( coroutine && other)`]
+[variablelist
+[[Effects:] [Moves the internal data of `other` to `*this`.
+`other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `coroutine & operator=( coroutine && other)`]
+[variablelist
+[[Effects:] [Destroys the internal data of `*this` and moves the
+internal data of `other` to `*this`. `other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `operator unspecified-bool-type() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns false. Otherwise true.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool operator!() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns true. Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool empty()`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true.
+Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `coroutine<> & operator()(A0 a0, A9 a9)`]
+[variablelist
+[[Preconditions:] [operator unspecified-bool-type() returns true for `*this`.]
+[[Effects:] [Execution control is transferred to __coro_fn__ and the arguments
+`a0`,..., are passed to the coroutine-function.]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `R get()()`]
+[variablelist
+[[Preconditions:] [`*this` is not a __not_a_coro__, `! is_complete()`.]]
+[[Returns:] [Returns data transferred from coroutine-function via __coro_op__
+of __coro_caller__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `void swap( coroutine & other)`]
+[variablelist
+[[Effects:] [Swaps the internal data from `*this` with the values
+of `other`.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `T caller_type::operator()( R)`]
+[variablelist
+[[Effects:] [Gives execution control back to calling context by returning
+a value of type R. The return type of this function is a __tuple__ containing
+the arguments passed to __coro_op__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading Non-member function `swap()`]
+
+ template< typename Signature >
+ void swap( coroutine< Signature > & l, coroutine< Signature > & r);
+
+[variablelist
+[[Effects:] [As if 'l.swap( r)'.]]
+]
+
+[heading Non-member function `begin( coroutine< T() > &)`]
+ template< typename T >
+ range_iterator< coroutine< T() > >::type begin( coroutine< T() > &);
+
+[variablelist
+[[Returns:] [Returns a range-iterator (input-iterator).]]
+]
+
+[heading Non-member function `begin( coroutine< void(T) > &)`]
+ template< typename T >
+ range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &);
+
+[variablelist
+[[Returns:] [Returns a range-iterator (output-iterator).]]
+]
+
+[heading Non-member function `end( coroutine< T() > &)`]
+ template< typename T >
+ range_iterator< coroutine< T() > >::type end( coroutine< T() > &);
+
+[variablelist
+[[Returns:] [Returns a end range-iterator (input-iterator).]]
+]
+
+[heading Non-member function `end( coroutine< void(T) > &)`]
+ template< typename T >
+ range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &);
+
+[variablelist
+[[Returns:] [Returns a end range-iterator (output-iterator).]]
+]
+
+[endsect]
+
+[endsect]

Added: trunk/libs/coroutine/doc/unidirect.qbk
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/coroutine/doc/unidirect.qbk 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -0,0 +1,878 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ 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
+]
+
+[section:unidirect Unidirectional coroutine (version 2)]
+
+[note This is the default interface (macro BOOST_COROUTINES_UNIDIRECT).]
+
+Two kinds of __coros__ are provided - __push_coro__ for transfering data to
+and __pull_coro__ for transfering data from the other execution context.
+Both coroutine flavours occure in a pair - providing a unidirectional data
+transfer.
+
+Each instance of __coro__ has its own context of execution (CPU registers and
+stack space) or represents __not_a_coro__ (similar to __thread__).
+Objects of type __coro__ are moveable but not copyable and can be returned by a
+function.
+
+ boost::coroutines::push_coroutine< int > f();
+
+ void g()
+ {
+ boost::coroutines::push_coroutine< int > c( f() );
+ c( 1);
+ }
+
+[note __boost_move__ is used to emulate rvalue references.]
+
+
+[heading Creating a coroutine]
+
+A new __coro__ is created from a __coro_fn__ (function or functor) which will be
+executed in a new __ctx__ (CPU registers and stack space).
+
+[note __coro_fn__ is required to return ['void] and accept a reference of type
+__push_coro__ (if called by __pull_coro__) or vice versa.]
+
+The template argument determines the data-type transferred to/from
+__coro_fn__.
+
+ void f( boost:::coroutines::pull_coroutine< std::string > & c)
+ {
+ // access argument
+ std::string str( c.get() );
+ // return to other execution context
+ c();
+ }
+
+ std::string str;
+ boost::coroutines::push_coroutine< std::string > c( f);
+ // pass argument
+ c( str);
+
+
+The __coro_fn__ is started at __coro__ construction (similar to __thread__)
+in a newly created __pull_coro__ complete with registers, flags, stack and
+instruction pointer. In the case of __push_coro__ the __coro_fn__ is entered
+when __push_coro_op__ is called the first time.
+
+__attrs__, an additional constructor argument of __coro__, defines the stack
+size, stack unwinding and floating-point preserving behaviour used for __ctx__
+construction.
+
+The __coro__ constructor uses the __stack_allocator_concept__ to allocate an
+associated stack, and the destructor uses the same __stack_allocator_concept__
+to deallocate the stack. The default __stack_allocator_concept__ is
+__stack_allocator__, but a custom stack-allocator can be passed to the
+constructor.
+
+
+[heading Calling a coroutine]
+
+Using __pull_coro__ requires that __coro_fn__ takes __push_coro__ as first
+argument and vice versa.
+For __pull_coro__ __coro_fn__ is entered at construction and if control should
+be returned to the original calling routine __push_coro_op__ (first argument of
+__coro_fn__) has to be invoked.
+
+ void f( boost::coroutines::push_coroutine< std::string > & c)
+ {
+ c("abc");
+ }
+
+ boost::coroutines::pull_coroutine< std::string > c( f);
+ std::string str = c.get();
+ c();
+
+Multiple arguments are wrapped into __tuple__.
+
+ void g( boost::coroutines::pull_coroutine< boost::tuple< X, Y > > & c);
+ boost::coroutines::push_coroutine< boost::tuple< X, Y > > c( g);
+
+
+The current coroutine information (registers, flags, and stack and instruction
+pointer) is saved and the original context information is restored. Calling
+__push_coro_op__/__pull_coro_op__ resumes execution in the coroutine after
+saving the new state of the original routine.
+
+ void fn( boost::coroutines::pull_coroutine< void > & c, int j)
+ {
+ for( int i = 0; i < j; ++i)
+ {
+ std::cout << "fn(): local variable i == " << i << std::endl;
+
+ // save current coroutine
+ // value of local variable is preserved
+ // transfer execution control back to main()
+ c();
+
+ // push_coroutine<>::operator()() was called
+ // execution control transferred back from main()
+ }
+ }
+
+ int main( int argc, char * argv[])
+ {
+ // bind parameter '7' to coroutine-fn
+ boost::coroutines::push_coroutine< void > c( boost::bind( fn, _1, 7) );
+
+ std::cout << "main() starts coroutine c" << std::endl;
+
+ while ( c)
+ {
+ std::cout << "main() calls coroutine c" << std::endl;
+ // execution control is transferred to c
+ c();
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main() starts coroutine c
+ fn(): local variable i == 0
+ main() calls coroutine c
+ fn(): local variable i == 1
+ main() calls coroutine c
+ fn(): local variable i == 2
+ main() calls coroutine c
+ fn(): local variable i == 3
+ main() calls coroutine c
+ fn(): local variable i == 4
+ main() calls coroutine c
+ fn(): local variable i == 5
+ main() calls coroutine c
+ fn(): local variable i == 6
+ main() calls coroutine c
+ Done
+
+[warning Calling __push_coro_op__/__pull_coro_op__ from inside the [_same]
+coroutine results in undefined behaviour.]
+
+
+[heading Transfer of data]
+
+The template argument of __push_coro__, defines the types transferred
+to and in the case of __pull_coroutine__ the type transfered from
+__coro_fn__.
+
+__push_coro_op__ accepts argument defined as template argument and returns a
+refernce to __push_coro__.
+The arguments passed to __push_coro_op__, in one coroutine, is returned by
+__pull_coro_get__ in the other execution context.
+
+The value given to __push_coro_op__, in one coroutine, is returned by
+__pull_coro_get__ in the other routine.
+
+ void fn( boost::coroutines::pull_coroutine< int > & c)
+ {
+ // access the integer argument passed to push_coroutine< int >::operator()
+ int i = c.get();
+ std::cout << "fn(): local variable i == " << i << std::endl;
+
+ // save current coroutine context and
+ // transfer execution control back to caller
+ // after execution control returns from pull_coroutine< int >::operator()
+ // the transferred integer s accessed via pull_coroutine< int >::get()
+ i = c().get();
+
+ // i == 10 because c( 10) in main()
+ std::cout << "fn(): local variable i == " << i << std::endl;
+ ca( i);
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ coro_t c( fn, 7);
+
+ int x = c.get();
+ std::cout << "main(): transferred value: " << x << std::endl;
+
+ x = c( 10).get();
+ std::cout << "main(): transferred value: " << x << std::endl;
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ fn(): local variable i == 7
+ main(): transferred value: 7
+ fn(): local variable i == 10
+ main(): transferred value: 10
+ Done
+
+
+[heading __coro_fn__ with multiple arguments]
+
+__tuple__ can be used to transfer mutliple data types.
+
+ void fn( boost::coroutines::pull_coroutine< boost::tuple< int, int > > & c)
+ {
+ int a, b;
+ boost::tie( a, b) = c.get();
+ std::cout << "main(): " << a << " + " << b << " == " << a + b << std::endl;
+ boost::tie( a, b) = c().get();
+ std::cout << "main(): " << a << " + " << b << " == " << a + b << std::endl;
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ boost::coroutines::push_coroutine< boost::tuple< int, int > c( fn);
+
+ c( boost::make_tuple( 3, 7) );
+ c( boost::make_tuple( 5, 7) );
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ main(): 3 + 7 == 10
+ main(): 5 + 7 == 12
+ Done
+
+
+[heading Transfer of pointers and references]
+
+You can transfer references and pointers from and to coroutines but as usual
+you must take care (scope, no re-assignment of const references etc.).
+In the following code `x` points to `local` which is allocated on stack of
+`c`. When `c` goes out of scope the stack becomes deallocated. Using `x`
+after `c` is gone will fail!
+
+ struct X
+ {
+ void g();
+ };
+
+ typedef boost::coroutines::pull_coroutine< X* > coro_t;
+
+ // void fn( boost::coroutines::push_coroutine< X* > & ca)
+ void fn( coro_t::caller_t & ca) {
+ X local;
+ ca( & local);
+ }
+
+ int main() {
+ X * x = 0;
+ {
+ coro_t c( fn);
+ x = c.get(); // let x point to X on stack owned by c
+ // stack gets unwound -> X will be destructed
+ }
+ x->g(); // segmentation fault!
+ return EXIT_SUCCESS;
+ }
+
+
+[heading Range iterators]
+
+__boost_coroutine__ provides output- and input-iterators using __boost_range__.
+__pull_coro__ can be used via output-iterators using __begin__ and __end__.
+
+ typedef boost::coroutines::pull_coroutine< int > coro_t;
+ typedef boost::range_iterator< coro_t >::type iterator_t;
+
+ void power( boost::coroutines::push_coroutine< int > & c, int number, int exponent)
+ {
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ c( result);
+ }
+ }
+
+ int main()
+ {
+ coro_t c( boost::bind( power, _1, 2, 8) );
+ iterator_t e( boost::end( c) );
+ for ( iterator_t i( boost::begin( c) ); i != e; ++i)
+ std::cout << * i << " ";
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ 2 4 8 16 32 64 128 256
+ Done
+
+`BOOST_FOREACH` can be used to iterate over the coroutine range too.
+
+ typedef boost::coroutines::pull_coroutine< int > coro_t;
+ typedef boost::range_iterator< coro_t >::type iterator_t;
+
+ void power( boost::coroutines::push_coroutine< int > & c, int number, int exponent)
+ {
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ c( result);
+ }
+ }
+
+ int main()
+ {
+ coro_t c( boost::bind( power, _1, 2, 8) );
+ BOOST_FOREACH( int i, c)
+ { std::cout << i << " "; }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ 2 4 8 16 32 64 128 256
+ Done
+
+
+Input iterators can be created from __push_coro__.
+
+
+
+[heading Exit a __coro_fn__]
+
+__coro_fn__ is exited with a simple return statement jumping back to the calling
+routine. The __pull_coro__/__push_coro__ becomes complete, e.g. __coro_bool__
+will return 'false'.
+
+ typedef boost::coroutines::coroutine< int(int,int) > coro_t;
+
+ void power( boost::coroutines::pull_coroutine< boost::tuple< int, int > > & c, int number, int exponent)
+ {
+ int a, b;
+
+ boost::tie( a, b) = ca.get();
+ std::cout << "main(): " << a << " + " << b " == " << a + b << std::endl;
+ c();
+
+ boost::tie( a, b) = ca.get();
+ std::cout << "main(): " << a << " + " << b " == " << a + b << std::endl;
+ c();
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ coro_t c( power);
+ c( boost::make_tuple( 3, 7) );
+ BOOST_ASSERT( c);
+
+ c( boot::make_tuple( 5, 7) );
+ BOOST_ASSERT( ! c);
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ main(): 3 + 7 == 10
+ main(): 5 + 7 == 12
+ Done
+
+[important After returning from __coro_fn__ the __coro__ is complete (can not
+resumed with __coro_op__).]
+
+
+[heading Exceptions in __coro_fn__]
+
+An exception thrown inside __coro_fn__ will transferred via exception-pointer
+(see __boost_exception__ for details) and re-thrown by constructor or
+__coro_op__.
+
+ void f( boost::coroutines::push_coroutine< void > & c)
+ {
+ c();
+ throw std::runtime_error("abc");
+ }
+
+ int main( int argc, char * argv[])
+ {
+ boost::coroutines::pull_coroutine< void > c( f);
+ try
+ {
+ c();
+ }
+ catch ( std::exception const& e)
+ {
+ std::cout << "exception catched:" << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ exception catched: abc
+
+[important Code executed by coroutine must not prevent the propagation of the
+__forced_unwind__ exception. Absorbing that exception will cause stack
+unwinding to fail. Thus, any code that catches all exceptions must re-throw the
+pending exception.]
+
+ try
+ {
+ // code that might throw
+ }
+ catch( forced_unwind)
+ {
+ throw;
+ }
+ catch(...)
+ {
+ // possibly not re-throw pending exception
+ }
+
+
+[heading Stack unwinding]
+
+Sometimes it is necessary to unwind the stack of an unfinished coroutine to
+destroy local stack variables so they can release allocated resources (RAII
+pattern). The third argument of the coroutine constructor, `do_unwind`,
+indicates whether the destructor should unwind the stack (stack is unwound by
+default).
+
+Stack unwinding assumes the following preconditions:
+
+* The coroutine is not __not_a_coro__
+* The coroutine is not complete
+* The coroutine is not running
+* The coroutine owns a stack
+
+After unwinding, a __coro__ is complete.
+
+
+ struct X
+ {
+ X()
+ { std::cout << "X()" << std::endl; }
+
+ ~X()
+ { std::cout << "~X()" << std::endl; }
+ };
+
+ void fn( boost::coroutines::pull_coroutine< void > & c)
+ {
+ X x;
+
+ for ( int = 0;; ++i)
+ {
+ std::cout << "fn(): " << i << std::endl;
+ // transfer execution control back to main()
+ c();
+ }
+ }
+
+ int main( int argc, char * argv[])
+ {
+ {
+ boost::coroutines::push_coroutine< void > c( fn,
+ boost::coroutines::attributes(
+ boost::ctx::default_stacksize(),
+ boost::coroutines::stack_unwind) );
+
+ c();
+ c();
+ c();
+ c();
+ c();
+
+ std::cout << "c is complete: " << std::boolalpha << c.is_complete() << "\n";
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ X()
+ fn(): 0
+ fn(): 1
+ fn(): 2
+ fn(): 3
+ fn(): 4
+ fn(): 5
+ c is complete: false
+ ~X()
+ Done
+
+[important You must not swallow __forced_unwind__ exceptions!]
+
+
+[heading FPU preserving]
+
+Some applications do not use floating-point registers and can disable preserving
+fpu registers for performance reasons.
+
+[note According to the calling convention the FPU registers are preserved by default.]
+
+
+[section:push_coro Class `push_coroutine`]
+
+ #include <boost/coroutine/coroutine.hpp>
+
+ template< typename Arg >
+ class push_coroutine
+ {
+ public:
+ push_coroutine();
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ push_coroutine( Fn fn, attributes const& attr = attributes(),
+ StackAllocator const& stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ push_coroutine( Fn && fn, attributes const& attr = attributes(),
+ StackAllocator stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ push_coroutine( push_coroutine && other);
+
+ push_coroutine & operator=( push_coroutine && other);
+
+ operator unspecified-bool-type() const;
+
+ bool operator!() const;
+
+ void swap( push_coroutine & other);
+
+ bool empty() const;
+
+ push_coroutine & operator()( Arg arg);
+ };
+
+ template< typename Arg >
+ void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r);
+
+ template< typename Arg >
+ range_iterator< push_coroutine< Arg > >::type begin( push_coroutine< Arg > &);
+
+ template< typename Arg >
+ range_iterator< push_coroutine< Arg > >::type end( push_coroutine< Arg > &);
+
+[heading `push_coroutine()`]
+[variablelist
+[[Effects:] [Creates a coroutine representing __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ push_coroutine( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ push_coroutine( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+]
+
+[heading `push_coroutine( push_coroutine && other)`]
+[variablelist
+[[Effects:] [Moves the internal data of `other` to `*this`.
+`other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `push_coroutine & operator=( push_coroutine && other)`]
+[variablelist
+[[Effects:] [Destroys the internal data of `*this` and moves the
+internal data of `other` to `*this`. `other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `operator unspecified-bool-type() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns false. Otherwise true.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool operator!() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns true. Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool empty()`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true.
+Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `push_coroutine<> & operator()(Arg arg)`]
+[variablelist
+[[Preconditions:] [operator unspecified-bool-type() returns true for `*this`.]
+[[Effects:] [Execution control is transferred to __coro_fn__ and the argument
+`arg` is passed to the coroutine-function.]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `void swap( push_coroutine & other)`]
+[variablelist
+[[Effects:] [Swaps the internal data from `*this` with the values
+of `other`.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `T caller_type::operator()( R)`]
+[variablelist
+[[Effects:] [Gives execution control back to calling context by returning
+a value of type R. The return type of this function is a __tuple__ containing
+the arguments passed to __coro_op__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading Non-member function `swap()`]
+
+ template< typename Arg >
+ void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r);
+
+[variablelist
+[[Effects:] [As if 'l.swap( r)'.]]
+]
+
+[heading Non-member function `begin( push_coroutine< Arg > &)`]
+ template< typename Arg >
+ range_iterator< push_coroutine< Arg > >::type begin( push_coroutine< Arg > &);
+
+[variablelist
+[[Returns:] [Returns a range-iterator (output-iterator).]]
+]
+
+[heading Non-member function `end( push_coroutine< Arg > &)`]
+ template< typename Arg >
+ range_iterator< push_coroutine< Arg > >::type end( push_coroutine< Arg > &);
+
+[variablelist
+[[Returns:] [Returns a end range-iterator (output-iterator).]]
+]
+
+[endsect]
+
+
+[section:pull_coro Class `pull_coroutine`]
+
+ #include <boost/coroutine/coroutine.hpp>
+
+ template< typename R >
+ class pull_coroutine
+ {
+ public:
+ pull_coroutine();
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ pull_coroutine( Fn fn, attributes const& attr = attributes(),
+ StackAllocator const& stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ pull_coroutine( Fn && fn, attributes const& attr = attributes(),
+ StackAllocator stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ pull_coroutine( pull_coroutine && other);
+
+ pull_coroutine & operator=( pull_coroutine && other);
+
+ operator unspecified-bool-type() const;
+
+ bool operator!() const;
+
+ void swap( pull_coroutine & other);
+
+ bool empty() const;
+
+ pull_coroutine & operator()();
+
+ bool has_result() const;
+
+ R get() const;
+ };
+
+ template< typename R >
+ void swap( pull_coroutine< R > & l, pull_coroutine< R > & r);
+
+ template< typename R >
+ range_iterator< pull_coroutine< R > >::type begin( pull_coroutine< R > &);
+
+ template< typename R >
+ range_iterator< pull_coroutine< R > >::type end( pull_coroutine< R > &);
+
+[heading `pull_coroutine()`]
+[variablelist
+[[Effects:] [Creates a coroutine representing __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ pull_coroutine( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ pull_coroutine( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `pull_coroutine( pull_coroutine && other)`]
+[variablelist
+[[Effects:] [Moves the internal data of `other` to `*this`.
+`other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `pull_coroutine & operator=( pull_coroutine && other)`]
+[variablelist
+[[Effects:] [Destroys the internal data of `*this` and moves the
+internal data of `other` to `*this`. `other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `operator unspecified-bool-type() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns false. Otherwise true.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool operator!() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns true. Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool empty()`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true.
+Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `pull_coroutine<> & operator()()`]
+[variablelist
+[[Preconditions:] [`*this` is not a __not_a_coro__.]]
+[[Effects:] [Execution control is transferred to __coro_fn__ (no parameter are
+passed to the coroutine-function).]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `bool has_result()`]
+[variablelist
+[[Preconditions:] [`*this` is not a __not_a_coro__.]]
+[[Returns:] [If `*this` has a, the function returns true. Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `R get()()`]
+[variablelist
+[[Preconditions:] [`*this` is not a __not_a_coro__.]]
+[[Returns:] [Returns data transferred from coroutine-function via
+__push_coro_op__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `void swap( pull_coroutine & other)`]
+[variablelist
+[[Effects:] [Swaps the internal data from `*this` with the values
+of `other`.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading Non-member function `swap()`]
+
+ template< typename R >
+ void swap( pull_coroutine< R > & l, pull_coroutine< R > & r);
+
+[variablelist
+[[Effects:] [As if 'l.swap( r)'.]]
+]
+
+[heading Non-member function `begin( pull_coroutine< R > &)`]
+ template< typename R >
+ range_iterator< pull_coroutine< R > >::type begin( pull_coroutine< R > &);
+
+[variablelist
+[[Returns:] [Returns a range-iterator (input-iterator).]]
+]
+
+[heading Non-member function `end( pull_coroutine< R > &)`]
+ template< typename R >
+ range_iterator< pull_coroutine< R > >::type end( pull_coroutine< R > &);
+
+[variablelist
+[[Returns:] [Returns a end range-iterator (input-iterator).]]
+]
+
+[endsect]
+
+[endsect]

Modified: trunk/libs/coroutine/example/c++11/fibonacci.cpp
==============================================================================
--- trunk/libs/coroutine/example/c++11/fibonacci.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/c++11/fibonacci.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -9,7 +9,7 @@
 
 #include <boost/coroutine/all.hpp>
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 int main()
 {
     boost::coroutines::pull_coroutine< int > c(

Modified: trunk/libs/coroutine/example/c++11/same_fringe.cpp
==============================================================================
--- trunk/libs/coroutine/example/c++11/same_fringe.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/c++11/same_fringe.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -28,7 +28,7 @@
         leaf::create( "C") );
 }
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 class coro_visitor : public visitor
 {
 private:

Modified: trunk/libs/coroutine/example/echo.cpp
==============================================================================
--- trunk/libs/coroutine/example/echo.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/echo.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -10,7 +10,7 @@
 #include <boost/bind.hpp>
 #include <boost/coroutine/all.hpp>
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 typedef boost::coroutines::pull_coroutine< void > pull_coro_t;
 typedef boost::coroutines::push_coroutine< void > push_coro_t;
 

Modified: trunk/libs/coroutine/example/fibonacci.cpp
==============================================================================
--- trunk/libs/coroutine/example/fibonacci.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/fibonacci.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -10,7 +10,7 @@
 #include <boost/range.hpp>
 #include <boost/coroutine/all.hpp>
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 void fibonacci( boost::coroutines::push_coroutine< int > & c)
 {
     int first = 1, second = 1;

Modified: trunk/libs/coroutine/example/parallel.cpp
==============================================================================
--- trunk/libs/coroutine/example/parallel.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/parallel.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -10,7 +10,7 @@
 #include <boost/bind.hpp>
 #include <boost/coroutine/all.hpp>
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 void first( boost::coroutines::push_coroutine< void > & c)
 {
     std::cout << "started first! ";

Modified: trunk/libs/coroutine/example/power.cpp
==============================================================================
--- trunk/libs/coroutine/example/power.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/power.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -12,7 +12,7 @@
 #include <boost/range.hpp>
 #include <boost/coroutine/all.hpp>
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 void power( boost::coroutines::push_coroutine< int > & c, int number, int exponent)
 {
     int counter = 0;

Modified: trunk/libs/coroutine/example/same_fringe.cpp
==============================================================================
--- trunk/libs/coroutine/example/same_fringe.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/same_fringe.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -49,7 +49,7 @@
     return std::make_pair( tree1, tree2);
 }
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 bool match_trees( boost::coroutines::pull_coroutine< leaf & > & c1,
                   boost::coroutines::pull_coroutine< leaf & > & c2)
 {

Modified: trunk/libs/coroutine/example/segmented_stack.cpp
==============================================================================
--- trunk/libs/coroutine/example/segmented_stack.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/segmented_stack.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -31,7 +31,7 @@
     }
 }
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 void foo( boost::coroutines::pull_coroutine< void > & c)
 {
     bar( count);

Modified: trunk/libs/coroutine/example/tree.h
==============================================================================
--- trunk/libs/coroutine/example/tree.h Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/tree.h 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -91,7 +91,7 @@
 bool operator!=( leaf const& l, leaf const& r)
 { return l.value != r.value; }
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 class tree_visitor : public visitor
 {
 private:

Modified: trunk/libs/coroutine/example/unwind.cpp
==============================================================================
--- trunk/libs/coroutine/example/unwind.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/example/unwind.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -10,7 +10,7 @@
 #include <boost/bind.hpp>
 #include <boost/coroutine/all.hpp>
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 struct X : private boost::noncopyable
 {
     X() { std::cout << "X()" << std::endl; }

Modified: trunk/libs/coroutine/performance/performance.cpp
==============================================================================
--- trunk/libs/coroutine/performance/performance.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/performance/performance.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -32,7 +32,7 @@
 # define CALL_COROUTINE(z,n,unused) \
     c();
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 void fn( boost::coroutines::push_coroutine< void > & c)
 { while ( true) c(); }
 

Modified: trunk/libs/coroutine/test/test_coroutine.cpp
==============================================================================
--- trunk/libs/coroutine/test/test_coroutine.cpp Thu Jun 6 13:11:17 2013 (r84656)
+++ trunk/libs/coroutine/test/test_coroutine.cpp 2013-06-06 13:26:45 EDT (Thu, 06 Jun 2013) (r84657)
@@ -37,7 +37,7 @@
 int value8 = 0;
 int value9 = 0;
 
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
 struct X : private boost::noncopyable
 {
     X() { value1 = 7; }
@@ -1036,7 +1036,7 @@
     test->add( BOOST_TEST_CASE( & test_fp) );
     test->add( BOOST_TEST_CASE( & test_ptr) );
     test->add( BOOST_TEST_CASE( & test_const_ptr) );
-#ifndef BOOST_COROUTINES_V2
+#ifndef BOOST_COROUTINES_UNIDIRECT
     test->add( BOOST_TEST_CASE( & test_pre) );
     test->add( BOOST_TEST_CASE( & test_post) );
 #endif


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