|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r84428 - in trunk: boost/coroutine/detail boost/coroutine/v1/detail boost/coroutine/v2 boost/coroutine/v2/detail libs/coroutine/example libs/coroutine/example/c++11 libs/coroutine/performance libs/coroutine/test
From: oliver.kowalke_at_[hidden]
Date: 2013-05-22 16:15:49
Author: olli
Date: 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
New Revision: 84428
URL: http://svn.boost.org/trac/boost/changeset/84428
Log:
coroutine: activate new interface V2
Added:
trunk/boost/coroutine/detail/stack_tuple.hpp (contents, props changed)
trunk/boost/coroutine/detail/trampoline.hpp (contents, props changed)
trunk/boost/coroutine/v2/coroutine.hpp (contents, props changed)
trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp (contents, props changed)
trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp (contents, props changed)
trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp (contents, props changed)
trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp (contents, props changed)
trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp (contents, props changed)
trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp (contents, props changed)
Text files modified:
trunk/boost/coroutine/detail/config.hpp | 6
trunk/boost/coroutine/detail/exceptions.hpp | 6
trunk/boost/coroutine/v1/detail/coroutine_object.hpp | 43 ---
trunk/libs/coroutine/example/Jamfile.v2 | 18
trunk/libs/coroutine/example/c++11/fibonacci.cpp | 24 +
trunk/libs/coroutine/example/c++11/same_fringe.cpp | 80 ++++-
trunk/libs/coroutine/example/echo.cpp | 38 ++
trunk/libs/coroutine/example/fibonacci.cpp | 35 +-
trunk/libs/coroutine/example/parallel.cpp | 40 +++
trunk/libs/coroutine/example/power.cpp | 60 ++--
trunk/libs/coroutine/example/same_fringe.cpp | 52 +++
trunk/libs/coroutine/example/segmented_stack.cpp | 22 +
trunk/libs/coroutine/example/tree.h | 28 ++
trunk/libs/coroutine/example/unwind.cpp | 35 ++
trunk/libs/coroutine/performance/performance.cpp | 83 +++++
trunk/libs/coroutine/test/test_coroutine.cpp | 523 +++++++++++++++++++++++++++++++++++++++
16 files changed, 943 insertions(+), 150 deletions(-)
Modified: trunk/boost/coroutine/detail/config.hpp
==============================================================================
--- trunk/boost/coroutine/detail/config.hpp (original)
+++ trunk/boost/coroutine/detail/config.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -46,8 +46,8 @@
# define BOOST_COROUTINES_SEGMENTS 10
#endif
-//#ifndef BOOST_COROUTINES_V1
-//# define BOOST_COROUTINES_V2
-//#endif
+#ifndef BOOST_COROUTINES_V1
+# define BOOST_COROUTINES_V2
+#endif
#endif // BOOST_COROUTINES_DETAIL_CONFIG_H
Modified: trunk/boost/coroutine/detail/exceptions.hpp
==============================================================================
--- trunk/boost/coroutine/detail/exceptions.hpp (original)
+++ trunk/boost/coroutine/detail/exceptions.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -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_DETAIL_EXCEPTIONs_H
-#define BOOST_COROUTINES_DETAIL_EXCEPTIONs_H
+#ifndef BOOST_COROUTINES_DETAIL_EXCEPTIONS_H
+#define BOOST_COROUTINES_DETAIL_EXCEPTIONS_H
#include <boost/config.hpp>
@@ -25,4 +25,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_DETAIL_EXCEPTIONs_H
+#endif // BOOST_COROUTINES_DETAIL_EXCEPTIONS_H
Added: trunk/boost/coroutine/detail/stack_tuple.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/detail/stack_tuple.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,47 @@
+
+// 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_DETAIL_STACK_TUPLE_H
+#define BOOST_COROUTINES_DETAIL_STACK_TUPLE_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename StackAllocator >
+struct stack_tuple
+{
+ coroutines::stack_context stack_ctx;
+ StackAllocator stack_alloc;
+
+ stack_tuple( StackAllocator const& stack_alloc_, std::size_t size) :
+ stack_ctx(),
+ stack_alloc( stack_alloc_)
+ { stack_alloc.allocate( stack_ctx, size); }
+
+ ~stack_tuple()
+ { stack_alloc.deallocate( stack_ctx); }
+};
+
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_STACK_TUPLE_H
Added: trunk/boost/coroutine/detail/trampoline.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/detail/trampoline.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,52 @@
+
+// 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_DETAIL_TRAMPOLINE_H
+#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Coroutine >
+void trampoline1( intptr_t vp)
+{
+ BOOST_ASSERT( vp);
+
+ reinterpret_cast< Coroutine * >( vp)->run();
+}
+
+template< typename Coroutine, typename Arg >
+void trampoline2( intptr_t vp)
+{
+ BOOST_ASSERT( vp);
+
+ tuple< Coroutine *, Arg > * tpl(
+ reinterpret_cast< tuple< Coroutine *, Arg > * >( vp) );
+ Coroutine * coro( get< 0 >( * tpl) );
+ Arg arg( get< 1 >( * tpl) );
+
+ coro->run( arg);
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
Modified: trunk/boost/coroutine/v1/detail/coroutine_object.hpp
==============================================================================
--- trunk/boost/coroutine/v1/detail/coroutine_object.hpp (original)
+++ trunk/boost/coroutine/v1/detail/coroutine_object.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -25,8 +25,11 @@
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/holder.hpp>
#include <boost/coroutine/detail/param.hpp>
+#include <boost/coroutine/detail/stack_tuple.hpp>
+#include <boost/coroutine/detail/trampoline.hpp>
#include <boost/coroutine/flags.hpp>
#include <boost/coroutine/stack_context.hpp>
+#include <boost/coroutine/stack_context.hpp>
#include <boost/coroutine/v1/detail/arg.hpp>
#include <boost/coroutine/v1/detail/coroutine_base.hpp>
@@ -43,46 +46,6 @@
namespace coroutines {
namespace detail {
-template< typename Coroutine >
-void trampoline1( intptr_t vp)
-{
- BOOST_ASSERT( vp);
-
- reinterpret_cast< Coroutine * >( vp)->run();
-}
-
-template< typename Coroutine, typename Arg >
-void trampoline2( intptr_t vp)
-{
- BOOST_ASSERT( vp);
-
- tuple< Coroutine *, Arg > * tpl(
- reinterpret_cast< tuple< Coroutine *, Arg > * >( vp) );
- Coroutine * coro( get< 0 >( * tpl) );
- Arg arg( get< 1 >( * tpl) );
-
- coro->run( arg);
-}
-
-template< typename StackAllocator >
-struct stack_tuple
-{
- coroutines::stack_context stack_ctx;
- StackAllocator stack_alloc;
-
- stack_tuple( StackAllocator const& stack_alloc_, std::size_t size) :
- stack_ctx(),
- stack_alloc( stack_alloc_)
- {
- stack_alloc.allocate( stack_ctx, size);
- }
-
- ~stack_tuple()
- {
- stack_alloc.deallocate( stack_ctx);
- }
-};
-
template<
typename Signature,
typename Fn, typename StackAllocator, typename Allocator,
Added: trunk/boost/coroutine/v2/coroutine.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/v2/coroutine.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,2428 @@
+
+// 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_COROUTINE_H
+#define BOOST_COROUTINES_V2_COROUTINE_H
+
+#include <cstddef>
+#include <iterator>
+#include <memory>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/move/move.hpp>
+#include <boost/optional.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/coroutine/attributes.hpp>
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/param.hpp>
+#include <boost/coroutine/stack_allocator.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_base.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_caller.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_object.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_base.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_caller.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_object.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+template< typename Arg >
+class push_coroutine
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::pull_coroutine_object;
+
+ 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)
+
+ template< typename Allocator >
+ push_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::push_coroutine_caller<
+ Arg, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ push_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#else
+ template< typename Fn >
+ explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+
+ push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
+ {
+ push_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( push_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ push_coroutine & operator()( Arg const& arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( arg);
+ return * this;
+ }
+
+ push_coroutine & operator()( Arg && arg) {
+ BOOST_ASSERT( * this);
+
+ impl_->push( arg);
+ return * this;
+ }
+#else
+ push_coroutine & operator()( Arg arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( forward< Arg >( arg) );
+ return * this;
+ }
+
+ push_coroutine & operator()( BOOST_RV_REF( Arg) arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( forward< Arg >( arg) );
+ return * this;
+ }
+#endif
+
+ class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void >
+ {
+ private:
+ push_coroutine< Arg > * c_;
+
+ public:
+ iterator() :
+ c_( 0)
+ {}
+
+ explicit iterator( push_coroutine< Arg > * c) :
+ c_( c)
+ {}
+
+ iterator & operator=( Arg a)
+ {
+ BOOST_ASSERT( c_);
+ if ( ! ( * c_)( a) ) c_ = 0;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_; }
+
+ iterator & operator*()
+ { return * this; }
+
+ iterator & operator++()
+ { return * this; }
+ };
+
+ struct const_iterator;
+};
+
+template< typename Arg >
+class push_coroutine< Arg & >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::pull_coroutine_object;
+
+ 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)
+
+ template< typename Allocator >
+ push_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::push_coroutine_caller<
+ Arg &, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ push_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#else
+ template< typename Fn >
+ explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+
+ push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
+ {
+ push_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( push_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ push_coroutine & operator()( Arg & arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( forward< Arg & >( arg) );
+ return * this;
+ }
+
+ class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void >
+ {
+ private:
+ push_coroutine< Arg & > * c_;
+
+ public:
+ iterator() :
+ c_( 0)
+ {}
+
+ explicit iterator( push_coroutine< Arg & > * c) :
+ c_( c)
+ {}
+
+ iterator & operator=( Arg & a)
+ {
+ BOOST_ASSERT( c_);
+ if ( ! ( * c_)( a) ) c_ = 0;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_; }
+
+ iterator & operator*()
+ { return * this; }
+
+ iterator & operator++()
+ { return * this; }
+ };
+
+ struct const_iterator;
+};
+
+template< typename Arg >
+class push_coroutine< Arg const& >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::pull_coroutine_object;
+
+ typedef detail::push_coroutine_base< Arg const& > base_t;
+ typedef typename base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
+
+ template< typename Allocator >
+ push_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::push_coroutine_caller<
+ Arg const&, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ push_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#else
+ template< typename Fn >
+ explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+
+ push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
+ {
+ push_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( push_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ push_coroutine & operator()( Arg const& arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( forward< Arg const& >( arg) );
+ return * this;
+ }
+
+ class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void >
+ {
+ private:
+ push_coroutine< Arg const& > * c_;
+
+ public:
+ iterator() :
+ c_( 0)
+ {}
+
+ explicit iterator( push_coroutine< Arg const& > * c) :
+ c_( c)
+ {}
+
+ iterator & operator=( Arg const& a)
+ {
+ BOOST_ASSERT( c_);
+ if ( ! ( * c_)( a) ) c_ = 0;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_; }
+
+ iterator & operator*()
+ { return * this; }
+
+ iterator & operator++()
+ { return * this; }
+ };
+
+ struct const_iterator;
+};
+
+template<>
+class push_coroutine< void >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::pull_coroutine_object;
+
+ typedef detail::push_coroutine_base< void > base_t;
+ typedef typename base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
+
+ template< typename Allocator >
+ push_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::push_coroutine_caller<
+ void, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ 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);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#else
+ template< typename Fn >
+ explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+
+ push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
+ {
+ push_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( push_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ push_coroutine & operator()()
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push();
+ return * this;
+ }
+
+ struct iterator;
+ struct const_iterator;
+};
+
+
+
+template< typename R >
+class pull_coroutine
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::push_coroutine_object;
+
+ 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)
+
+ template< typename Allocator >
+ pull_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc,
+ optional< R > const& result) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_caller<
+ R, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a, result) );
+ }
+
+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 >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+#else
+ template< typename Fn >
+ explicit pull_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+#endif
+
+ pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
+ {
+ pull_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( pull_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ pull_coroutine & operator()()
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->pull();
+ return * this;
+ }
+
+ bool has_result() const
+ {
+ BOOST_ASSERT( ! empty() );
+
+ return impl_->has_result();
+ }
+
+ R get() const
+ {
+ BOOST_ASSERT( has_result() );
+
+ return impl_->get();
+ }
+
+ class iterator : public std::iterator< std::input_iterator_tag, typename remove_reference< R >::type >
+ {
+ private:
+ pull_coroutine< R > * c_;
+ optional< R > val_;
+
+ void fetch_()
+ {
+ BOOST_ASSERT( c_);
+
+ if ( ! c_->has_result() )
+ {
+ c_ = 0;
+ val_ = none;
+ return;
+ }
+ val_ = c_->get();
+ }
+
+ void increment_()
+ {
+ BOOST_ASSERT( c_);
+ BOOST_ASSERT( * c_);
+
+ ( * c_)();
+ fetch_();
+ }
+
+ public:
+ typedef typename iterator::pointer pointer_t;
+ typedef typename iterator::reference reference_t;
+
+ iterator() :
+ c_( 0), val_()
+ {}
+
+ explicit iterator( pull_coroutine< R > * c) :
+ c_( c), val_()
+ { fetch_(); }
+
+ iterator( iterator const& other) :
+ c_( other.c_), val_( other.val_)
+ {}
+
+ iterator & operator=( iterator const& other)
+ {
+ if ( this == & other) return * this;
+ c_ = other.c_;
+ val_ = other.val_;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_ && other.val_ == val_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_ || other.val_ != val_; }
+
+ iterator & operator++()
+ {
+ increment_();
+ return * this;
+ }
+
+ iterator operator++( int)
+ {
+ iterator tmp( * this);
+ ++*this;
+ return tmp;
+ }
+
+ reference_t operator*() const
+ { return const_cast< optional< R > & >( val_).get(); }
+
+ pointer_t operator->() const
+ { return const_cast< optional< R > & >( val_).get_ptr(); }
+ };
+
+ class const_iterator : public std::iterator< std::input_iterator_tag, const typename remove_reference< R >::type >
+ {
+ private:
+ pull_coroutine< R > * c_;
+ optional< R > val_;
+
+ void fetch_()
+ {
+ BOOST_ASSERT( c_);
+
+ if ( ! c_->has_result() )
+ {
+ c_ = 0;
+ val_ = none;
+ return;
+ }
+ val_ = c_->get();
+ }
+
+ void increment_()
+ {
+ BOOST_ASSERT( c_);
+ BOOST_ASSERT( * c_);
+
+ ( * c_)();
+ fetch_();
+ }
+
+ public:
+ typedef typename const_iterator::pointer pointer_t;
+ typedef typename const_iterator::reference reference_t;
+
+ const_iterator() :
+ c_( 0), val_()
+ {}
+
+ explicit const_iterator( pull_coroutine< R > const* c) :
+ c_( const_cast< pull_coroutine< R > * >( c) ), val_()
+ { fetch_(); }
+
+ const_iterator( const_iterator const& other) :
+ c_( other.c_), val_( other.val_)
+ {}
+
+ const_iterator & operator=( const_iterator const& other)
+ {
+ if ( this == & other) return * this;
+ c_ = other.c_;
+ val_ = other.val_;
+ return * this;
+ }
+
+ bool operator==( const_iterator const& other)
+ { return other.c_ == c_ && other.val_ == val_; }
+
+ bool operator!=( const_iterator const& other)
+ { return other.c_ != c_ || other.val_ != val_; }
+
+ const_iterator & operator++()
+ {
+ increment_();
+ return * this;
+ }
+
+ const_iterator operator++( int)
+ {
+ const_iterator tmp( * this);
+ ++*this;
+ return tmp;
+ }
+
+ reference_t operator*() const
+ { return val_.get(); }
+
+ pointer_t operator->() const
+ { return val_.get_ptr(); }
+ };
+};
+
+template<>
+class pull_coroutine< void >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::push_coroutine_object;
+
+ typedef detail::pull_coroutine_base< void > base_t;
+ typedef 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)
+
+ template< typename Allocator >
+ pull_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_caller<
+ void, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ pull_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ 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<
+ void, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > 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<
+ void, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > 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<
+ void, Fn, StackAllocator, Allocator,
+ push_coroutine< void >
+ > 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<
+ void, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > 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<
+ void, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > 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<
+ void, Fn, StackAllocator, Allocator,
+ push_coroutine< void >
+ > 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<
+ void, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > 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<
+ void, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > 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<
+ void, Fn, StackAllocator, Allocator,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+#endif
+
+ pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
+ {
+ pull_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( pull_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ pull_coroutine & operator()()
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->pull();
+ return * this;
+ }
+
+ struct iterator;
+ struct const_iterator;
+};
+
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Fn >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > 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 >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > 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 >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ pull_coroutine< void >
+ > 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 Arg >
+template< typename Fn >
+push_coroutine< Arg >::push_coroutine( Fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg & >::push_coroutine( Fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg & >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg & >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine<Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg const& >::push_coroutine( Fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg const& >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg const& >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg const& >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg const&, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg const& >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Fn >
+push_coroutine< void >::push_coroutine( Fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > 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 >
+push_coroutine< void >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > 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 >
+push_coroutine< void >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Fn >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > 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 >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > 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 >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ pull_coroutine< void >
+ > 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
+
+template< typename R >
+void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
+{ l.swap( r); }
+
+template< typename Arg >
+void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
+{ l.swap( r); }
+
+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 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::push_coroutine< Arg > >
+{ typedef typename coroutines::push_coroutine< Arg >::iterator type; };
+
+template< typename Arg >
+struct range_const_iterator< coroutines::push_coroutine< Arg > >
+{ typedef typename coroutines::push_coroutine< Arg >::const_iterator type; };
+
+template< typename R >
+struct range_mutable_iterator< coroutines::pull_coroutine< R > >
+{ typedef typename coroutines::pull_coroutine< R >::iterator type; };
+
+template< typename R >
+struct range_const_iterator< coroutines::pull_coroutine< R > >
+{ typedef typename coroutines::pull_coroutine< R >::const_iterator type; };
+
+}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_V2_COROUTINE_H
Added: trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,232 @@
+
+// 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_DETAIL_PULL_COROUTINE_BASE_H
+#define BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_BASE_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/context/fcontext.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+#include <boost/coroutine/detail/holder.hpp>
+#include <boost/coroutine/detail/param.hpp>
+#include <boost/coroutine/detail/exceptions.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+struct stack_context;
+
+namespace detail {
+
+template< typename R >
+class pull_coroutine_base : private noncopyable
+{
+public:
+ typedef intrusive_ptr< pull_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class push_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+ optional< R > result_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ pull_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx),
+ result_()
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ pull_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ optional< R > const& result) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee),
+ result_( result)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void pull()
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< R > hldr_to( & caller_);
+ holder< R > * hldr_from(
+ reinterpret_cast< holder< R > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ result_ = hldr_from->data;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ bool has_result() const
+ { return result_; }
+
+ R get() const
+ {
+ BOOST_ASSERT( has_result() );
+
+ return result_.get();
+ }
+};
+
+template<>
+class pull_coroutine_base< void > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< pull_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class push_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ pull_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ pull_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void pull()
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< void > hldr_to( & caller_);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_BASE_H
Added: trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,84 @@
+// 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_DETAIL_PULL_COROUTINE_CALLER_H
+#define BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_CALLER_H
+
+#include <boost/config.hpp>
+#include <boost/context/fcontext.hpp>
+#include <boost/optional.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_base.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename R, typename Allocator >
+class pull_coroutine_caller : public pull_coroutine_base< R >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_caller< R, Allocator >
+ >::other allocator_t;
+
+ pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu,
+ allocator_t const& alloc, optional< R > const& data) BOOST_NOEXCEPT :
+ pull_coroutine_base< R >( callee, unwind, preserve_fpu, data),
+ alloc_( alloc)
+ {}
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+
+private:
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_caller * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+};
+
+template< typename Allocator >
+class pull_coroutine_caller< void, Allocator > : public pull_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_caller< void, Allocator >
+ >::other allocator_t;
+
+ pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu,
+ allocator_t const& alloc) BOOST_NOEXCEPT :
+ pull_coroutine_base< void >( callee, unwind, preserve_fpu),
+ alloc_( alloc)
+ {}
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+
+private:
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_caller * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_CALLER_H
Added: trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,768 @@
+
+// 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_DETAIL_PULL_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_V2_DETAIL_PULL_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/detail/stack_tuple.hpp>
+#include <boost/coroutine/detail/trampoline.hpp>
+#include <boost/coroutine/flags.hpp>
+#include <boost/coroutine/stack_context.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_base.hpp>
+
+#ifdef BOOST_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4355) // using 'this' in initializer list
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object : private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R > * hldr_from(
+ reinterpret_cast< holder< R > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ this->result_ = hldr_from->data;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ pull_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ pull_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create push_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R > * hldr_from(
+ reinterpret_cast< holder< R > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R > * hldr_from(
+ reinterpret_cast< holder< R > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< void, Fn, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< 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
+ pull_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ pull_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create push_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< void, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< 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:
+ pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< void, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< 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:
+ pull_coroutine_object( const reference_wrapper< Fn > fn,
+ attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#ifdef BOOST_MSVC
+ #pragma warning (pop)
+#endif
+
+#endif // BOOST_COROUTINES_V2_DETAIL_PULL_COROUTINE_OBJECT_H
Added: trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,441 @@
+
+// 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_DETAIL_PUSH_COROUTINE_BASE_H
+#define BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_BASE_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/context/fcontext.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/exceptions.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+struct stack_context;
+
+namespace detail {
+
+template< typename Arg >
+class push_coroutine_base : private noncopyable
+{
+public:
+ typedef intrusive_ptr< push_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class pull_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ push_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ push_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~push_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ void push( Arg const& arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg > hldr_to( & caller_, arg);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ void push( Arg && arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg > hldr_to( & caller_, arg);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+#else
+ void push( Arg arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg > hldr_to( & caller_, arg);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ void push( BOOST_RV_REF( Arg) arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg > hldr_to( & caller_, arg);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+#endif
+};
+
+template< typename Arg >
+class push_coroutine_base< Arg & > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< push_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class pull_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ push_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ push_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~push_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void push( Arg & arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg & > hldr_to( & caller_, arg);
+ holder< Arg & > * hldr_from(
+ reinterpret_cast< holder< Arg & > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+};
+
+template< typename Arg >
+class push_coroutine_base< Arg const& > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< push_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class pull_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ push_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ push_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~push_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void push( Arg const& arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg const& > hldr_to( & caller_, arg);
+ holder< Arg const& > * hldr_from(
+ reinterpret_cast< holder< Arg const& > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+};
+
+template<>
+class push_coroutine_base< void > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< push_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class pull_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ push_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ push_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~push_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void push()
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< void > hldr_to( & caller_);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_BASE_H
Added: trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,56 @@
+// 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_DETAIL_PUSH_COROUTINE_CALLER_H
+#define BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_CALLER_H
+
+#include <boost/config.hpp>
+#include <boost/context/fcontext.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_base.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Arg, typename Allocator >
+class push_coroutine_caller : public push_coroutine_base< Arg >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_caller< Arg, Allocator >
+ >::other allocator_t;
+
+ push_coroutine_caller( coroutine_context const& callee, bool unwind,
+ bool preserve_fpu, allocator_t const& alloc) BOOST_NOEXCEPT :
+ push_coroutine_base< Arg >( callee, unwind, preserve_fpu),
+ alloc_( alloc)
+ {}
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+
+private:
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_caller * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_CALLER_H
Added: trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -0,0 +1,823 @@
+
+// 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_DETAIL_PUSH_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_V2_DETAIL_PUSH_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/detail/stack_tuple.hpp>
+#include <boost/coroutine/detail/trampoline.hpp>
+#include <boost/coroutine/flags.hpp>
+#include <boost/coroutine/stack_context.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_base.hpp>
+
+#ifdef BOOST_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4355) // using 'this' in initializer list
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object : private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ push_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ push_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< void, Fn, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< 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
+ push_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ push_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< void, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< 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:
+ push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< void, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< 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:
+ push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#ifdef BOOST_MSVC
+ #pragma warning (pop)
+#endif
+
+#endif // BOOST_COROUTINES_V2_DETAIL_PUSH_COROUTINE_OBJECT_H
Modified: trunk/libs/coroutine/example/Jamfile.v2
==============================================================================
--- trunk/libs/coroutine/example/Jamfile.v2 (original)
+++ trunk/libs/coroutine/example/Jamfile.v2 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -69,18 +69,18 @@
: same_fringe.cpp
;
-exe asio/stream_client
- : asio/stream_client.cpp
- ;
-
-exe asio/stream_server
- : asio/stream_server.cpp
- ;
+#exe asio/stream_client
+# : asio/stream_client.cpp
+# ;
+#
+#exe asio/stream_server
+# : asio/stream_server.cpp
+# ;
-#exe same_fringe
+#exe same_fringe11
# : c++11/same_fringe.cpp
# ;
#
-#exe fibonacci
+#exe fibonacci11
# : c++11/fibonacci.cpp
# ;
Modified: trunk/libs/coroutine/example/c++11/fibonacci.cpp
==============================================================================
--- trunk/libs/coroutine/example/c++11/fibonacci.cpp (original)
+++ trunk/libs/coroutine/example/c++11/fibonacci.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -9,6 +9,29 @@
#include <boost/coroutine/all.hpp>
+#ifdef BOOST_COROUTINES_V2
+int main()
+{
+ boost::coroutines::pull_coroutine< int > c(
+ [&]( boost::coroutines::push_coroutine< int > & c) {
+ int first = 1, second = 1;
+ for ( int i = 0; i < 10; ++i)
+ {
+ int third = first + second;
+ first = second;
+ second = third;
+ c( third);
+ }
+ });
+
+ for ( auto i : c)
+ std::cout << i << " ";
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
int main()
{
boost::coroutines::coroutine< int() > c(
@@ -30,3 +53,4 @@
return EXIT_SUCCESS;
}
+#endif
Modified: trunk/libs/coroutine/example/c++11/same_fringe.cpp
==============================================================================
--- trunk/libs/coroutine/example/c++11/same_fringe.cpp (original)
+++ trunk/libs/coroutine/example/c++11/same_fringe.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -10,13 +10,32 @@
#include "tree.h"
+node::ptr_t create_tree1()
+{
+ return branch::create(
+ leaf::create( "A"),
+ branch::create(
+ leaf::create( "B"),
+ leaf::create( "C") ) );
+}
+
+node::ptr_t create_tree2()
+{
+ return branch::create(
+ branch::create(
+ leaf::create( "A"),
+ leaf::create( "B") ),
+ leaf::create( "C") );
+}
+
+#ifdef BOOST_COROUTINES_V2
class coro_visitor : public visitor
{
private:
- boost::coroutines::coroutine< void( leaf&) > & c_;
+ boost::coroutines::push_coroutine< leaf& > & c_;
public:
- coro_visitor( boost::coroutines::coroutine< void( leaf&) > & c) :
+ coro_visitor( boost::coroutines::push_coroutine< leaf& > & c) :
c_( c)
{}
@@ -30,23 +49,51 @@
{ c_( l); }
};
-node::ptr_t create_tree1()
+int main()
{
- return branch::create(
- leaf::create( "A"),
- branch::create(
- leaf::create( "B"),
- leaf::create( "C") ) );
-}
+ node::ptr_t t1 = create_tree1();
+ boost::coroutines::pull_coroutine< leaf& > c1(
+ [&]( boost::coroutines::push_coroutine< leaf & > & c) {
+ coro_visitor v( c);
+ t1->accept( v);
+ });
-node::ptr_t create_tree2()
-{
- return branch::create(
- branch::create(
- leaf::create( "A"),
- leaf::create( "B") ),
- leaf::create( "C") );
+ node::ptr_t t2 = create_tree2();
+ boost::coroutines::pull_coroutine< leaf& > c2(
+ [&]( boost::coroutines::push_coroutine< leaf & > & c) {
+ coro_visitor v( c);
+ t2->accept( v);
+ });
+
+ bool result = std::equal(
+ boost::begin( c1),
+ boost::end( c1),
+ boost::begin( c2) );
+
+ std::cout << std::boolalpha << "same fringe == " << result << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
}
+#else
+class coro_visitor : public visitor
+{
+private:
+ boost::coroutines::coroutine< void( leaf&) > & c_;
+
+public:
+ coro_visitor( boost::coroutines::coroutine< void( leaf&) > & c) :
+ c_( c)
+ {}
+
+ void visit( branch & b)
+ {
+ if ( b.left) b.left->accept( * this);
+ if ( b.right) b.right->accept( * this);
+ }
+
+ void visit( leaf & l)
+ { c_( l); }
+};
int main()
{
@@ -73,3 +120,4 @@
return EXIT_SUCCESS;
}
+#endif
Modified: trunk/libs/coroutine/example/echo.cpp
==============================================================================
--- trunk/libs/coroutine/example/echo.cpp (original)
+++ trunk/libs/coroutine/example/echo.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -10,6 +10,43 @@
#include <boost/bind.hpp>
#include <boost/coroutine/all.hpp>
+#ifdef BOOST_COROUTINES_V2
+typedef boost::coroutines::pull_coroutine< void > pull_coro_t;
+typedef boost::coroutines::push_coroutine< void > push_coro_t;
+
+void echo( pull_coro_t & c, int i)
+{
+ std::cout << i;
+ c();
+}
+
+void runit( push_coro_t & ca)
+{
+ std::cout << "started! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ push_coro_t c( boost::bind( echo, _1, i) );
+ while ( c)
+ c();
+ ca();
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ pull_coro_t c( runit);
+ while ( c) {
+ std::cout << "-";
+ c();
+ }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
typedef boost::coroutines::coroutine< void() > coro_t;
void echo( coro_t & ca, int i)
@@ -44,3 +81,4 @@
return EXIT_SUCCESS;
}
+#endif
Modified: trunk/libs/coroutine/example/fibonacci.cpp
==============================================================================
--- trunk/libs/coroutine/example/fibonacci.cpp (original)
+++ trunk/libs/coroutine/example/fibonacci.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -10,7 +10,8 @@
#include <boost/range.hpp>
#include <boost/coroutine/all.hpp>
-void fibonacci( boost::coroutines::coroutine< void( int) > & c)
+#ifdef BOOST_COROUTINES_V2
+void fibonacci( boost::coroutines::push_coroutine< int > & c)
{
int first = 1, second = 1;
while ( true)
@@ -24,9 +25,9 @@
int main()
{
- boost::coroutines::coroutine< int() > c( fibonacci);
+ boost::coroutines::pull_coroutine< int > c( fibonacci);
boost::range_iterator<
- boost::coroutines::coroutine< int() >
+ boost::coroutines::pull_coroutine< int >
>::type it( boost::begin( c) );
for ( int i = 0; i < 10; ++i)
{
@@ -38,27 +39,25 @@
return EXIT_SUCCESS;
}
+#else
+void fibonacci( boost::coroutines::coroutine< void( int) > & c)
+{
+ int first = 1, second = 1;
+ while ( true)
+ {
+ int third = first + second;
+ first = second;
+ second = third;
+ c( third);
+ }
+}
-// C++11
-#if 0
int main()
{
- boost::coroutines::coroutine< int() > c(
- [&]( boost::coroutines::coroutine< void( int) > & c) {
- int first = 1, second = 1;
- while ( true)
- {
- int third = first + second;
- first = second;
- second = third;
- c( third);
- }
- });
-
+ boost::coroutines::coroutine< int() > c( fibonacci);
boost::range_iterator<
boost::coroutines::coroutine< int() >
>::type it( boost::begin( c) );
-
for ( int i = 0; i < 10; ++i)
{
std::cout << * it << " ";
Modified: trunk/libs/coroutine/example/parallel.cpp
==============================================================================
--- trunk/libs/coroutine/example/parallel.cpp (original)
+++ trunk/libs/coroutine/example/parallel.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -10,6 +10,45 @@
#include <boost/bind.hpp>
#include <boost/coroutine/all.hpp>
+#ifdef BOOST_COROUTINES_V2
+void first( boost::coroutines::push_coroutine< void > & c)
+{
+ std::cout << "started first! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ c();
+ std::cout << "a" << i;
+ }
+}
+
+void second( boost::coroutines::push_coroutine< void > & c)
+{
+ std::cout << "started second! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ c();
+ std::cout << "b" << i;
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ boost::coroutines::pull_coroutine< void > c1( boost::bind( first, _1) );
+ boost::coroutines::pull_coroutine< void > c2( boost::bind( second, _1) );
+ while ( c1 && c2) {
+ c1();
+ std::cout << " ";
+ c2();
+ std::cout << " ";
+ }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
typedef boost::coroutines::coroutine< void() > coroutine_t;
void first( coroutine_t::caller_type & self)
@@ -49,3 +88,4 @@
return EXIT_SUCCESS;
}
+#endif
Modified: trunk/libs/coroutine/example/power.cpp
==============================================================================
--- trunk/libs/coroutine/example/power.cpp (original)
+++ trunk/libs/coroutine/example/power.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -12,11 +12,8 @@
#include <boost/range.hpp>
#include <boost/coroutine/all.hpp>
-typedef boost::coroutines::coroutine< int() > coro1_t;
-typedef boost::coroutines::coroutine< void( int) > coro2_t;
-typedef boost::range_iterator< coro1_t >::type iterator_t;
-
-void power( coro2_t & c, int number, int exponent)
+#ifdef BOOST_COROUTINES_V2
+void power( boost::coroutines::push_coroutine< int > & c, int number, int exponent)
{
int counter = 0;
int result = 1;
@@ -31,15 +28,16 @@
{
{
std::cout << "using range functions" << std::endl;
- coro1_t c( boost::bind( power, _1, 2, 8) );
- iterator_t e( boost::end( c) );
- for ( iterator_t i( boost::begin( c) ); i != e; ++i)
+ boost::coroutines::pull_coroutine< int > c( boost::bind( power, _1, 2, 8) );
+ boost::coroutines::pull_coroutine< int >::iterator e( boost::end( c) );
+ for ( boost::coroutines::pull_coroutine< int >::iterator i( boost::begin( c) );
+ i != e; ++i)
std::cout << * i << " ";
}
{
std::cout << "\nusing BOOST_FOREACH" << std::endl;
- coro1_t c( boost::bind( power, _1, 2, 8) );
+ boost::coroutines::pull_coroutine< int > c( boost::bind( power, _1, 2, 8) );
BOOST_FOREACH( int i, c)
{ std::cout << i << " "; }
}
@@ -48,21 +46,27 @@
return EXIT_SUCCESS;
}
-#if 0
+#else
+typedef boost::coroutines::coroutine< int() > coro1_t;
+typedef boost::coroutines::coroutine< void( int) > coro2_t;
+typedef boost::range_iterator< coro1_t >::type iterator_t;
+
+void power( coro2_t & c, int number, int exponent)
+{
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ c( result);
+ }
+}
+
int main()
{
{
std::cout << "using range functions" << std::endl;
- boost::coroutines::coroutine< int() > c(
- [&]( boost::coroutines::coroutine< void( int) > &c) {
- int counter = 0;
- int result = 1;
- while ( counter++ < 8)
- {
- result = result * 2;
- c( result);
- }
- });
+ coro1_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 << " ";
@@ -70,19 +74,9 @@
{
std::cout << "\nusing BOOST_FOREACH" << std::endl;
- boost::coroutines::coroutine< int() > c(
- [&]( boost::coroutines::coroutine< void( int) > &c) {
- int counter = 0;
- int result = 1;
- while ( counter++ < 8)
- {
- result = result * 2;
- c( result);
- }
- });
- for ( int i : c) {
- std::cout << i << " ";
- }
+ coro1_t c( boost::bind( power, _1, 2, 8) );
+ BOOST_FOREACH( int i, c)
+ { std::cout << i << " "; }
}
std::cout << "\nDone" << std::endl;
Modified: trunk/libs/coroutine/example/same_fringe.cpp
==============================================================================
--- trunk/libs/coroutine/example/same_fringe.cpp (original)
+++ trunk/libs/coroutine/example/same_fringe.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -15,15 +15,6 @@
#include "tree.h"
-bool match_trees( coro_t & c1, coro_t & c2)
-{
- typedef boost::range_iterator< coro_t >::type iterator_t;
- iterator_t i1( boost::begin( c1) );
- iterator_t e1( boost::end( c1) );
- iterator_t i2( boost::begin( c2) );
- return std::equal( i1, e1, i2);
-}
-
std::pair< node::ptr_t, node::ptr_t > create_eq_trees()
{
branch::ptr_t tree1 = branch::create(
@@ -58,6 +49,48 @@
return std::make_pair( tree1, tree2);
}
+#ifdef BOOST_COROUTINES_V2
+bool match_trees( boost::coroutines::pull_coroutine< leaf & > & c1,
+ boost::coroutines::pull_coroutine< leaf & > & c2)
+{
+ typedef boost::range_iterator< boost::coroutines::pull_coroutine< leaf & > >::type iterator_t;
+ iterator_t i1( boost::begin( c1) );
+ iterator_t e1( boost::end( c1) );
+ iterator_t i2( boost::begin( c2) );
+ return std::equal( i1, e1, i2);
+}
+
+int main()
+{
+ {
+ std::pair< node::ptr_t, node::ptr_t > pt = create_eq_trees();
+ boost::coroutines::pull_coroutine< leaf & > te1( boost::bind( enumerate_leafs, _1, pt.first) );
+ boost::coroutines::pull_coroutine< leaf & > te2( boost::bind( enumerate_leafs, _1, pt.second) );
+ bool result = match_trees( te1, te2);
+ std::cout << std::boolalpha << "eq. trees matched == " << result << std::endl;
+ }
+ {
+ std::pair< node::ptr_t, node::ptr_t > pt = create_diff_trees();
+ boost::coroutines::pull_coroutine< leaf & > te1( boost::bind( enumerate_leafs, _1, pt.first) );
+ boost::coroutines::pull_coroutine< leaf & > te2( boost::bind( enumerate_leafs, _1, pt.second) );
+ bool result = match_trees( te1, te2);
+ std::cout << std::boolalpha << "diff. trees matched == " << result << std::endl;
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
+bool match_trees( coro_t & c1, coro_t & c2)
+{
+ typedef boost::range_iterator< coro_t >::type iterator_t;
+ iterator_t i1( boost::begin( c1) );
+ iterator_t e1( boost::end( c1) );
+ iterator_t i2( boost::begin( c2) );
+ return std::equal( i1, e1, i2);
+}
+
int main()
{
{
@@ -79,3 +112,4 @@
return EXIT_SUCCESS;
}
+#endif
Modified: trunk/libs/coroutine/example/segmented_stack.cpp
==============================================================================
--- trunk/libs/coroutine/example/segmented_stack.cpp (original)
+++ trunk/libs/coroutine/example/segmented_stack.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -10,8 +10,6 @@
#include <boost/coroutine/all.hpp>
#include <boost/thread.hpp>
-typedef boost::coroutines::coroutine< void() > coro_t;
-
int count = 20;
void access( char *buf) __attribute__ ((noinline));
@@ -19,6 +17,7 @@
{
buf[0] = '\0';
}
+
void bar( int i)
{
char buf[4 * 1024];
@@ -31,6 +30,23 @@
}
}
+#ifdef BOOST_COROUTINES_V2
+void foo( boost::coroutines::pull_coroutine< void > & c)
+{
+ bar( count);
+ c();
+}
+
+void thread_fn()
+{
+ {
+ boost::coroutines::push_coroutine< void > c( foo);
+ c();
+ }
+}
+#else
+typedef boost::coroutines::coroutine< void() > coro_t;
+
void foo( coro_t & c)
{
bar( count);
@@ -42,9 +58,9 @@
{
coro_t c( foo);
c();
- int i = 7;
}
}
+#endif
int main( int argc, char * argv[])
{
Modified: trunk/libs/coroutine/example/tree.h
==============================================================================
--- trunk/libs/coroutine/example/tree.h (original)
+++ trunk/libs/coroutine/example/tree.h 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -91,6 +91,33 @@
bool operator!=( leaf const& l, leaf const& r)
{ return l.value != r.value; }
+#ifdef BOOST_COROUTINES_V2
+class tree_visitor : public visitor
+{
+private:
+ boost::coroutines::push_coroutine< leaf & > & c_;
+
+public:
+ tree_visitor( boost::coroutines::push_coroutine< leaf & > & c) :
+ c_( c)
+ {}
+
+ void visit( branch & b)
+ {
+ if ( b.left) b.left->accept( * this);
+ if ( b.right) b.right->accept( * this);
+ }
+
+ void visit( leaf & l)
+ { c_( l); }
+};
+
+void enumerate_leafs( boost::coroutines::push_coroutine< leaf & > & c, node::ptr_t root)
+{
+ tree_visitor v( c);
+ root->accept( v);
+}
+#else
typedef boost::coroutines::coroutine< leaf&() > coro_t;
class tree_visitor : public visitor
@@ -118,6 +145,7 @@
tree_visitor v( c);
root->accept( v);
}
+#endif
# if defined(BOOST_MSVC)
# pragma warning(pop)
Modified: trunk/libs/coroutine/example/unwind.cpp
==============================================================================
--- trunk/libs/coroutine/example/unwind.cpp (original)
+++ trunk/libs/coroutine/example/unwind.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -10,6 +10,40 @@
#include <boost/bind.hpp>
#include <boost/coroutine/all.hpp>
+#ifdef BOOST_COROUTINES_V2
+struct X : private boost::noncopyable
+{
+ X() { std::cout << "X()" << std::endl; }
+ ~X() { std::cout << "~X()" << std::endl; }
+};
+
+void fn( boost::coroutines::push_coroutine< void > & c)
+{
+ X x;
+ int i = 0;
+ while ( true)
+ {
+ std::cout << "fn() : " << ++i << std::endl;
+ c();
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ boost::coroutines::pull_coroutine< void > c( fn);
+ for ( int k = 0; k < 3; ++k)
+ {
+ c();
+ }
+ std::cout << "destroying coroutine and unwinding stack" << std::endl;
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
typedef boost::coroutines::coroutine< void() > coro_t;
struct X : private boost::noncopyable
@@ -44,3 +78,4 @@
return EXIT_SUCCESS;
}
+#endif
Modified: trunk/libs/coroutine/performance/performance.cpp
==============================================================================
--- trunk/libs/coroutine/performance/performance.cpp (original)
+++ trunk/libs/coroutine/performance/performance.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -27,25 +27,81 @@
namespace coro = boost::coroutines;
-typedef coro::coroutine< void() > coro_t;
-
-#define COUNTER BOOST_PP_LIMIT_MAG
+# define COUNTER BOOST_PP_LIMIT_MAG
-#define CALL_COROUTINE(z,n,unused) \
+# define CALL_COROUTINE(z,n,unused) \
c();
+#ifdef BOOST_COROUTINES_V2
+void fn( boost::coroutines::push_coroutine< void > & c)
+{ while ( true) c(); }
+
+# ifdef BOOST_CONTEXT_CYCLE
+cycle_t test_cycles( cycle_t ov, coro::flag_fpu_t preserve_fpu)
+{
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ boost::coroutines::pull_coroutine< void > c( fn, coro::attributes( preserve_fpu) );
+# else
+ coro::simple_stack_allocator< 8 * 1024 * 1024, 64 * 1024, 8 * 1024 > alloc;
+ boost::coroutines::pull_coroutine< void > c( fn, coro::attributes( preserve_fpu), alloc);
+# endif
+
+ // cache warum-up
+BOOST_PP_REPEAT_FROM_TO( 0, COUNTER, CALL_COROUTINE, ~)
+
+ cycle_t start( cycles() );
+BOOST_PP_REPEAT_FROM_TO( 0, COUNTER, CALL_COROUTINE, ~)
+ cycle_t total( cycles() - start);
+
+ // we have two jumps and two measuremt-overheads
+ total -= ov; // overhead of measurement
+ total /= COUNTER; // per call
+ total /= 2; // 2x jump_to c1->c2 && c2->c1
+
+ return total;
+}
+# endif
+
+# if _POSIX_C_SOURCE >= 199309L
+zeit_t test_zeit( zeit_t ov, coro::flag_fpu_t preserve_fpu)
+{
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ boost::coroutines::pull_coroutine< void > c( fn, coro::attributes( preserve_fpu) );
+# else
+ coro::simple_stack_allocator< 8 * 1024 * 1024, 64 * 1024, 8 * 1024 > alloc;
+ boost::coroutines::pull_coroutine< void > c( fn, coro::attributes( preserve_fpu), alloc);
+# endif
+
+ // cache warum-up
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_COROUTINE, ~)
+
+ zeit_t start( zeit() );
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_COROUTINE, ~)
+ zeit_t total( zeit() - start);
+
+ // we have two jumps and two measuremt-overheads
+ total -= ov; // overhead of measurement
+ total /= BOOST_PP_LIMIT_MAG; // per call
+ total /= 2; // 2x jump_to c1->c2 && c2->c1
+
+ return total;
+}
+# endif
+#else
+typedef coro::coroutine< void() > coro_t;
+
void fn( coro_t::caller_type & c)
{ while ( true) c(); }
-#ifdef BOOST_CONTEXT_CYCLE
+# ifdef BOOST_CONTEXT_CYCLE
cycle_t test_cycles( cycle_t ov, coro::flag_fpu_t preserve_fpu)
{
-#if defined(BOOST_USE_SEGMENTED_STACKS)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
coro_t c( fn, coro::attributes( preserve_fpu) );
-#else
+# else
coro::simple_stack_allocator< 8 * 1024 * 1024, 64 * 1024, 8 * 1024 > alloc;
coro_t c( fn, coro::attributes( preserve_fpu), alloc);
-#endif
+# endif
// cache warum-up
BOOST_PP_REPEAT_FROM_TO( 0, COUNTER, CALL_COROUTINE, ~)
@@ -61,17 +117,17 @@
return total;
}
-#endif
+# endif
-#if _POSIX_C_SOURCE >= 199309L
+# if _POSIX_C_SOURCE >= 199309L
zeit_t test_zeit( zeit_t ov, coro::flag_fpu_t preserve_fpu)
{
-#if defined(BOOST_USE_SEGMENTED_STACKS)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
coro_t c( fn, coro::attributes( preserve_fpu) );
-#else
+# else
coro::simple_stack_allocator< 8 * 1024 * 1024, 64 * 1024, 8 * 1024 > alloc;
coro_t c( fn, coro::attributes( preserve_fpu), alloc);
-#endif
+# endif
// cache warum-up
BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_COROUTINE, ~)
@@ -87,6 +143,7 @@
return total;
}
+# endif
#endif
int main( int argc, char * argv[])
Modified: trunk/libs/coroutine/test/test_coroutine.cpp
==============================================================================
--- trunk/libs/coroutine/test/test_coroutine.cpp (original)
+++ trunk/libs/coroutine/test/test_coroutine.cpp 2013-05-22 16:15:43 EDT (Wed, 22 May 2013)
@@ -30,7 +30,487 @@
int value1 = 0;
std::string value2 = "";
bool value3 = false;
+double value4 = .0;
+int * value5 = 0;
+int& value6 = value1;
+int& value7 = value1;
+int value8 = 0;
+int value9 = 0;
+#ifdef BOOST_COROUTINES_V2
+struct X : private boost::noncopyable
+{
+ X() { value1 = 7; }
+ ~X() { value1 = 0; }
+};
+
+class copyable
+{
+public:
+ bool state;
+
+ copyable() :
+ state( false)
+ {}
+
+ copyable( int) :
+ state( true)
+ {}
+
+ void operator()( coro::push_coroutine< int > &)
+ { value3 = state; }
+};
+
+class moveable
+{
+private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( moveable);
+
+public:
+ bool state;
+
+ moveable() :
+ state( false)
+ {}
+
+ moveable( int) :
+ state( true)
+ {}
+
+ moveable( BOOST_RV_REF( moveable) other) :
+ state( false)
+ { std::swap( state, other.state); }
+
+ moveable & operator=( BOOST_RV_REF( moveable) other)
+ {
+ if ( this == & other) return * this;
+ moveable tmp( boost::move( other) );
+ std::swap( state, tmp.state);
+ return * this;
+ }
+
+ void operator()( coro::push_coroutine< int > &)
+ { value3 = state; }
+};
+
+struct my_exception {};
+
+void f1( coro::push_coroutine< void > & c)
+{ c(); }
+
+void f2( coro::push_coroutine< void > &)
+{ ++value1; }
+
+void f3( coro::push_coroutine< void > & c)
+{
+ ++value1;
+ c();
+ ++value1;
+}
+
+void f4( coro::push_coroutine< int > & c)
+{
+ c( 3);
+ c( 7);
+}
+
+void f5( coro::push_coroutine< std::string > & c)
+{
+ std::string res("abc");
+ c( res);
+ res = "xyz";
+ c( res);
+}
+
+void f6( coro::pull_coroutine< int > & c)
+{ value1 = c.get(); }
+
+void f7( coro::pull_coroutine< std::string > & c)
+{ value2 = c.get(); }
+
+void f8( coro::pull_coroutine< boost::tuple< double, double > > & c)
+{
+ double x = 0, y = 0;
+ boost::tie( x, y) = c.get();
+ value4 = x + y;
+ c();
+ boost::tie( x, y) = c.get();
+ value4 = x + y;
+}
+
+void f9( coro::pull_coroutine< int * > & c)
+{ value5 = c.get(); }
+
+void f91( coro::pull_coroutine< int const* > & c)
+{ value5 = const_cast< int * >( c.get() ); }
+
+void f10( coro::pull_coroutine< int & > & c)
+{
+ int const& i = c.get();
+ value5 = const_cast< int * >( & i);
+}
+
+void f101( coro::pull_coroutine< int const& > & c)
+{
+ int const& i = c.get();
+ value5 = const_cast< int * >( & i);
+}
+
+void f11( coro::pull_coroutine< boost::tuple< int, int > > & c)
+{
+ boost::tie( value8, value9) = c.get();
+}
+
+void f12( coro::pull_coroutine< void > & c)
+{
+ X x_;
+ c();
+ c();
+}
+
+template< typename E >
+void f14( coro::pull_coroutine< void > &, E const& e)
+{ throw e; }
+
+void f16( coro::push_coroutine< int > & c)
+{
+ c( 1);
+ c( 2);
+ c( 3);
+ c( 4);
+ c( 5);
+}
+
+void f17( coro::pull_coroutine< int > & c, std::vector< int > & vec)
+{
+ int x = c.get();
+ while ( 5 > x)
+ {
+ vec.push_back( x);
+ x = c().get();
+ }
+}
+
+void f19( coro::push_coroutine< const int* > & c, std::vector< const int * > & vec)
+{
+ BOOST_FOREACH( const int * ptr, vec)
+ { c( ptr); }
+}
+
+void test_move()
+{
+ {
+ coro::pull_coroutine< void > coro1;
+ coro::pull_coroutine< void > coro2( f1);
+ BOOST_CHECK( ! coro1);
+ BOOST_CHECK( coro1.empty() );
+ BOOST_CHECK( coro2);
+ BOOST_CHECK( ! coro2.empty() );
+ coro1 = boost::move( coro2);
+ BOOST_CHECK( coro1);
+ BOOST_CHECK( ! coro1.empty() );
+ BOOST_CHECK( ! coro2);
+ BOOST_CHECK( coro2.empty() );
+ }
+
+ {
+ value3 = false;
+ copyable cp( 3);
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK( ! value3);
+ coro::pull_coroutine< int > coro( cp);
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK( value3);
+ }
+
+ {
+ value3 = false;
+ moveable mv( 7);
+ BOOST_CHECK( mv.state);
+ BOOST_CHECK( ! value3);
+ coro::pull_coroutine< int > coro( boost::move( mv) );
+ BOOST_CHECK( ! mv.state);
+ BOOST_CHECK( value3);
+ }
+}
+
+void test_complete()
+{
+ value1 = 0;
+
+ coro::pull_coroutine< void > coro( f2);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( int)1, value1);
+}
+
+void test_jump()
+{
+ value1 = 0;
+
+ coro::pull_coroutine< void > coro( f3);
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int)1, value1);
+ coro();
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( int)2, value1);
+}
+
+void test_result_int()
+{
+ coro::pull_coroutine< int > coro( f4);
+ BOOST_CHECK( coro);
+ int result = coro.get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( 3, result);
+ result = coro().get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( 7, result);
+ coro();
+ BOOST_CHECK( ! coro);
+}
+
+void test_result_string()
+{
+ coro::pull_coroutine< std::string > coro( f5);
+ BOOST_CHECK( coro);
+ std::string result = coro.get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( std::string("abc"), result);
+ result = coro().get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( std::string("xyz"), result);
+ coro();
+ BOOST_CHECK( ! coro);
+}
+
+void test_arg_int()
+{
+ value1 = 0;
+
+ coro::push_coroutine< int > coro( f6);
+ BOOST_CHECK( coro);
+ coro( 3);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( 3, value1);
+}
+
+void test_arg_string()
+{
+ value2 = "";
+
+ coro::push_coroutine< std::string > coro( f7);
+ BOOST_CHECK( coro);
+ coro( std::string("abc") );
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( std::string("abc"), value2);
+}
+
+void test_fp()
+{
+ value4 = 0;
+
+ coro::push_coroutine< boost::tuple< double, double > > coro( f8);
+ BOOST_CHECK( coro);
+ coro( boost::make_tuple( 7.35, 3.14) );
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( double) 10.49, value4);
+
+ value4 = 0;
+ coro( boost::make_tuple( 1.15, 3.14) );
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( double) 4.29, value4);
+}
+
+void test_ptr()
+{
+ value5 = 0;
+
+ int a = 3;
+ coro::push_coroutine< int * > coro( f9);
+ BOOST_CHECK( coro);
+ coro( & a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_const_ptr()
+{
+ value5 = 0;
+
+ int a = 3;
+ coro::push_coroutine< int const* > coro( f91);
+ BOOST_CHECK( coro);
+ coro( & a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_ref()
+{
+ value5 = 0;
+
+ int a = 3;
+ coro::push_coroutine< int & > coro( f10);
+ BOOST_CHECK( coro);
+ coro( a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_const_ref()
+{
+ value5 = 0;
+
+ int a = 3;
+ coro::push_coroutine< int const& > coro( f101);
+ BOOST_CHECK( coro);
+ coro( a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_tuple()
+{
+ value8 = 0;
+ value9 = 0;
+
+ int a = 3, b = 7;
+ boost::tuple< int, int > tpl( a, b);
+ BOOST_CHECK_EQUAL( a, tpl.get< 0 >() );
+ BOOST_CHECK_EQUAL( b, tpl.get< 1 >() );
+ coro::push_coroutine< boost::tuple< int, int > > coro( f11);
+ BOOST_CHECK( coro);
+ coro( tpl);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( a, value8);
+ BOOST_CHECK_EQUAL( b, value9);
+}
+
+void test_unwind()
+{
+ value1 = 0;
+ {
+ coro::push_coroutine< void > coro( f12);
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+ coro();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ coro();
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ }
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+}
+
+void test_no_unwind()
+{
+ value1 = 0;
+ {
+ coro::push_coroutine< void > coro(
+ f12,
+ coro::attributes(
+ coro::stack_allocator::default_stacksize(),
+ coro::no_stack_unwind) );
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+ coro();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ coro();
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ }
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+}
+
+void test_exceptions()
+{
+ bool thrown = false;
+ std::runtime_error ex("abc");
+ try
+ {
+ coro::push_coroutine< void > coro( boost::bind( f14< std::runtime_error >, _1, ex) );
+ BOOST_CHECK( coro);
+ coro();
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK( false);
+ }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ catch ( std::exception const&)
+ {}
+ catch (...)
+ {}
+ BOOST_CHECK( thrown);
+}
+
+void test_output_iterator()
+{
+ {
+ std::vector< int > vec;
+ coro::pull_coroutine< int > coro( f16);
+ BOOST_FOREACH( int i, coro)
+ { vec.push_back( i); }
+ BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
+ BOOST_CHECK_EQUAL( ( int)1, vec[0] );
+ BOOST_CHECK_EQUAL( ( int)2, vec[1] );
+ BOOST_CHECK_EQUAL( ( int)3, vec[2] );
+ BOOST_CHECK_EQUAL( ( int)4, vec[3] );
+ BOOST_CHECK_EQUAL( ( int)5, vec[4] );
+ }
+ {
+ std::vector< int > vec;
+ coro::pull_coroutine< int > coro( f16);
+ coro::pull_coroutine< int >::iterator e = boost::end( coro);
+ for (
+ coro::pull_coroutine< int >::iterator i = boost::begin( coro);
+ i != e; ++i)
+ { vec.push_back( * i); }
+ BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
+ BOOST_CHECK_EQUAL( ( int)1, vec[0] );
+ BOOST_CHECK_EQUAL( ( int)2, vec[1] );
+ BOOST_CHECK_EQUAL( ( int)3, vec[2] );
+ BOOST_CHECK_EQUAL( ( int)4, vec[3] );
+ BOOST_CHECK_EQUAL( ( int)5, vec[4] );
+ }
+ {
+ int i1 = 1, i2 = 2, i3 = 3;
+ std::vector< const int* > vec_in;
+ vec_in.push_back( & i1);
+ vec_in.push_back( & i2);
+ vec_in.push_back( & i3);
+ std::vector< const int* > vec_out;
+ coro::pull_coroutine< const int* > coro( boost::bind( f19, _1, boost::ref( vec_in) ) );
+ coro::pull_coroutine< const int* >::const_iterator e = boost::const_end( coro);
+ for (
+ coro::pull_coroutine< const int* >::const_iterator i = boost::const_begin( coro);
+ i != e; ++i)
+ { vec_out.push_back( * i); }
+ BOOST_CHECK_EQUAL( ( std::size_t)3, vec_out.size() );
+ BOOST_CHECK_EQUAL( & i1, vec_out[0] );
+ BOOST_CHECK_EQUAL( & i2, vec_out[1] );
+ BOOST_CHECK_EQUAL( & i3, vec_out[2] );
+ }
+}
+
+void test_input_iterator()
+{
+ int counter = 0;
+ std::vector< int > vec;
+ coro::push_coroutine< int > coro(
+ boost::bind( f17, _1, boost::ref( vec) ) );
+ coro::push_coroutine< int >::iterator e( boost::end( coro) );
+ for ( coro::push_coroutine< int >::iterator i( boost::begin( coro) );
+ i != e; ++i)
+ {
+ i = ++counter;
+ }
+ BOOST_CHECK_EQUAL( ( std::size_t)4, vec.size() );
+ BOOST_CHECK_EQUAL( ( int)1, vec[0] );
+ BOOST_CHECK_EQUAL( ( int)2, vec[1] );
+ BOOST_CHECK_EQUAL( ( int)3, vec[2] );
+ BOOST_CHECK_EQUAL( ( int)4, vec[3] );
+}
+#else
typedef coro::coroutine< void() > coro_void_void;
typedef coro::coroutine< int() > coro_int_void;
typedef coro::coroutine< std::string() > coro_string_void;
@@ -40,7 +520,9 @@
typedef coro::coroutine< int(int,int) > coro_int;
typedef coro::coroutine< int(int) > coro_int_int;
typedef coro::coroutine< int*(int*) > coro_ptr;
-typedef coro::coroutine< int const&(int const&) > coro_ref;
+typedef coro::coroutine< int const*(int const*) > coro_const_ptr;
+typedef coro::coroutine< int&(int&) > coro_ref;
+typedef coro::coroutine< int const&(int const&) > coro_const_ref;
typedef coro::coroutine< boost::tuple<int&,int&>(int&,int&) > coro_tuple;
typedef coro::coroutine< const int *() > coro_const_int_ptr_void;
@@ -146,9 +628,15 @@
void f9( coro_ptr::caller_type & self)
{ self( self.get() ); }
+void f91( coro_const_ptr::caller_type & self)
+{ self( self.get() ); }
+
void f10( coro_ref::caller_type & self)
{ self( self.get() ); }
+void f101( coro_const_ref::caller_type & self)
+{ self( self.get() ); }
+
void f11( coro_tuple::caller_type & self)
{
boost::tuple<int&,int&> tpl( self.get().get< 0 >(), self.get().get< 1 >() );
@@ -338,6 +826,18 @@
BOOST_CHECK( ! coro);
}
+void test_const_ptr()
+{
+ int a = 3;
+ coro_const_ptr coro( f91, & a);
+ BOOST_CHECK( coro);
+ int const* res = coro.get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( & a, res);
+ coro( & a);
+ BOOST_CHECK( ! coro);
+}
+
void test_ref()
{
int a = 3;
@@ -350,6 +850,18 @@
BOOST_CHECK( ! coro);
}
+void test_const_ref()
+{
+ int a = 3;
+ coro_const_ref coro( f101, a);
+ BOOST_CHECK( coro);
+ int const& res = coro.get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( & a, & res);
+ coro( a);
+ BOOST_CHECK( ! coro);
+}
+
void test_tuple()
{
int a = 3, b = 7;
@@ -507,6 +1019,7 @@
coro( -1);
BOOST_CHECK( ! coro);
}
+#endif
boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
{
@@ -516,15 +1029,19 @@
test->add( BOOST_TEST_CASE( & test_move) );
test->add( BOOST_TEST_CASE( & test_complete) );
test->add( BOOST_TEST_CASE( & test_jump) );
- test->add( BOOST_TEST_CASE( & test_pre) );
- test->add( BOOST_TEST_CASE( & test_post) );
test->add( BOOST_TEST_CASE( & test_result_int) );
test->add( BOOST_TEST_CASE( & test_result_string) );
test->add( BOOST_TEST_CASE( & test_arg_int) );
test->add( BOOST_TEST_CASE( & test_arg_string) );
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
+ test->add( BOOST_TEST_CASE( & test_pre) );
+ test->add( BOOST_TEST_CASE( & test_post) );
+#endif
test->add( BOOST_TEST_CASE( & test_ref) );
+ test->add( BOOST_TEST_CASE( & test_const_ref) );
test->add( BOOST_TEST_CASE( & test_tuple) );
test->add( BOOST_TEST_CASE( & test_unwind) );
test->add( BOOST_TEST_CASE( & test_no_unwind) );
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