diff --git a/example/c++11/fibonacci.cpp b/example/c++11/fibonacci.cpp new file mode 100644 index 0000000..8c7a1e9 --- /dev/null +++ b/example/c++11/fibonacci.cpp @@ -0,0 +1,32 @@ + +// 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) + +#include +#include + +#include + +int main() +{ + boost::coroutines::coroutine< int() > c( + [&]( boost::coroutines::coroutine< void( 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; +} diff --git a/example/c++11/same_fringe.cpp b/example/c++11/same_fringe.cpp new file mode 100644 index 0000000..a0c9908 --- /dev/null +++ b/example/c++11/same_fringe.cpp @@ -0,0 +1,75 @@ + +// 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) + +#include +#include +#include + +#include "tree.h" + +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); } +}; + +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") ); +} + +int main() +{ + node::ptr_t t1 = create_tree1(); + boost::coroutines::coroutine< leaf&() > c1( + [&]( boost::coroutines::coroutine< void( leaf &) > & c) { + coro_visitor v( c); + t1->accept( v); + }); + + node::ptr_t t2 = create_tree2(); + boost::coroutines::coroutine< leaf&() > c2( + [&]( boost::coroutines::coroutine< void( leaf &) > & c) { + coro_visitor v( c); + t2->accept( v); + }); + + bool result = std::equal( + boost::begin( c1), + boost::end( c1), + boost::begin( c2) ); + + std::cout << std::boolalpha << "same fringe == " << result << "\nDone" << std::endl; + + return EXIT_SUCCESS; +} diff --git a/example/c++11/tree.h b/example/c++11/tree.h new file mode 100644 index 0000000..292550b --- /dev/null +++ b/example/c++11/tree.h @@ -0,0 +1,98 @@ + +// 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 TREE_H +#define TREE_H + +#include +#include + +#include +#include +#include +#include + +# if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4355) +# endif + +struct branch; +struct leaf; + +struct visitor +{ + virtual ~visitor() {}; + + virtual void visit( branch & b) = 0; + virtual void visit( leaf & l) = 0; +}; + +struct node +{ + typedef boost::intrusive_ptr< node > ptr_t; + + std::size_t use_count; + + node() : + use_count( 0) + {} + + virtual ~node() {} + + virtual void accept( visitor & v) = 0; + + friend inline void intrusive_ptr_add_ref( node * p) + { ++p->use_count; } + + friend inline void intrusive_ptr_release( node * p) + { if ( 0 == --p->use_count) delete p; } +}; + +struct branch : public node +{ + node::ptr_t left; + node::ptr_t right; + + static ptr_t create( node::ptr_t left_, node::ptr_t right_) + { return ptr_t( new branch( left_, right_) ); } + + branch( node::ptr_t left_, node::ptr_t right_) : + left( left_), right( right_) + {} + + void accept( visitor & v) + { v.visit( * this); } +}; + +struct leaf : public node +{ + std::string value; + + static ptr_t create( std::string const& value_) + { return ptr_t( new leaf( value_) ); } + + leaf( std::string const& value_) : + value( value_) + {} + + void accept( visitor & v) + { v.visit( * this); } +}; + +inline +bool operator==( leaf const& l, leaf const& r) +{ return l.value == r.value; } + +inline +bool operator!=( leaf const& l, leaf const& r) +{ return l.value != r.value; } + +# if defined(BOOST_MSVC) +# pragma warning(pop) +# endif + +#endif // TREE_H diff --git a/include/boost/coroutine/checkpoint.hpp b/include/boost/coroutine/checkpoint.hpp new file mode 100644 index 0000000..e713414 --- /dev/null +++ b/include/boost/coroutine/checkpoint.hpp @@ -0,0 +1,34 @@ + +// 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_CHECKPOINT_H +#define BOOST_COROUTINES_CHECKPOINT_H + +#include +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace coroutines { + +class checkpoint +{ +public: +private: + context::fcontext_t ctx_; + void * sp_; +}; + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_COROUTINES_CHECKPOINT_H diff --git a/include/boost/coroutine/coroutine.hpp b/include/boost/coroutine/coroutine.hpp index 07bcccc..bfb89d9 100644 --- a/include/boost/coroutine/coroutine.hpp +++ b/include/boost/coroutine/coroutine.hpp @@ -7,1423 +7,10 @@ #ifndef BOOST_COROUTINES_COROUTINE_H #define BOOST_COROUTINES_COROUTINE_H -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace coroutines { -namespace detail { - -template< - typename Signature, - template< class, int > class C, - typename Result = typename function_traits< Signature >::result_type, - int arity = function_traits< Signature >::arity -> -struct caller; - -template< - typename Signature, - template< class, int > class C -> -struct caller< Signature, C, void, 0 > -{ typedef C< void(), 0 > type; }; - -template< - typename Signature, - template< class, int > class C, - typename Result -> -struct caller< Signature, C, Result, 0 > -{ typedef C< void( Result), 1 > type; }; - -template< - typename Signature, - template< class, int > class C, - int arity -> -struct caller< Signature, C, void, arity > -{ typedef C< typename detail::arg< Signature >::type(), 0 > type; }; - -template< - typename Signature, - template< class, int > class C, - typename Result, int arity -> -struct caller -{ typedef C< typename detail::arg< Signature >::type( Result), 1 > type; }; - -} - -template< typename Signature, int arity = function_traits< Signature >::arity > -class coroutine; - -template< typename Signature > -class coroutine< Signature, 0 > : public detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >, - public detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > -{ -private: - typedef detail::coroutine_base< Signature > base_t; - typedef typename base_t::ptr_t ptr_t; - - template< typename X, typename Y, int > - friend struct detail::coroutine_get; - template< typename X, typename Y, typename Z, int > - friend struct detail::coroutine_op; - template< typename X, typename Y, typename Z, typename A, typename B, typename C, int > - friend class detail::coroutine_object; - - struct dummy - { void nonnull() {} }; - - typedef void ( dummy::*safe_bool)(); - - ptr_t impl_; - - BOOST_MOVABLE_BUT_NOT_COPYABLE( coroutine) - - template< typename Allocator > - coroutine( detail::coroutine_context const& callee, - bool unwind, bool preserve_fpu, - Allocator const& alloc) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - - >(), - impl_() - { - typedef detail::coroutine_caller< - Signature, 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: - typedef typename detail::caller< - Signature, - boost::coroutines::coroutine - >::type caller_type; - - coroutine() BOOST_NOEXCEPT : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - {} - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -#ifdef BOOST_MSVC - typedef void ( * coroutine_fn) ( caller_type &); - - explicit coroutine( coroutine_fn fn, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >() ) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { - typedef detail::coroutine_object< - Signature, - coroutine_fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); - } - - template< typename StackAllocator > - explicit coroutine( coroutine_fn fn, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >() ) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { - typedef detail::coroutine_object< - Signature, - coroutine_fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); - } - - template< typename StackAllocator, typename Allocator > - explicit coroutine( coroutine_fn fn, attributes const& attr, - StackAllocator const& stack_alloc, - Allocator const& alloc) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { - typedef detail::coroutine_object< - Signature, - coroutine_fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); - } -#endif - template< typename Fn > - explicit coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 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, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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) ); - } +#ifdef BOOST_COROUTINES_V2 +#include #else - template< typename Fn > - explicit coroutine( Fn fn, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_convertible< Fn &, BOOST_RV_REF( Fn) >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( Fn fn, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_convertible< Fn &, BOOST_RV_REF( Fn) >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 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) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 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, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 - - coroutine( BOOST_RV_REF( coroutine) other) BOOST_NOEXCEPT : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { swap( other); } - - coroutine & operator=( BOOST_RV_REF( coroutine) other) BOOST_NOEXCEPT - { - 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( coroutine & other) BOOST_NOEXCEPT - { impl_.swap( other.impl_); } -}; - -template< typename Signature, int arity > -class coroutine : public detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >, - public detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > -{ -private: - typedef detail::coroutine_base< Signature > base_t; - typedef typename base_t::ptr_t ptr_t; - - template< typename X, typename Y, int > - friend struct detail::coroutine_get; - template< typename X, typename Y, typename Z, int > - friend struct detail::coroutine_op; - template< typename X, typename Y, typename Z, typename A, typename B, typename C, int > - friend class detail::coroutine_object; - - struct dummy - { void nonnull() {} }; - - typedef void ( dummy::*safe_bool)(); - - ptr_t impl_; - - BOOST_MOVABLE_BUT_NOT_COPYABLE( coroutine) - - template< typename Allocator > - coroutine( detail::coroutine_context const& callee, - bool unwind, bool preserve_fpu, - Allocator const& alloc) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { - typedef detail::coroutine_caller< - Signature, 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: - typedef typename detail::caller< - Signature, - boost::coroutines::coroutine - >::type caller_type; - typedef typename detail::arg< Signature >::type arguments; - - coroutine() BOOST_NOEXCEPT : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - {} - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -#ifdef BOOST_MSVC - typedef void ( * coroutine_fn) ( caller_type &); - - explicit coroutine( coroutine_fn fn, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >() ) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { - typedef detail::coroutine_object< - Signature, - coroutine_fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); - } - - explicit coroutine( coroutine_fn fn, arguments arg, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >() ) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { - typedef detail::coroutine_object< - Signature, - coroutine_fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), arg, attr, stack_alloc, a) ); - } - - template< typename StackAllocator > - explicit coroutine( coroutine_fn fn, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >() ) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { - typedef detail::coroutine_object< - Signature, - coroutine_fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); - } - - template< typename StackAllocator, typename Allocator > - explicit coroutine( coroutine_fn fn, attributes const& attr, - StackAllocator const& stack_alloc, - Allocator const& alloc) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { - typedef detail::coroutine_object< - Signature, - coroutine_fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); - } -#endif - template< typename Fn > - explicit coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 > - explicit coroutine( BOOST_RV_REF( Fn) fn, arguments arg, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), arg, attr, stack_alloc, a) ); - } - - template< typename Fn, typename StackAllocator > - explicit coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( BOOST_RV_REF( Fn) fn, arguments arg, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), arg, attr, stack_alloc, a) ); - } - - template< typename Fn, typename StackAllocator, typename Allocator > - explicit 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, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( BOOST_RV_REF( Fn) fn, arguments arg, attributes const& attr, - StackAllocator const& stack_alloc, - Allocator const& alloc, - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), arg, attr, stack_alloc, a) ); - } -#else - template< typename Fn > - explicit coroutine( Fn fn, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_convertible< Fn &, BOOST_RV_REF( Fn) >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( Fn fn, arguments arg, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_convertible< Fn &, BOOST_RV_REF( Fn) >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > object_t; - typename object_t::allocator_t a( alloc); - impl_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( fn, arg, attr, stack_alloc, a) ); - } - - template< typename Fn, typename StackAllocator > - explicit coroutine( Fn fn, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_convertible< Fn &, BOOST_RV_REF( Fn) >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 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) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), - stack_allocator const& stack_alloc = - stack_allocator(), - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, stack_allocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, - StackAllocator const& stack_alloc, - std::allocator< coroutine > const& alloc = - std::allocator< coroutine >(), - typename disable_if< - is_same< typename decay< Fn >::type, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, std::allocator< coroutine >, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 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, coroutine >, - dummy * - >::type = 0) : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { -// BOOST_STATIC_ASSERT(( -// is_same< void, typename result_of< Fn() >::type >::value)); - typedef detail::coroutine_object< - Signature, - Fn, StackAllocator, Allocator, - caller_type, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - > 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 - - coroutine( BOOST_RV_REF( coroutine) other) BOOST_NOEXCEPT : - detail::coroutine_op< - Signature, - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - detail::coroutine_get< - coroutine< Signature >, - typename function_traits< Signature >::result_type, - function_traits< Signature >::arity - >(), - impl_() - { swap( other); } - - coroutine & operator=( BOOST_RV_REF( coroutine) other) BOOST_NOEXCEPT - { - 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( coroutine & other) BOOST_NOEXCEPT - { impl_.swap( other.impl_); } -}; - -template< typename Signature > -void swap( coroutine< Signature > & l, coroutine< Signature > & r) BOOST_NOEXCEPT -{ l.swap( r); } - -template< typename Signature > -inline -typename coroutine< Signature >::iterator -range_begin( coroutine< Signature > & c) -{ return typename coroutine< Signature >::iterator( & c); } - -template< typename Signature > -inline -typename coroutine< Signature >::const_iterator -range_begin( coroutine< Signature > const& c) -{ return typename coroutine< Signature >::const_iterator( & c); } - -template< typename Signature > -inline -typename coroutine< Signature >::iterator -range_end( coroutine< Signature > &) -{ return typename coroutine< Signature >::iterator(); } - -template< typename Signature > -inline -typename coroutine< Signature >::const_iterator -range_end( coroutine< Signature > const&) -{ return typename coroutine< Signature >::const_iterator(); } - -template< typename Signature > -inline -typename coroutine< Signature >::iterator -begin( coroutine< Signature > & c) -{ return boost::begin( c); } - -template< typename Signature > -inline -typename coroutine< Signature >::iterator -end( coroutine< Signature > & c) -{ return boost::end( c); } - -template< typename Signature > -inline -typename coroutine< Signature >::const_iterator -begin( coroutine< Signature > const& c) -{ return boost::const_begin( c); } - -template< typename Signature > -inline -typename coroutine< Signature >::const_iterator -end( coroutine< Signature > const& c) -{ return boost::const_end( c); } - -} - -template< typename Signature > -struct range_mutable_iterator< coroutines::coroutine< Signature > > -{ typedef typename coroutines::coroutine< Signature >::iterator type; }; - -template< typename Signature > -struct range_const_iterator< coroutines::coroutine< Signature > > -{ typedef typename coroutines::coroutine< Signature >::const_iterator type; }; - -} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX +#include #endif #endif // BOOST_COROUTINES_COROUTINE_H diff --git a/include/boost/coroutine/detail/config.hpp b/include/boost/coroutine/detail/config.hpp index 1caa3ac..0452730 100644 --- a/include/boost/coroutine/detail/config.hpp +++ b/include/boost/coroutine/detail/config.hpp @@ -46,4 +46,8 @@ # define BOOST_COROUTINES_SEGMENTS 10 #endif +//#ifndef BOOST_COROUTINES_V1 +//# define BOOST_COROUTINES_V2 +//#endif + #endif // BOOST_COROUTINES_DETAIL_CONFIG_H diff --git a/include/boost/coroutine/detail/segmented_stack_allocator.hpp b/include/boost/coroutine/detail/segmented_stack_allocator.hpp index 30b3e13..5afefa0 100644 --- a/include/boost/coroutine/detail/segmented_stack_allocator.hpp +++ b/include/boost/coroutine/detail/segmented_stack_allocator.hpp @@ -36,7 +36,7 @@ public: static std::size_t maximum_stacksize(); - void allocate( stack_context &, std::size_t size); + void allocate( stack_context &, std::size_t = minimum_stacksize() ); void deallocate( stack_context &); }; diff --git a/include/boost/coroutine/v1/coroutine.hpp b/include/boost/coroutine/v1/coroutine.hpp new file mode 100644 index 0000000..294d81c --- /dev/null +++ b/include/boost/coroutine/v1/coroutine.hpp @@ -0,0 +1,1430 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_COROUTINES_V1_COROUTINE_H +#define BOOST_COROUTINES_V1_COROUTINE_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace coroutines { +namespace detail { + +template< + typename Signature, + template< class, int > class C, + typename Result = typename function_traits< Signature >::result_type, + int arity = function_traits< Signature >::arity +> +struct caller; + +template< + typename Signature, + template< class, int > class C +> +struct caller< Signature, C, void, 0 > +{ typedef C< void(), 0 > type; }; + +template< + typename Signature, + template< class, int > class C, + typename Result +> +struct caller< Signature, C, Result, 0 > +{ typedef C< void( Result), 1 > type; }; + +template< + typename Signature, + template< class, int > class C, + int arity +> +struct caller< Signature, C, void, arity > +{ typedef C< typename detail::arg< Signature >::type(), 0 > type; }; + +template< + typename Signature, + template< class, int > class C, + typename Result, int arity +> +struct caller +{ typedef C< typename detail::arg< Signature >::type( Result), 1 > type; }; + +} + +template< typename Signature, int arity = function_traits< Signature >::arity > +class coroutine; + +template< typename Signature > +class coroutine< Signature, 0 > : public detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >, + public detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > +{ +private: + typedef detail::coroutine_base< Signature > base_t; + typedef typename base_t::ptr_t ptr_t; + + template< typename X, typename Y, int > + friend struct detail::coroutine_get; + template< typename X, typename Y, typename Z, int > + friend struct detail::coroutine_op; + template< typename X, typename Y, typename Z, typename A, typename B, typename C, int > + friend class detail::coroutine_object; + + struct dummy + { void nonnull() {} }; + + typedef void ( dummy::*safe_bool)(); + + ptr_t impl_; + + BOOST_MOVABLE_BUT_NOT_COPYABLE( coroutine) + + template< typename Allocator > + coroutine( detail::coroutine_context const& callee, + bool unwind, bool preserve_fpu, + Allocator const& alloc) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + + >(), + impl_() + { + typedef detail::coroutine_caller< + Signature, 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: + typedef typename detail::caller< + Signature, + boost::coroutines::coroutine + >::type caller_type; + + coroutine() BOOST_NOEXCEPT : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + {} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifdef BOOST_MSVC + typedef void ( * coroutine_fn) ( caller_type &); + + explicit coroutine( coroutine_fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >() ) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { + typedef detail::coroutine_object< + Signature, + coroutine_fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } + + template< typename StackAllocator > + explicit coroutine( coroutine_fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >() ) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { + typedef detail::coroutine_object< + Signature, + coroutine_fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } + + template< typename StackAllocator, typename Allocator > + explicit coroutine( coroutine_fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { + typedef detail::coroutine_object< + Signature, + coroutine_fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } +#endif + template< typename Fn > + explicit coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 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, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( Fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 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) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 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, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 + + coroutine( BOOST_RV_REF( coroutine) other) BOOST_NOEXCEPT : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { swap( other); } + + coroutine & operator=( BOOST_RV_REF( coroutine) other) BOOST_NOEXCEPT + { + 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( coroutine & other) BOOST_NOEXCEPT + { impl_.swap( other.impl_); } +}; + +template< typename Signature, int arity > +class coroutine : public detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >, + public detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > +{ +private: + typedef detail::coroutine_base< Signature > base_t; + typedef typename base_t::ptr_t ptr_t; + + template< typename X, typename Y, int > + friend struct detail::coroutine_get; + template< typename X, typename Y, typename Z, int > + friend struct detail::coroutine_op; + template< typename X, typename Y, typename Z, typename A, typename B, typename C, int > + friend class detail::coroutine_object; + + struct dummy + { void nonnull() {} }; + + typedef void ( dummy::*safe_bool)(); + + ptr_t impl_; + + BOOST_MOVABLE_BUT_NOT_COPYABLE( coroutine) + + template< typename Allocator > + coroutine( detail::coroutine_context const& callee, + bool unwind, bool preserve_fpu, + Allocator const& alloc) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { + typedef detail::coroutine_caller< + Signature, 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: + typedef typename detail::caller< + Signature, + boost::coroutines::coroutine + >::type caller_type; + typedef typename detail::arg< Signature >::type arguments; + + coroutine() BOOST_NOEXCEPT : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + {} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifdef BOOST_MSVC + typedef void ( * coroutine_fn) ( caller_type &); + + explicit coroutine( coroutine_fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >() ) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { + typedef detail::coroutine_object< + Signature, + coroutine_fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } + + explicit coroutine( coroutine_fn fn, arguments arg, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >() ) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { + typedef detail::coroutine_object< + Signature, + coroutine_fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), arg, attr, stack_alloc, a) ); + } + + template< typename StackAllocator > + explicit coroutine( coroutine_fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >() ) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { + typedef detail::coroutine_object< + Signature, + coroutine_fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } + + template< typename StackAllocator, typename Allocator > + explicit coroutine( coroutine_fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { + typedef detail::coroutine_object< + Signature, + coroutine_fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) ); + } +#endif + template< typename Fn > + explicit coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 > + explicit coroutine( BOOST_RV_REF( Fn) fn, arguments arg, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), arg, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( BOOST_RV_REF( Fn) fn, arguments arg, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), arg, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit 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, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( BOOST_RV_REF( Fn) fn, arguments arg, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), arg, attr, stack_alloc, a) ); + } +#else + template< typename Fn > + explicit coroutine( Fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( Fn fn, arguments arg, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, arg, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit coroutine( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 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) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, stack_allocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< coroutine > const& alloc = + std::allocator< coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, std::allocator< coroutine >, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 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, coroutine >, + dummy * + >::type = 0) : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { +// BOOST_STATIC_ASSERT(( +// is_same< void, typename result_of< Fn() >::type >::value)); + typedef detail::coroutine_object< + Signature, + Fn, StackAllocator, Allocator, + caller_type, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + > 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 + + coroutine( BOOST_RV_REF( coroutine) other) BOOST_NOEXCEPT : + detail::coroutine_op< + Signature, + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + detail::coroutine_get< + coroutine< Signature >, + typename function_traits< Signature >::result_type, + function_traits< Signature >::arity + >(), + impl_() + { swap( other); } + + coroutine & operator=( BOOST_RV_REF( coroutine) other) BOOST_NOEXCEPT + { + 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( coroutine & other) BOOST_NOEXCEPT + { impl_.swap( other.impl_); } +}; + +template< typename Signature > +void swap( coroutine< Signature > & l, coroutine< Signature > & r) BOOST_NOEXCEPT +{ l.swap( r); } + +template< typename Signature > +inline +typename coroutine< Signature >::iterator +range_begin( coroutine< Signature > & c) +{ return typename coroutine< Signature >::iterator( & c); } + +template< typename Signature > +inline +typename coroutine< Signature >::const_iterator +range_begin( coroutine< Signature > const& c) +{ return typename coroutine< Signature >::const_iterator( & c); } + +template< typename Signature > +inline +typename coroutine< Signature >::iterator +range_end( coroutine< Signature > &) +{ return typename coroutine< Signature >::iterator(); } + +template< typename Signature > +inline +typename coroutine< Signature >::const_iterator +range_end( coroutine< Signature > const&) +{ return typename coroutine< Signature >::const_iterator(); } + +template< typename Signature > +inline +typename coroutine< Signature >::iterator +begin( coroutine< Signature > & c) +{ return boost::begin( c); } + +template< typename Signature > +inline +typename coroutine< Signature >::iterator +end( coroutine< Signature > & c) +{ return boost::end( c); } + +template< typename Signature > +inline +typename coroutine< Signature >::const_iterator +begin( coroutine< Signature > const& c) +{ return boost::const_begin( c); } + +template< typename Signature > +inline +typename coroutine< Signature >::const_iterator +end( coroutine< Signature > const& c) +{ return boost::const_end( c); } + +} + +template< typename Signature > +struct range_mutable_iterator< coroutines::coroutine< Signature > > +{ typedef typename coroutines::coroutine< Signature >::iterator type; }; + +template< typename Signature > +struct range_const_iterator< coroutines::coroutine< Signature > > +{ typedef typename coroutines::coroutine< Signature >::const_iterator type; }; + +} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_COROUTINES_V1_COROUTINE_H diff --git a/include/boost/coroutine/detail/arg.hpp b/include/boost/coroutine/v1/detail/arg.hpp similarity index 93% rename from include/boost/coroutine/detail/arg.hpp rename to include/boost/coroutine/v1/detail/arg.hpp index f3d35c5..00b2462 100644 --- a/include/boost/coroutine/detail/arg.hpp +++ b/include/boost/coroutine/v1/detail/arg.hpp @@ -3,8 +3,9 @@ // 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_ARG_H -#define BOOST_COROUTINES_DETAIL_ARG_H + +#ifndef BOOST_COROUTINES_V1_DETAIL_ARG_H +#define BOOST_COROUTINES_V1_DETAIL_ARG_H #include #include @@ -58,4 +59,4 @@ BOOST_PP_REPEAT_FROM_TO(2,11,BOOST_CONTEXT_TUPLE,~) # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_ARG_H +#endif // BOOST_COROUTINES_V1_DETAIL_ARG_H diff --git a/include/boost/coroutine/detail/coroutine_base.hpp b/include/boost/coroutine/v1/detail/coroutine_base.hpp similarity index 94% rename from include/boost/coroutine/detail/coroutine_base.hpp rename to include/boost/coroutine/v1/detail/coroutine_base.hpp index 47d67fd..a460cf3 100644 --- a/include/boost/coroutine/detail/coroutine_base.hpp +++ b/include/boost/coroutine/v1/detail/coroutine_base.hpp @@ -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_COROUTINE_BASE_H -#define BOOST_COROUTINES_DETAIL_COROUTINE_BASE_H +#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H +#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H #include #include @@ -17,8 +17,8 @@ #include #include -#include #include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -122,4 +122,4 @@ public: # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_COROUTINE_BASE_H +#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H diff --git a/include/boost/coroutine/detail/coroutine_base_resume.hpp b/include/boost/coroutine/v1/detail/coroutine_base_resume.hpp similarity index 97% rename from include/boost/coroutine/detail/coroutine_base_resume.hpp rename to include/boost/coroutine/v1/detail/coroutine_base_resume.hpp index c344255..9c8a804 100644 --- a/include/boost/coroutine/detail/coroutine_base_resume.hpp +++ b/include/boost/coroutine/v1/detail/coroutine_base_resume.hpp @@ -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_COROUTINE_BASE_RESUME_H -#define BOOST_COROUTINES_DETAIL_COROUTINE_BASE_RESUME_H +#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_RESUME_H +#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_RESUME_H #include @@ -20,11 +20,11 @@ #include #include -#include #include #include #include #include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -234,4 +234,4 @@ BOOST_PP_REPEAT_FROM_TO(2,11,BOOST_COROUTINE_BASE_RESUME,~) # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_coroutine_base_resume_H +#endif // BOOST_COROUTINES_V1_DETAIL_coroutine_base_resume_H diff --git a/include/boost/coroutine/detail/coroutine_caller.hpp b/include/boost/coroutine/v1/detail/coroutine_caller.hpp similarity index 85% rename from include/boost/coroutine/detail/coroutine_caller.hpp rename to include/boost/coroutine/v1/detail/coroutine_caller.hpp index 752d9c9..3796de7 100644 --- a/include/boost/coroutine/detail/coroutine_caller.hpp +++ b/include/boost/coroutine/v1/detail/coroutine_caller.hpp @@ -4,14 +4,14 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_COROUTINES_DETAIL_COROUTINE_CALLER_H -#define BOOST_COROUTINES_DETAIL_COROUTINE_CALLER_H +#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H +#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H #include #include #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -54,4 +54,4 @@ private: # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_COROUTINE_CALLER_H +#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H diff --git a/include/boost/coroutine/detail/coroutine_get.hpp b/include/boost/coroutine/v1/detail/coroutine_get.hpp similarity index 87% rename from include/boost/coroutine/detail/coroutine_get.hpp rename to include/boost/coroutine/v1/detail/coroutine_get.hpp index c2a3339..62b73bb 100644 --- a/include/boost/coroutine/detail/coroutine_get.hpp +++ b/include/boost/coroutine/v1/detail/coroutine_get.hpp @@ -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_COROUTINE_GET_H -#define BOOST_COROUTINES_DETAIL_COROUTINE_GET_H +#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H +#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H #include #include @@ -51,4 +51,4 @@ struct coroutine_get # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_COROUTINE_GET_H +#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H diff --git a/include/boost/coroutine/detail/coroutine_object.hpp b/include/boost/coroutine/v1/detail/coroutine_object.hpp similarity index 75% rename from include/boost/coroutine/detail/coroutine_object.hpp rename to include/boost/coroutine/v1/detail/coroutine_object.hpp index 7f085a7..9dd68ae 100644 --- a/include/boost/coroutine/detail/coroutine_object.hpp +++ b/include/boost/coroutine/v1/detail/coroutine_object.hpp @@ -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_COROUTINE_OBJECT_H -#define BOOST_COROUTINES_DETAIL_COROUTINE_OBJECT_H +#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H +#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H #include @@ -20,15 +20,15 @@ #include #include -#include #include -#include #include #include #include #include #include #include +#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -86,12 +86,12 @@ template< > class coroutine_object; -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include }}} @@ -99,4 +99,4 @@ class coroutine_object; # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_COROUTINE_OBJECT_H +#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H diff --git a/include/boost/coroutine/detail/coroutine_object_result_0.ipp b/include/boost/coroutine/v1/detail/coroutine_object_result_0.ipp similarity index 84% rename from include/boost/coroutine/detail/coroutine_object_result_0.ipp rename to include/boost/coroutine/v1/detail/coroutine_object_result_0.ipp index ff15cde..96022fc 100644 --- a/include/boost/coroutine/detail/coroutine_object_result_0.ipp +++ b/include/boost/coroutine/v1/detail/coroutine_object_result_0.ipp @@ -50,37 +50,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -146,8 +115,27 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() @@ -200,37 +188,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -268,8 +225,27 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() @@ -322,37 +298,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -390,8 +335,27 @@ public: void run() { - Caller c( & this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() diff --git a/include/boost/coroutine/detail/coroutine_object_result_1.ipp b/include/boost/coroutine/v1/detail/coroutine_object_result_1.ipp similarity index 84% rename from include/boost/coroutine/detail/coroutine_object_result_1.ipp rename to include/boost/coroutine/v1/detail/coroutine_object_result_1.ipp index 3246e99..b1e5dfe 100644 --- a/include/boost/coroutine/detail/coroutine_object_result_1.ipp +++ b/include/boost/coroutine/v1/detail/coroutine_object_result_1.ipp @@ -67,37 +67,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -202,15 +171,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + try + { fn_( c); } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + callee = c.impl_->callee_; + } + + this->flags_ |= flag_complete; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() @@ -280,37 +287,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -361,15 +337,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + try + { fn_( c); } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + callee = c.impl_->callee_; + } + + this->flags_ |= flag_complete; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() @@ -439,37 +453,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -520,15 +503,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + try + { fn_( c); } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + callee = c.impl_->callee_; + } + + this->flags_ |= flag_complete; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() diff --git a/include/boost/coroutine/detail/coroutine_object_result_arity.ipp b/include/boost/coroutine/v1/detail/coroutine_object_result_arity.ipp similarity index 84% rename from include/boost/coroutine/detail/coroutine_object_result_arity.ipp rename to include/boost/coroutine/v1/detail/coroutine_object_result_arity.ipp index 27f2815..c2728cb 100644 --- a/include/boost/coroutine/detail/coroutine_object_result_arity.ipp +++ b/include/boost/coroutine/v1/detail/coroutine_object_result_arity.ipp @@ -67,37 +67,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -202,15 +171,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + try + { fn_( c); } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + callee = c.impl_->callee_; + } + + this->flags_ |= flag_complete; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() @@ -280,37 +287,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -361,15 +337,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + try + { fn_( c); } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + callee = c.impl_->callee_; + } + + this->flags_ |= flag_complete; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() @@ -439,37 +453,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< Result > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -520,15 +503,55 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + try + { + fn_( c); + } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + callee = c.impl_->callee_; + } + + this->flags_ |= flag_complete; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); } void deallocate_object() diff --git a/include/boost/coroutine/detail/coroutine_object_void_0.ipp b/include/boost/coroutine/v1/detail/coroutine_object_void_0.ipp similarity index 84% rename from include/boost/coroutine/detail/coroutine_object_void_0.ipp rename to include/boost/coroutine/v1/detail/coroutine_object_void_0.ipp index 5ff5acc..e20df6f 100644 --- a/include/boost/coroutine/detail/coroutine_object_void_0.ipp +++ b/include/boost/coroutine/v1/detail/coroutine_object_void_0.ipp @@ -48,37 +48,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -144,8 +113,27 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void deallocate_object() @@ -196,37 +184,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -264,8 +221,27 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void deallocate_object() @@ -316,37 +292,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -384,8 +329,27 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void deallocate_object() diff --git a/include/boost/coroutine/detail/coroutine_object_void_1.ipp b/include/boost/coroutine/v1/detail/coroutine_object_void_1.ipp similarity index 84% rename from include/boost/coroutine/detail/coroutine_object_void_1.ipp rename to include/boost/coroutine/v1/detail/coroutine_object_void_1.ipp index b01918e..7fba216 100644 --- a/include/boost/coroutine/detail/coroutine_object_void_1.ipp +++ b/include/boost/coroutine/v1/detail/coroutine_object_void_1.ipp @@ -64,37 +64,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -199,15 +168,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + 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, "coroutine is complete"); } void deallocate_object() @@ -274,37 +281,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -356,15 +332,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + 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, "coroutine is complete"); } void deallocate_object() @@ -431,37 +445,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -513,15 +496,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + 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, "coroutine is complete"); } void deallocate_object() diff --git a/include/boost/coroutine/detail/coroutine_object_void_arity.ipp b/include/boost/coroutine/v1/detail/coroutine_object_void_arity.ipp similarity index 84% rename from include/boost/coroutine/detail/coroutine_object_void_arity.ipp rename to include/boost/coroutine/v1/detail/coroutine_object_void_arity.ipp index 29a3f75..7da3e77 100644 --- a/include/boost/coroutine/detail/coroutine_object_void_arity.ipp +++ b/include/boost/coroutine/v1/detail/coroutine_object_void_arity.ipp @@ -65,37 +65,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -200,15 +169,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + 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, "coroutine is complete"); } void deallocate_object() @@ -276,37 +283,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -357,15 +333,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + 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, "coroutine is complete"); } void deallocate_object() @@ -433,37 +447,6 @@ private: if ( this->except_) rethrow_exception( this->except_); } - void run_( Caller & c) - { - coroutine_context callee; - coroutine_context caller; - try - { - fn_( c); - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - catch ( forced_unwind const&) - {} - catch (...) - { this->except_ = current_exception(); } - - this->flags_ |= flag_complete; - callee = c.impl_->callee_; - holder< void > hldr_to( & caller); - caller.jump( - callee, - reinterpret_cast< intptr_t >( & hldr_to), - this->preserve_fpu() ); - BOOST_ASSERT_MSG( false, "coroutine is complete"); - } - void unwind_stack_() BOOST_NOEXCEPT { BOOST_ASSERT( ! this->is_complete() ); @@ -514,15 +497,53 @@ public: void run() { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + 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, "coroutine is complete"); } void run( typename detail::param< arg_type >::type arg) { - Caller c( this->caller_, false, this->preserve_fpu(), alloc_); - c.impl_->result_ = arg; - run_( c); + coroutine_context callee; + coroutine_context caller; + + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + c.impl_->result_ = arg; + 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, "coroutine is complete"); } void deallocate_object() diff --git a/include/boost/coroutine/detail/coroutine_op.hpp b/include/boost/coroutine/v1/detail/coroutine_op.hpp similarity index 97% rename from include/boost/coroutine/detail/coroutine_op.hpp rename to include/boost/coroutine/v1/detail/coroutine_op.hpp index eea8bd6..83806ac 100644 --- a/include/boost/coroutine/detail/coroutine_op.hpp +++ b/include/boost/coroutine/v1/detail/coroutine_op.hpp @@ -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_COROUTINE_OP_H -#define BOOST_COROUTINES_DETAIL_COROUTINE_OP_H +#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H +#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H #include @@ -21,8 +21,8 @@ #include #include -#include #include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -323,4 +323,4 @@ BOOST_PP_REPEAT_FROM_TO(2,11,BOOST_COROUTINE_OP,~) # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_COROUTINES_DETAIL_COROUTINE_OP_H +#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H diff --git a/include/boost/coroutine/v2/detail/coroutine_object.hpp b/include/boost/coroutine/v2/detail/coroutine_object.hpp new file mode 100644 index 0000000..4255b85 --- /dev/null +++ b/include/boost/coroutine/v2/detail/coroutine_object.hpp @@ -0,0 +1,423 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H +#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template< + typename Arg, + typename Fn, typename StackAllocator, typename Allocator +> +class coroutine_object< Arg, Fn, StackAllocator, Allocator > : + private stack_tuple< StackAllocator >, + public coroutine_base +{ +public: + typedef typename Allocator::template rebind< + coroutine_object< + Arg, Fn, StackAllocator, Allocator + > + >::other allocator_t; + +private: + typedef stack_tuple< StackAllocator > pbase_type; + typedef coroutine_base base_type; + + Fn fn_; + allocator_t alloc_; + + static void destroy_( allocator_t & alloc, coroutine_object * p) + { + alloc.destroy( p); + alloc.deallocate( p, 1); + } + + coroutine_object( coroutine_object const&); + coroutine_object & operator=( coroutine_object const&); + + void enter_() + { + holder< void > * hldr_from( + reinterpret_cast< holder< void > * >( + this->caller_.jump( + this->callee_, + reinterpret_cast< intptr_t >( this), + this->preserve_fpu() ) ) ); + this->callee_ = * hldr_from->ctx; + this->result_ = hldr_from->data; + if ( this->except_) rethrow_exception( this->except_); + } + + void run_( Caller & c) + { + coroutine_context callee; + coroutine_context caller; + try + { + fn_( c); + this->flags_ |= flag_complete; + callee = c.impl_->callee_; + holder< void > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); + } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + + this->flags_ |= flag_complete; + callee = c.impl_->callee_; + holder< void > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); + } + + void unwind_stack_() BOOST_NOEXCEPT + { + BOOST_ASSERT( ! this->is_complete() ); + + this->flags_ |= flag_unwind_stack; + holder< void > hldr_to( & this->caller_, true); + this->caller_.jump( + this->callee_, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + this->flags_ &= ~flag_unwind_stack; + + BOOST_ASSERT( this->is_complete() ); + } + +public: +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + pbase_type( stack_alloc, attr.size), + base_type( + trampoline1< coroutine_object >, + & this->stack_ctx, + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( forward< Fn >( fn) ), + alloc_( alloc) + { enter_(); } +#else + coroutine_object( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + pbase_type( stack_alloc, attr.size), + base_type( + trampoline1< coroutine_object >, + & this->stack_ctx, + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( fn), + alloc_( alloc) + { enter_(); } + + coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + pbase_type( stack_alloc, attr.size), + base_type( + trampoline1< coroutine_object >, + & this->stack_ctx, + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( fn), + alloc_( alloc) + { enter_(); } +#endif + + ~coroutine_object() + { + if ( ! this->is_complete() && this->force_unwind() ) + unwind_stack_(); + } + + void run() + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + run_( c); + } + + void deallocate_object() + { destroy_( alloc_, this); } +}; + +template< + typename Arg, + typename Fn, typename StackAllocator, typename Allocator, + typename Caller, + typename Result +> +class coroutine_object< Arg, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > : + private stack_tuple< StackAllocator >, + public coroutine_base< Arg > +{ +public: + typedef typename Allocator::template rebind< + coroutine_object< + Arg, Fn, StackAllocator, Allocator, Caller, Result, 0 + > + >::other allocator_t; + +private: + typedef stack_tuple< StackAllocator > pbase_type; + typedef coroutine_base< Arg > base_type; + + Fn fn_; + allocator_t alloc_; + + static void destroy_( allocator_t & alloc, coroutine_object * p) + { + alloc.destroy( p); + alloc.deallocate( p, 1); + } + + coroutine_object( coroutine_object const&); + coroutine_object & operator=( coroutine_object const&); + + void enter_() + { + holder< Result > * hldr_from( + reinterpret_cast< holder< Result > * >( + this->caller_.jump( + this->callee_, + reinterpret_cast< intptr_t >( this), + this->preserve_fpu() ) ) ); + this->callee_ = * hldr_from->ctx; + this->result_ = hldr_from->data; + if ( this->except_) rethrow_exception( this->except_); + } + + void run_( Caller & c) + { + coroutine_context callee; + coroutine_context caller; + try + { + fn_( c); + this->flags_ |= flag_complete; + callee = c.impl_->callee_; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); + } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + + this->flags_ |= flag_complete; + callee = c.impl_->callee_; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); + } + + void unwind_stack_() BOOST_NOEXCEPT + { + BOOST_ASSERT( ! this->is_complete() ); + + this->flags_ |= flag_unwind_stack; + holder< void > hldr_to( & this->caller_, true); + this->caller_.jump( + this->callee_, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + this->flags_ &= ~flag_unwind_stack; + + BOOST_ASSERT( this->is_complete() ); + } + +public: + coroutine_object( reference_wrapper< Fn > fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + pbase_type( stack_alloc, attr.size), + base_type( + trampoline1< coroutine_object >, + & this->stack_ctx, + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( fn), + alloc_( alloc) + { enter_(); } + + ~coroutine_object() + { + if ( ! this->is_complete() && this->force_unwind() ) + unwind_stack_(); + } + + void run() + { + Caller c( this->caller_, false, this->preserve_fpu(), alloc_); + run_( c); + } + + void deallocate_object() + { destroy_( alloc_, this); } +}; + +template< + typename Arg, + typename Fn, typename StackAllocator, typename Allocator, + typename Caller, + typename Result +> +class coroutine_object< Arg, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > : + private stack_tuple< StackAllocator >, + public coroutine_base< Arg > +{ +public: + typedef typename Allocator::template rebind< + coroutine_object< + Arg, Fn, StackAllocator, Allocator, Caller, Result, 0 + > + >::other allocator_t; + +private: + typedef stack_tuple< StackAllocator > pbase_type; + typedef coroutine_base< Arg > base_type; + + Fn fn_; + allocator_t alloc_; + + static void destroy_( allocator_t & alloc, coroutine_object * p) + { + alloc.destroy( p); + alloc.deallocate( p, 1); + } + + coroutine_object( coroutine_object const&); + coroutine_object & operator=( coroutine_object const&); + + void enter_() + { + holder< Result > * hldr_from( + reinterpret_cast< holder< Result > * >( + this->caller_.jump( + this->callee_, + reinterpret_cast< intptr_t >( this), + this->preserve_fpu() ) ) ); + this->callee_ = hldr_from->ctx; + this->result_ = hldr_from->data; + if ( this->except_) rethrow_exception( this->except_); + } + + void run_( Caller & c) + { + coroutine_context callee; + coroutine_context caller; + try + { + fn_( c); + this->flags_ |= flag_complete; + callee = c.impl_->callee_; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); + } + catch ( forced_unwind const&) + {} + catch (...) + { this->except_ = current_exception(); } + + this->flags_ |= flag_complete; + callee = c.impl_->callee_; + holder< Result > hldr_to( & caller); + caller.jump( + callee, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + BOOST_ASSERT_MSG( false, "coroutine is complete"); + } + + void unwind_stack_() BOOST_NOEXCEPT + { + BOOST_ASSERT( ! this->is_complete() ); + + this->flags_ |= flag_unwind_stack; + holder< void > hldr_to( & this->caller_, true); + this->caller_.jump( + this->callee_, + reinterpret_cast< intptr_t >( & hldr_to), + this->preserve_fpu() ); + this->flags_ &= ~flag_unwind_stack; + + BOOST_ASSERT( this->is_complete() ); + } + +public: + coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + pbase_type( stack_alloc, attr.size), + base_type( + trampoline1< coroutine_object >, + & this->stack_ctx, + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( fn), + alloc_( alloc) + { enter_(); } + + ~coroutine_object() + { + if ( ! this->is_complete() && this->force_unwind() ) + unwind_stack_(); + } + + void run() + { + Caller c( & this->caller_, false, this->preserve_fpu(), alloc_); + run_( c); + } + + void deallocate_object() + { destroy_( alloc_, this); } +}; diff --git a/include/boost/coroutine/v2/pull_corotuine.hpp b/include/boost/coroutine/v2/pull_corotuine.hpp new file mode 100644 index 0000000..fa21476 --- /dev/null +++ b/include/boost/coroutine/v2/pull_corotuine.hpp @@ -0,0 +1,355 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_COROUTINES_V2_PULL_COROUTINE_H +#define BOOST_COROUTINES_V2_PULL_COROUTINE_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace coroutines { +namespace detail { + +template< typename R > +class pull_coroutine +{ +private: + typedef detail::pull_coroutine_base< R > base_t; + typedef typename base_t::ptr_t ptr_t; + + struct dummy + { void nonnull() {} }; + + typedef void ( dummy::*safe_bool)(); + + ptr_t impl_; + + BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine) + +public: + pull_coroutine() BOOST_NOEXCEPT : + impl_() + {} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template< typename Fn > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< pull_coroutine > const& alloc = + std::allocator< pull_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, stack_allocator, std::allocator< pull_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< pull_coroutine > const& alloc = + std::allocator< pull_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, StackAllocator, std::allocator< pull_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, StackAllocator, Allocator + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } +#else + template< typename Fn > + explicit pull_coroutine( Fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< pull_coroutine > const& alloc = + std::allocator< pull_coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, stack_allocator, std::allocator< pull_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit pull_coroutine( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< pull_coroutine > const& alloc = + std::allocator< pull_coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, StackAllocator, std::allocator< pull_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit pull_coroutine( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, StackAllocator, Allocator + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< pull_coroutine > const& alloc = + std::allocator< pull_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, stack_allocator, std::allocator< pull_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< pull_coroutine > const& alloc = + std::allocator< pull_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, StackAllocator, std::allocator< pull_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_same< typename decay< Fn >::type, pull_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::pull_coroutine_object< + R, Fn, StackAllocator, Allocator + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } +#endif + + pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT : + impl_() + { swap( other); } + + pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT + { + pull_coroutine tmp( boost::move( other) ); + swap( tmp); + return * this; + } + + bool empty() const BOOST_NOEXCEPT + { return ! impl_; } + + operator safe_bool() const BOOST_NOEXCEPT + { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; } + + bool operator!() const BOOST_NOEXCEPT + { return empty() || impl_->is_complete(); } + + void swap( pull_coroutine & other) BOOST_NOEXCEPT + { impl_.swap( other.impl_); } + + void operator()() + { + BOOST_ASSERT( * this); + + impl_->resume(); + } + + bool has_result() const + { + BOOST_ASSERT( * this); + + return impl_->has_result(); + } + + R get() const + { + BOOST_ASSERT( * this); + + return impl_->get(); + } +}; + +template< typename R > +void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT +{ l.swap( r); } +#if 0 +template< typename R > +inline +typename pull_coroutine< R >::iterator +range_begin( pull_coroutine< R > & c) +{ return typename pull_coroutine< R >::iterator( & c); } + +template< typename R > +inline +typename pull_coroutine< R >::const_iterator +range_begin( pull_coroutine< R > const& c) +{ return typename pull_coroutine< R >::const_iterator( & c); } + +template< typename R > +inline +typename pull_coroutine< R >::iterator +range_end( pull_coroutine< R > &) +{ return typename pull_coroutine< R >::iterator(); } + +template< typename R > +inline +typename pull_coroutine< R >::const_iterator +range_end( pull_coroutine< R > const&) +{ return typename pull_coroutine< R >::const_iterator(); } + +template< typename R > +inline +typename pull_coroutine< R >::iterator +begin( pull_coroutine< R > & c) +{ return boost::begin( c); } + +template< typename R > +inline +typename pull_coroutine< R >::iterator +end( pull_coroutine< R > & c) +{ return boost::end( c); } + +template< typename R > +inline +typename pull_coroutine< R >::const_iterator +begin( pull_coroutine< R > const& c) +{ return boost::const_begin( c); } + +template< typename R > +inline +typename pull_coroutine< R >::const_iterator +end( pull_coroutine< R > const& c) +{ return boost::const_end( c); } + +} + +template< typename R > +struct range_mutable_iterator< coroutines::coroutine< R > > +{ typedef typename coroutines::coroutine< R >::iterator type; }; + +template< typename R > +struct range_const_iterator< coroutines::coroutine< R > > +{ typedef typename coroutines::coroutine< R >::const_iterator type; }; +#endif +} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_COROUTINES_V2_PULL_COROUTINE_H diff --git a/include/boost/coroutine/v2/push_coroutine.hpp b/include/boost/coroutine/v2/push_coroutine.hpp new file mode 100644 index 0000000..a0a63e5 --- /dev/null +++ b/include/boost/coroutine/v2/push_coroutine.hpp @@ -0,0 +1,357 @@ + +// Copyright Oliver Kowalke 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_COROUTINES_V2_PUSH_COROUTINE_H +#define BOOST_COROUTINES_V2_PUSH_COROUTINE_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace coroutines { +namespace detail { + +template< typename Arg > +class push_coroutine +{ +private: + typedef detail::push_coroutine_base< Arg > base_t; + typedef typename base_t::ptr_t ptr_t; + + struct dummy + { void nonnull() {} }; + + typedef void ( dummy::*safe_bool)(); + + ptr_t impl_; + + BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine) + +public: + push_coroutine() BOOST_NOEXCEPT : + impl_() + {} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template< typename Fn > + explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< push_coroutine > const& alloc = + std::allocator< push_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, push_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, stack_allocator, std::allocator< push_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< push_coroutine > const& alloc = + std::allocator< push_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, push_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, StackAllocator, std::allocator< push_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_same< typename decay< Fn >::type, push_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, StackAllocator, Allocator + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + } +#else + template< typename Fn > + explicit push_coroutine( Fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< push_coroutine > const& alloc = + std::allocator< push_coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, stack_allocator, std::allocator< push_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit push_coroutine( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< push_coroutine > const& alloc = + std::allocator< push_coroutine >(), + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, StackAllocator, std::allocator< push_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit push_coroutine( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_convertible< Fn &, BOOST_RV_REF( Fn) >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, StackAllocator, Allocator + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn > + explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = + stack_allocator(), + std::allocator< push_coroutine > const& alloc = + std::allocator< push_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, push_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, stack_allocator, std::allocator< push_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator > + explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< push_coroutine > const& alloc = + std::allocator< push_coroutine >(), + typename disable_if< + is_same< typename decay< Fn >::type, push_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, StackAllocator, std::allocator< push_coroutine > + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } + + template< typename Fn, typename StackAllocator, typename Allocator > + explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_same< typename decay< Fn >::type, push_coroutine >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::push_coroutine_object< + Arg, Fn, StackAllocator, Allocator + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); + } +#endif + + push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT : + impl_() + { swap( other); } + + push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT + { + push_coroutine tmp( boost::move( other) ); + swap( tmp); + return * this; + } + + bool empty() const BOOST_NOEXCEPT + { return ! impl_; } + + operator safe_bool() const BOOST_NOEXCEPT + { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; } + + bool operator!() const BOOST_NOEXCEPT + { return empty() || impl_->is_complete(); } + + void swap( push_coroutine & other) BOOST_NOEXCEPT + { impl_.swap( other.impl_); } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + void operator()( Arg && arg) + { + BOOST_ASSERT( * this); + + impl_->resume( boost::forward< Arg >( arg) ); + } +#else + void operator()( BOOST_RV_REF( Arg) arg) + { + BOOST_ASSERT( * this); + + impl_->resume( boost::forward< Arg >( arg) ); + } +#endif + + void operator()( Arg arg) + { + BOOST_ASSERT( * this); + + impl_->resume( arg); + } +}; + +template< typename Arg > +void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT +{ l.swap( r); } +#if 0 +template< typename Arg > +inline +typename push_coroutine< Arg >::iterator +range_begin( push_coroutine< Arg > & c) +{ return typename push_coroutine< Arg >::iterator( & c); } + +template< typename Arg > +inline +typename push_coroutine< Arg >::const_iterator +range_begin( push_coroutine< Arg > const& c) +{ return typename push_coroutine< Arg >::const_iterator( & c); } + +template< typename Arg > +inline +typename push_coroutine< Arg >::iterator +range_end( push_coroutine< Arg > &) +{ return typename push_coroutine< Arg >::iterator(); } + +template< typename Arg > +inline +typename push_coroutine< Arg >::const_iterator +range_end( push_coroutine< Arg > const&) +{ return typename push_coroutine< Arg >::const_iterator(); } + +template< typename Arg > +inline +typename push_coroutine< Arg >::iterator +begin( push_coroutine< Arg > & c) +{ return boost::begin( c); } + +template< typename Arg > +inline +typename push_coroutine< Arg >::iterator +end( push_coroutine< Arg > & c) +{ return boost::end( c); } + +template< typename Arg > +inline +typename push_coroutine< Arg >::const_iterator +begin( push_coroutine< Arg > const& c) +{ return boost::const_begin( c); } + +template< typename Arg > +inline +typename push_coroutine< Arg >::const_iterator +end( push_coroutine< Arg > const& c) +{ return boost::const_end( c); } + +} + +template< typename Arg > +struct range_mutable_iterator< coroutines::coroutine< Arg > > +{ typedef typename coroutines::coroutine< Arg >::iterator type; }; + +template< typename Arg > +struct range_const_iterator< coroutines::coroutine< Arg > > +{ typedef typename coroutines::coroutine< Arg >::const_iterator type; }; +#endif +} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_COROUTINES_V2_PUSH_COROUTINE_H diff --git a/src/detail/coroutine_context.cpp b/src/detail/coroutine_context.cpp index bf24719..2bfb660 100644 --- a/src/detail/coroutine_context.cpp +++ b/src/detail/coroutine_context.cpp @@ -64,15 +64,19 @@ intptr_t coroutine_context::jump( coroutine_context & other, intptr_t param, bool preserve_fpu) { #if defined(BOOST_USE_SEGMENTED_STACKS) - if ( stack_ctx_) - __splitstack_getcontext( stack_ctx_->segments_ctx); - if ( other.stack_ctx_) - __splitstack_setcontext( other.stack_ctx_->segments_ctx); -#endif + BOOST_ASSERT( stack_ctx_); + BOOST_ASSERT( other.stack_ctx_); + + __splitstack_getcontext( stack_ctx_->segments_ctx); + __splitstack_setcontext( other.stack_ctx_->segments_ctx); + intptr_t ret = context::jump_fcontext( ctx_, other.ctx_, param, preserve_fpu); + + BOOST_ASSERT( stack_ctx_); + __splitstack_setcontext( stack_ctx_->segments_ctx); + + return ret; +#else return context::jump_fcontext( ctx_, other.ctx_, param, preserve_fpu); -#if defined(BOOST_USE_SEGMENTED_STACKS) - if ( stack_ctx_) - __splitstack_setcontext( stack_ctx_->segments_ctx); #endif } diff --git a/src/detail/segmented_stack_allocator.cpp b/src/detail/segmented_stack_allocator.cpp index 7bc80a7..2a9485c 100644 --- a/src/detail/segmented_stack_allocator.cpp +++ b/src/detail/segmented_stack_allocator.cpp @@ -62,8 +62,6 @@ segmented_stack_allocator::maximum_stacksize() void segmented_stack_allocator::allocate( stack_context & ctx, std::size_t size) { - BOOST_ASSERT( default_stacksize() <= size); - void * limit = __splitstack_makecontext( size, ctx.segments_ctx, & ctx.size); BOOST_ASSERT( limit); ctx.sp = static_cast< char * >( limit) + ctx.size; diff --git a/test/test_coroutine.cpp b/test/test_coroutine.cpp index 9854a0f..c2adea2 100644 --- a/test/test_coroutine.cpp +++ b/test/test_coroutine.cpp @@ -153,6 +153,7 @@ void f11( coro_tuple::caller_type & self) { boost::tuple tpl( self.get().get< 0 >(), self.get().get< 1 >() ); self( tpl); + //self( 7, 11); //TODO: does not work } void f12( coro_int::caller_type & self)