From c9969ebdaf59d1f989112c522cb498dab8f5e599 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Thu, 22 Nov 2012 18:57:59 +0100 Subject: [PATCH] modification for fiberswq --- boost/fiber/detail/fiber_base.hpp | 117 ++++------ boost/fiber/detail/fiber_object.hpp | 314 +++++++++++++++++++++++---- boost/fiber/detail/flags.hpp | 38 ++++ boost/fiber/detail/scheduler.hpp | 20 +- boost/fiber/fiber.hpp | 134 +++++++++--- boost/fiber/flags.hpp | 27 +++ boost/fiber/operations.hpp | 78 ++++++- boost/fiber/stack_allocator.hpp | 2 +- libs/fiber/examples/Jamfile.v2 | 14 +- libs/fiber/examples/simple.cpp | 2 +- libs/fiber/src/detail/fiber_base.cpp | 70 +----- libs/fiber/src/detail/scheduler.cpp | 15 +- libs/fiber/src/fiber.cpp | 34 --- 13 files changed, 583 insertions(+), 282 deletions(-) create mode 100644 boost/fiber/detail/flags.hpp create mode 100644 boost/fiber/flags.hpp diff --git a/boost/fiber/detail/fiber_base.hpp b/boost/fiber/detail/fiber_base.hpp index fec5044f..7e7e5661 100644 --- a/boost/fiber/detail/fiber_base.hpp +++ b/boost/fiber/detail/fiber_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_FIBERS_DETAIL_STRATUM_BASE_H -#define BOOST_FIBERS_DETAIL_STRATUM_BASE_H +#ifndef BOOST_FIBERS_DETAIL_FIBER_BASE_H +#define BOOST_FIBERS_DETAIL_FIBER_BASE_H #include #include @@ -15,12 +15,13 @@ #include #include #include -#include #include +#include #include #include #include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -30,63 +31,28 @@ namespace boost { namespace fibers { namespace detail { -struct forced_unwind {}; - -enum flag_t -{ - flag_resumed = 1 << 1, - flag_complete = 1 << 2, - flag_unwind_stack = 1 << 3, - flag_canceled = 1 << 4 -}; - -template< typename Fiber > -void trampoline( intptr_t vp) -{ - BOOST_ASSERT( vp); - - Fiber * f( reinterpret_cast< Fiber * >( vp) ); - BOOST_ASSERT( ! f->is_complete() ); - BOOST_ASSERT( f->is_resumed() ); - try - { f->exec(); } - catch ( forced_unwind const&) - {} - catch (...) - { - //TODO: call std::terminate() or do nothing? - } - f->flags_ &= ~flag_resumed; - f->flags_ &= ~flag_unwind_stack; - f->flags_ |= flag_complete; - - ctx::jump_fcontext( & f->callee_, & f->caller_, 0, f->preserve_fpu_); -} - class BOOST_FIBERS_DECL fiber_base : private noncopyable { public: typedef intrusive_ptr< fiber_base > ptr_t; private: - template< typename T > - friend void trampoline( intptr_t); friend class scheduler; + template< typename X, typename Y, typename Z > + friend class fiber_object; std::size_t use_count_; - ctx::stack_allocator alloc_; - ctx::fcontext_t caller_; - ctx::fcontext_t callee_; + context::fcontext_t caller_; + context::fcontext_t * callee_; int flags_; - bool preserve_fpu_; + exception_ptr except_; std::vector< ptr_t > joining_; - void unwind_stack_(); - - void terminate_(); - void notify_(); +protected: + virtual void deallocate_object() = 0; + public: class id { @@ -95,31 +61,31 @@ public: fiber_base::ptr_t impl_; - id( fiber_base::ptr_t const& impl) : + explicit id( fiber_base::ptr_t const& impl) BOOST_NOEXCEPT : impl_( impl) {} public: - id() : + id() BOOST_NOEXCEPT : impl_() {} - bool operator==( id const& other) const + bool operator==( id const& other) const BOOST_NOEXCEPT { return impl_ == other.impl_; } - bool operator!=( id const& other) const + bool operator!=( id const& other) const BOOST_NOEXCEPT { return impl_ != other.impl_; } - bool operator<( id const& other) const + bool operator<( id const& other) const BOOST_NOEXCEPT { return impl_ < other.impl_; } - bool operator>( id const& other) const + bool operator>( id const& other) const BOOST_NOEXCEPT { return other.impl_ < impl_; } - bool operator<=( id const& other) const + bool operator<=( id const& other) const BOOST_NOEXCEPT { return ! ( * this > other); } - bool operator>=( id const& other) const + bool operator>=( id const& other) const BOOST_NOEXCEPT { return ! ( * this < other); } template< typename charT, class traitsT > @@ -132,26 +98,23 @@ public: return os << "{not-valid}"; } - operator bool() const + operator bool() const BOOST_NOEXCEPT { return 0 != impl_; } - bool operator!() const + bool operator!() const BOOST_NOEXCEPT { return 0 == impl_; } }; - fiber_base( std::size_t size, bool preserve_fpu); + fiber_base( context::fcontext_t *, bool, bool); - virtual ~fiber_base(); + virtual ~fiber_base() {} - id get_id() const; + virtual void terminate() = 0; - bool is_canceled() const; + id get_id() const BOOST_NOEXCEPT + { return id( ptr_t( const_cast< fiber_base * >( this) ) ); } - bool is_complete() const; - - bool is_resumed() const; - - void join( ptr_t const& p); + void join( ptr_t const&); void resume(); @@ -165,13 +128,29 @@ public: void sleep( chrono::system_clock::time_point const& abs_time); - virtual void exec() = 0; + bool force_unwind() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_forced_unwind); } - friend inline void intrusive_ptr_add_ref( fiber_base * p) + bool unwind_requested() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_unwind_stack); } + + bool preserve_fpu() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_preserve_fpu); } + + bool is_complete() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_complete); } + + bool is_canceled() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_canceled); } + + bool is_resumed() const BOOST_NOEXCEPT + { return 0 != ( flags_ & flag_resumed); } + + friend inline void intrusive_ptr_add_ref( fiber_base * p) BOOST_NOEXCEPT { ++p->use_count_; } friend inline void intrusive_ptr_release( fiber_base * p) - { if ( --p->use_count_ == 0) delete p; } + { if ( --p->use_count_ == 0) p->deallocate_object(); } }; }}} @@ -180,4 +159,4 @@ public: # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_FIBERS_DETAIL_STRATUM_BASE_H +#endif // BOOST_FIBERS_DETAIL_FIBER_BASE_H diff --git a/boost/fiber/detail/fiber_object.hpp b/boost/fiber/detail/fiber_object.hpp index 2c770c1e..256ba7c4 100644 --- a/boost/fiber/detail/fiber_object.hpp +++ b/boost/fiber/detail/fiber_object.hpp @@ -4,17 +4,22 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_FIBERS_DETAIL_STRATUM_OBJECT_H -#define BOOST_FIBERS_DETAIL_STRATUM_OBJECT_H +#ifndef BOOST_FIBERS_DETAIL_FIBER_OBJECT_H +#define BOOST_FIBERS_DETAIL_FIBER_OBJECT_H #include +#include #include +#include #include #include +#include #include #include +#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -24,66 +29,291 @@ namespace boost { namespace fibers { namespace detail { -template< typename Fn > +struct forced_unwind {}; + +template< typename Fiber > +void trampoline( intptr_t vp) +{ + BOOST_ASSERT( vp); + + Fiber * f( reinterpret_cast< Fiber * >( vp) ); + f->exec(); +} + +template< typename Fn, typename StackAllocator, typename Allocator > class fiber_object : public fiber_base { -private: - Fn fn_; +public: + typedef typename Allocator::template rebind< + fiber_object< + Fn, StackAllocator, Allocator + > + >::other allocator_t; - fiber_object( fiber_object &); - fiber_object & operator=( fiber_object const&); +private: + Fn fn_; + context::stack_t stack_; + StackAllocator stack_alloc_; + allocator_t alloc_; + + static void destroy_( allocator_t & alloc, fiber_object * p) + { + alloc.destroy( p); + alloc.deallocate( p, 1); + } + + fiber_object( fiber_object &); + fiber_object & operator=( fiber_object const&); + + void enter_() + { + context::jump_fcontext( + & this->caller_, this->callee_, + reinterpret_cast< intptr_t >( this), + this->preserve_fpu() ); + if ( this->except_) rethrow_exception( this->except_); + } + + void unwind_stack_() + { + + } public: - fiber_object( Fn fn, std::size_t size, bool preserve_fpu) : - fiber_base( size, preserve_fpu), - fn_( fn) - {} +#ifndef BOOST_NO_RVALUE_REFERENCES + fiber_object( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + fiber_base( + context::make_fcontext( + stack_alloc.allocate( attr.size), attr.size, + trampoline< fiber_object >), + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( forward< Fn >( fn) ), + stack_( fiber_base::callee_->fc_stack), + stack_alloc_( stack_alloc), + alloc_( alloc) + { enter_(); } +#else + fiber_object( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + fiber_base( + context::make_fcontext( + stack_alloc.allocate( attr.size), attr.size, + trampoline< fiber_object >), + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( fn), + stack_( fiber_base::callee_->fc_stack), + stack_alloc_( stack_alloc), + alloc_( alloc) + { enter_(); } - fiber_object( BOOST_RV_REF( Fn) fn, std::size_t size, bool preserve_fpu) : - fiber_base( size, preserve_fpu), - fn_( boost::move( fn) ) - {} + fiber_object( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + fiber_base( + context::make_fcontext( + stack_alloc.allocate( attr.size), attr.size, + trampoline< fiber_object >), + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( fn), + stack_( fiber_base::callee_->fc_stack), + stack_alloc_( stack_alloc), + alloc_( alloc) + { enter_(); } +#endif - void exec() - { fn_(); } + void exec() + { + BOOST_ASSERT( ! is_complete() ); + + suspend(); + + try + { fn_(); } + catch ( forced_unwind const&) + {} + catch (...) + { except_ = current_exception(); } + + flags_ &= ~flag_resumed; + flags_ |= flag_complete; + + context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() ); + BOOST_ASSERT_MSG( false, "fiber is complete"); + } + + void deallocate_object() + { destroy_( alloc_, this); } + + void terminate() + { + BOOST_ASSERT( ! is_resumed() ); + + if ( ! is_complete() ) + { + flags_ |= flag_canceled; + unwind_stack_(); + } + + notify_(); + + BOOST_ASSERT( is_complete() ); + BOOST_ASSERT( ! is_resumed() ); + BOOST_ASSERT( joining_.empty() ); + } }; -template< typename Fn > -class fiber_object< reference_wrapper< Fn > > : public fiber_base +template< typename Fn, typename StackAllocator, typename Allocator > +class fiber_object< reference_wrapper< Fn >, StackAllocator, Allocator > : public fiber_base { -private: - Fn fn_; +public: + typedef typename Allocator::template rebind< + fiber_object< + Fn, StackAllocator, Allocator + > + >::other allocator_t; - fiber_object( fiber_object &); - fiber_object & operator=( fiber_object const&); +private: + Fn fn_; + context::stack_t stack_; + StackAllocator stack_alloc_; + allocator_t alloc_; + + static void destroy_( allocator_t & alloc, fiber_object * p) + { + alloc.destroy( p); + alloc.deallocate( p, 1); + } + + fiber_object( fiber_object &); + fiber_object & operator=( fiber_object const&); + + void enter_() + { + context::jump_fcontext( + & this->caller_, this->callee_, + reinterpret_cast< intptr_t >( this), + this->preserve_fpu() ); + if ( this->except_) rethrow_exception( this->except_); + } public: - fiber_object( reference_wrapper< Fn > fn, std::size_t size, bool preserve_fpu) : - fiber_base( size, preserve_fpu), - fn_( fn) - {} + fiber_object( reference_wrapper< Fn > fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + fiber_base( + context::make_fcontext( + stack_alloc.allocate( attr.size), attr.size, + trampoline< fiber_object >), + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( fn), + stack_( fiber_base::callee_->fc_stack), + stack_alloc_( stack_alloc), + alloc_( alloc) + { enter_(); } - void exec() - { fn_(); } + void exec() + { + BOOST_ASSERT( ! is_complete() ); + + suspend(); + + try + { fn_(); } + catch ( forced_unwind const&) + {} + catch (...) + { except_ = current_exception(); } + + flags_ &= ~flag_resumed; + flags_ |= flag_complete; + + context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() ); + BOOST_ASSERT_MSG( false, "fiber is complete"); + } + + void deallocate_object() + { destroy_( alloc_, this); } }; -template< typename Fn > -class fiber_object< const reference_wrapper< Fn > > : public fiber_base +template< typename Fn, typename StackAllocator, typename Allocator > +class fiber_object< const reference_wrapper< Fn >, StackAllocator, Allocator > : public fiber_base { -private: - Fn fn_; +public: + typedef typename Allocator::template rebind< + fiber_object< + Fn, StackAllocator, Allocator + > + >::other allocator_t; - fiber_object( fiber_object &); - fiber_object & operator=( fiber_object const&); +private: + Fn fn_; + context::stack_t stack_; + StackAllocator stack_alloc_; + allocator_t alloc_; + + static void destroy_( allocator_t & alloc, fiber_object * p) + { + alloc.destroy( p); + alloc.deallocate( p, 1); + } + + fiber_object( fiber_object &); + fiber_object & operator=( fiber_object const&); + + void enter_() + { + context::jump_fcontext( + & this->caller_, this->callee_, + reinterpret_cast< intptr_t >( this), + this->preserve_fpu() ); + if ( this->except_) rethrow_exception( this->except_); + } public: - fiber_object( const reference_wrapper< Fn > fn, std::size_t size, bool preserve_fpu) : - fiber_base( size, preserve_fpu), - fn_( fn) - {} + fiber_object( const reference_wrapper< Fn > fn, attributes const& attr, + StackAllocator const& stack_alloc, + allocator_t const& alloc) : + fiber_base( + context::make_fcontext( + stack_alloc.allocate( attr.size), attr.size, + trampoline< fiber_object >), + stack_unwind == attr.do_unwind, + fpu_preserved == attr.preserve_fpu), + fn_( fn), + stack_( fiber_base::callee_->fc_stack), + stack_alloc_( stack_alloc), + alloc_( alloc) + { enter_(); } - void exec() - { fn_(); } + void exec() + { + BOOST_ASSERT( ! is_complete() ); + + suspend(); + + try + { fn_(); } + catch ( forced_unwind const&) + {} + catch (...) + { except_ = current_exception(); } + + flags_ &= ~flag_resumed; + flags_ |= flag_complete; + + context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() ); + BOOST_ASSERT_MSG( false, "fiber is complete"); + } + + void deallocate_object() + { destroy_( alloc_, this); } }; }}} @@ -92,4 +322,4 @@ public: # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_FIBERS_DETAIL_STRATUM_OBJECT_H +#endif // BOOST_FIBERS_DETAIL_FIBER_OBJECT_H diff --git a/boost/fiber/detail/flags.hpp b/boost/fiber/detail/flags.hpp new file mode 100644 index 00000000..8f271d63 --- /dev/null +++ b/boost/fiber/detail/flags.hpp @@ -0,0 +1,38 @@ + +// 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_FIBERS_DETAIL_FLAGS_H +#define BOOST_FIBERS_DETAIL_FLAGS_H + +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace fibers { +namespace detail { + +enum flag_t +{ + flag_forced_unwind = 1 << 1, + flag_unwind_stack = 1 << 2, + flag_preserve_fpu = 1 << 3, + flag_complete = 1 << 4, + flag_resumed = 1 << 5, + flag_canceled = 1 << 6 +}; + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_FIBERS_DETAIL_FLAGS_H diff --git a/boost/fiber/detail/scheduler.hpp b/boost/fiber/detail/scheduler.hpp index b1bce5a6..8c251023 100644 --- a/boost/fiber/detail/scheduler.hpp +++ b/boost/fiber/detail/scheduler.hpp @@ -92,25 +92,7 @@ private: public: static scheduler & instance(); - template< typename Fn > - fiber spawn( Fn fn, std::size_t size, bool preserve_fpu) - { - fiber f( fn, size, preserve_fpu); - active_fiber_.swap( f.impl_); - resume_(); - active_fiber_.swap( f.impl_); - return f; - } - - template< typename Fn > - fiber spawn( BOOST_RV_REF( Fn) fn, std::size_t size, bool preserve_fpu) - { - fiber f( boost::move( fn), size, preserve_fpu); - active_fiber_.swap( f.impl_); - resume_(); - active_fiber_.swap( f.impl_); - return f; - } + void spawn( fiber_base::ptr_t const&); void join( fiber_base::ptr_t const&); diff --git a/boost/fiber/fiber.hpp b/boost/fiber/fiber.hpp index 8b73b174..9ad39a76 100644 --- a/boost/fiber/fiber.hpp +++ b/boost/fiber/fiber.hpp @@ -11,9 +11,13 @@ #include #include -#include #include +#include +#include +#include +#include +#include #include #include @@ -45,68 +49,130 @@ private: friend void migrate_to( BOOST_RV_REF( fiber) ); friend class detail::scheduler; + struct dummy + { void nonnull() {} }; + typedef detail::fiber_base base_t; typedef base_t::ptr_t ptr_t; + typedef void ( dummy::*safe_bool)(); ptr_t impl_; BOOST_MOVABLE_BUT_NOT_COPYABLE( fiber); - fiber( ptr_t const& impl) : + fiber( ptr_t const& impl) BOOST_NOEXCEPT : impl_( impl) { BOOST_ASSERT( impl_); } - template< typename Fn > - fiber( Fn fn, std::size_t size = ctx::default_stacksize(), - bool preserve_fpu = true) : - impl_( - new detail::fiber_object< Fn >( - fn, size, preserve_fpu) ) - {} +#ifndef BOOST_NO_RVALUE_REFERENCES +#ifdef BOOST_MSVC + typedef void ( * fiber_fn)(); - template< typename Fn > - fiber( BOOST_RV_REF( Fn) fn, std::size_t size = ctx::default_stacksize(), - bool preserve_fpu = true) : - impl_( - new detail::fiber_object< Fn >( - boost::move( fn), size, preserve_fpu) ) - {} + template< typename StackAllocator, typename Allocator > + explicit fiber( fiber_fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocacator const& alloc) : + impl_() + { + typedef detail::fiber_object< + fiber_fn, StackAllocator, Allocator + > object_t; + typename object_t::allocator_t a( alloc); + impl_ = ptr_t( + // placement new + ::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, stack_alloc, a) ); + } +#endif + template< typename Fn, typename StackAllocator, typename Allocator > + explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocacator const& alloc, + typename disable_if< + is_same< typename decay< Fn >::type, fiber >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::fiber_object< + 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, typename StackAllocator, typename Allocator > + explicit fiber( 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::fiber_object< + 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, typename StackAllocator, typename Allocator > + explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc, + typename disable_if< + is_same< typename decay< Fn >::type, fiber >, + dummy * + >::type = 0) : + impl_() + { + typedef detail::fiber_object< + 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 public: typedef detail::fiber_base::id id; - typedef void ( * unspecified_bool_type)( fiber ***); - static void unspecified_bool( fiber ***) {} - - fiber() : + fiber() BOOST_NOEXCEPT : impl_() {} - fiber( BOOST_RV_REF( fiber) other) : + fiber( BOOST_RV_REF( fiber) other) BOOST_NOEXCEPT : impl_() - { impl_.swap( other.impl_); } + { swap( other); } - fiber & operator=( BOOST_RV_REF( fiber) other) + fiber & operator=( BOOST_RV_REF( fiber) other) BOOST_NOEXCEPT { - fiber tmp( other); + fiber tmp( move( other) ); swap( tmp); return * this; } - operator unspecified_bool_type() const; + operator safe_bool() const BOOST_NOEXCEPT + { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; } - bool operator!() const; + bool operator!() const BOOST_NOEXCEPT + { return empty() || impl_->is_complete(); } - void swap( fiber & other); + void swap( fiber & other) BOOST_NOEXCEPT + { impl_.swap( other.impl_); } - bool operator==( fiber const& other) const; - bool operator!=( fiber const& other) const; + bool empty() const BOOST_NOEXCEPT + { return ! impl_; } - id get_id() const; - - bool is_joinable() const; - - bool is_complete() const; + id get_id() const BOOST_NOEXCEPT + { return impl_ ? impl_->get_id() : id(); } void cancel(); diff --git a/boost/fiber/flags.hpp b/boost/fiber/flags.hpp new file mode 100644 index 00000000..5fb95e03 --- /dev/null +++ b/boost/fiber/flags.hpp @@ -0,0 +1,27 @@ + +// 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_FIBERS_FLAGS_H +#define BOOST_FIBERS_FLAGS_H + +namespace boost { +namespace fibers { + +enum flag_unwind_t +{ + stack_unwind = 0, + no_stack_unwind +}; + +enum flag_fpu_t +{ + fpu_preserved = 0, + fpu_not_preserved +}; + +}} + +#endif // BOOST_FIBERS_FLAGS_H diff --git a/boost/fiber/operations.hpp b/boost/fiber/operations.hpp index e853c2b9..40633d8c 100644 --- a/boost/fiber/operations.hpp +++ b/boost/fiber/operations.hpp @@ -6,10 +6,11 @@ #ifndef BOOST_THIS_STRATUM_OPERATIONS_H #define BOOST_THIS_STRATUM_OPERATIONS_H +#include + #include #include #include -#include #include #include #include @@ -66,15 +67,70 @@ void yield_break() namespace fibers { +#ifndef BOOST_NO_RVALUE_REFERENCES +#ifdef BOOST_MSVC +#endif +#else template< typename Fn > -fiber spawn( Fn fn, std::size_t size = ctx::default_stacksize(), - bool preserve_fpu = true) -{ return detail::scheduler::instance().spawn( fn, size, preserve_fpu); } +fiber spawn( Fn fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = stack_allocator(), + std::allocator< fiber > const& alloc = std::allocator< fiber >() ) +{ + fiber f( fn, attr, stack_alloc, alloc); + detail::scheduler::instance().spawn( f.impl_); + return f; +} + +template< typename Fn, typename StackAllocator > +fiber spawn( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< fiber > const& alloc = std::allocator< fiber >() ) +{ + fiber f( fn, attr, stack_alloc, alloc); + detail::scheduler::instance().spawn( f.impl_); + return f; +} + +template< typename Fn, typename StackAllocator, typename Allocator > +fiber spawn( Fn fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc) +{ + fiber f( fn, attr, stack_alloc, alloc); + detail::scheduler::instance().spawn( f.impl_); + return f; +} template< typename Fn > -fiber spawn( BOOST_RV_REF( Fn) fn, std::size_t size = ctx::default_stacksize(), - bool preserve_fpu = true) -{ return detail::scheduler::instance().spawn( boost::move( fn), size, preserve_fpu); } +fiber spawn( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(), + stack_allocator const& stack_alloc = stack_allocator(), + std::allocator< fiber > const& alloc = std::allocator< fiber >() ) +{ + fiber f( fn, attr, stack_alloc, alloc); + detail::scheduler::instance().spawn( f.impl_); + return f; +} + +template< typename Fn, typename StackAllocator > +fiber spawn( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + std::allocator< fiber > const& alloc = std::allocator< fiber >() ) +{ + fiber f( fn, attr, stack_alloc, alloc); + detail::scheduler::instance().spawn( f.impl_); + return f; +} + +template< typename Fn, typename StackAllocator, typename Allocator > +fiber spawn( BOOST_RV_REF( Fn) fn, attributes const& attr, + StackAllocator const& stack_alloc, + Allocator const& alloc) +{ + fiber f( fn, attr, stack_alloc, alloc); + detail::scheduler::instance().spawn( f.impl_); + return f; +} +#endif inline bool run() @@ -87,17 +143,17 @@ bool run() BOOST_PP_ENUM(n,BOOST_FIBERS_WAITFOR_STRATUM_FN_ARG,~) #define BOOST_FIBERS_WAITFOR_STRATUM_AND(z,n,t) \ - BOOST_PP_EXPR_IF(n,&&) BOOST_PP_CAT(s,n).is_complete() + BOOST_PP_EXPR_IF(n,&&) BOOST_PP_CAT(s,n) #define BOOST_FIBERS_WAITFOR_STRATUM_OR(z,n,t) \ - BOOST_PP_EXPR_IF(n,||) BOOST_PP_CAT(s,n).is_complete() + BOOST_PP_EXPR_IF(n,||) BOOST_PP_CAT(s,n) #define BOOST_FIBERS_WAITFOR_STRATUM_CANCEL(z,n,t) \ - if ( ! BOOST_PP_CAT(s,n).is_complete() ) \ + if ( ! BOOST_PP_CAT(s,n) ) \ BOOST_PP_CAT(s,n).cancel(); #define BOOST_FIBERS_WAITFOR_STRATUM_READY(z,n,t) \ - if ( BOOST_PP_CAT(s,n).is_complete() ) return n; + if ( BOOST_PP_CAT(s,n) ) return n; #define BOOST_FIBERS_WAITFOR_STRATUM_ALL(z,n,unused) \ inline \ diff --git a/boost/fiber/stack_allocator.hpp b/boost/fiber/stack_allocator.hpp index 4f498cba..7d7a047c 100644 --- a/boost/fiber/stack_allocator.hpp +++ b/boost/fiber/stack_allocator.hpp @@ -16,7 +16,7 @@ #endif namespace boost { -namespace coroutines { +namespace fibers { using detail::stack_allocator; }} diff --git a/libs/fiber/examples/Jamfile.v2 b/libs/fiber/examples/Jamfile.v2 index f66c56ba..903085ac 100644 --- a/libs/fiber/examples/Jamfile.v2 +++ b/libs/fiber/examples/Jamfile.v2 @@ -29,11 +29,11 @@ exe asio/host : asio/host.cpp ; -exe barrier : barrier.cpp ; -exe future : future.cpp ; -exe join : join.cpp ; -exe ping_pong : ping_pong.cpp ; +#exe barrier : barrier.cpp ; +#exe future : future.cpp ; +#exe join : join.cpp ; +#exe ping_pong : ping_pong.cpp ; exe simple : simple.cpp ; -exe wait_all : wait_all.cpp ; -exe wait_any : wait_any.cpp ; -exe wait_any_cancel : wait_any_cancel.cpp ; +#exe wait_all : wait_all.cpp ; +#exe wait_any : wait_any.cpp ; +#exe wait_any_cancel : wait_any_cancel.cpp ; diff --git a/libs/fiber/examples/simple.cpp b/libs/fiber/examples/simple.cpp index 24e2fd69..78a99987 100644 --- a/libs/fiber/examples/simple.cpp +++ b/libs/fiber/examples/simple.cpp @@ -26,7 +26,7 @@ int main() stm::fiber s1( stm::spawn( boost::bind( fn, "abc", 5) ) ); stm::fiber s2( stm::spawn( boost::bind( fn, "xyz", 7) ) ); - while ( ! s1.is_complete() || ! s2.is_complete() ) + while ( s1 || s2 ) stm::run(); std::cout << "done." << std::endl; diff --git a/libs/fiber/src/detail/fiber_base.cpp b/libs/fiber/src/detail/fiber_base.cpp index c9f1d663..c62f3114 100644 --- a/libs/fiber/src/detail/fiber_base.cpp +++ b/libs/fiber/src/detail/fiber_base.cpp @@ -20,37 +20,6 @@ namespace boost { namespace fibers { namespace detail { -void -fiber_base::unwind_stack_() -{ - BOOST_ASSERT( ! is_complete() ); - BOOST_ASSERT( ! is_resumed() ); - - flags_ |= flag_resumed; - flags_ |= flag_unwind_stack; - ctx::jump_fcontext( & caller_, & callee_, 0, preserve_fpu_); - BOOST_ASSERT( is_complete() ); - BOOST_ASSERT( ! is_resumed() ); -} - -void -fiber_base::terminate_() -{ - BOOST_ASSERT( ! is_resumed() ); - - if ( ! is_complete() ) - { - flags_ |= flag_canceled; - unwind_stack_(); - } - - notify_(); - - BOOST_ASSERT( is_complete() ); - BOOST_ASSERT( ! is_resumed() ); - BOOST_ASSERT( joining_.empty() ); -} - void fiber_base::notify_() { @@ -62,43 +31,18 @@ fiber_base::notify_() joining_.clear(); } -fiber_base::fiber_base( std::size_t size, bool preserve_fpu) : +fiber_base::fiber_base( context::fcontext_t * callee, bool unwind, bool preserve_fpu) : use_count_( 0), - alloc_(), caller_(), - callee_(), + callee_( callee), flags_( 0), - preserve_fpu_( preserve_fpu), + except_(), joining_() { - callee_.fc_stack.base = alloc_.allocate( size); - callee_.fc_stack.size = size; - - ctx::make_fcontext( & callee_, trampoline< fiber_base >); + if ( unwind) flags_ |= flag_forced_unwind; + if ( preserve_fpu) flags_ |= flag_preserve_fpu; } -fiber_base::~fiber_base() -{ - terminate_(); - alloc_.deallocate( callee_.fc_stack.base, callee_.fc_stack.size); -} - -fiber_base::id -fiber_base::get_id() const -{ return id( ptr_t( const_cast< fiber_base * >( this) ) ); } - -bool -fiber_base::is_canceled() const -{ return 0 != ( flags_ & flag_canceled); } - -bool -fiber_base::is_complete() const -{ return 0 != ( flags_ & flag_complete); } - -bool -fiber_base::is_resumed() const -{ return 0 != ( flags_ & flag_resumed); } - void fiber_base::join( ptr_t const& p) { @@ -116,7 +60,7 @@ fiber_base::resume() BOOST_ASSERT( ! is_resumed() ); flags_ |= flag_resumed; - ctx::jump_fcontext( & caller_, & callee_, ( intptr_t) this, preserve_fpu_); + context::jump_fcontext( & caller_, callee_, ( intptr_t) this, preserve_fpu() ); if ( is_complete() ) notify_(); @@ -130,7 +74,7 @@ fiber_base::suspend() BOOST_ASSERT( is_resumed() ); flags_ &= ~flag_resumed; - ctx::jump_fcontext( & callee_, & caller_, 0, preserve_fpu_); + context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() ); BOOST_ASSERT( is_resumed() ); diff --git a/libs/fiber/src/detail/scheduler.cpp b/libs/fiber/src/detail/scheduler.cpp index 5b81dcd1..119484ff 100644 --- a/libs/fiber/src/detail/scheduler.cpp +++ b/libs/fiber/src/detail/scheduler.cpp @@ -58,6 +58,19 @@ scheduler::instance() return * static_local.get(); } +void +scheduler::spawn( fiber_base::ptr_t const& f) +{ + BOOST_ASSERT( f); + BOOST_ASSERT( ! f->is_complete() ); + BOOST_ASSERT( f != active_fiber_); + + fiber_base::ptr_t tmp = active_fiber_; + active_fiber_ = f; + resume_(); + active_fiber_ = tmp; +} + void scheduler::join( fiber_base::ptr_t const& f) { @@ -98,7 +111,7 @@ scheduler::cancel( fiber_base::ptr_t const& f) // terminate fiber means unwinding its stack // so it becomes complete and joining strati // will be notified - active_fiber_->terminate_(); + active_fiber_->terminate(); active_fiber_ = tmp; // erase completed fiber from waiting-queue f_idx_.erase( f); diff --git a/libs/fiber/src/fiber.cpp b/libs/fiber/src/fiber.cpp index 07b8f476..08bcf908 100644 --- a/libs/fiber/src/fiber.cpp +++ b/libs/fiber/src/fiber.cpp @@ -20,40 +20,6 @@ namespace boost { namespace fibers { -fiber::operator unspecified_bool_type() const -{ return impl_ ? unspecified_bool : 0; } - -bool -fiber::operator!() const -{ return ! impl_; } - -bool -fiber::operator==( fiber const& other) const -{ return get_id() == other.get_id(); } - -bool -fiber::operator!=( fiber const& other) const -{ return ! ( get_id() == other.get_id() ); } - -void -fiber::swap( fiber & other) -{ impl_.swap( other.impl_); } - -fiber::id -fiber::get_id() const -{ return impl_ ? impl_->get_id() : id(); } - -bool -fiber::is_joinable() const -{ return impl_ && ! impl_->is_complete(); } - -bool -fiber::is_complete() const -{ - BOOST_ASSERT( impl_); - return impl_->is_complete(); -} - void fiber::cancel() {