diff --git a/include/boost/fiber/algorithm.hpp b/include/boost/fiber/algorithm.hpp index 3aa56001..29aacf10 100644 --- a/include/boost/fiber/algorithm.hpp +++ b/include/boost/fiber/algorithm.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -29,11 +30,9 @@ namespace fibers { struct BOOST_FIBERS_DECL algorithm : private noncopyable { - virtual void add( detail::fiber_base::ptr_t const&) = 0; + virtual void priority( BOOST_RV_REF( fiber), int) = 0; - virtual void priority( detail::fiber_base::ptr_t const&, int) = 0; - - virtual void join( detail::fiber_base::ptr_t const&) = 0; + virtual void join( BOOST_RV_REF( fiber) ) = 0; virtual detail::fiber_base::ptr_t active() = 0; @@ -43,6 +42,10 @@ struct BOOST_FIBERS_DECL algorithm : private noncopyable virtual void yield() = 0; + virtual void migrate_to( fiber const&) = 0; + + virtual fiber steel_from() = 0; + virtual ~algorithm() {} }; diff --git a/include/boost/fiber/detail/fiber_base.hpp b/include/boost/fiber/detail/fiber_base.hpp index ee5debed..97fa4cd4 100644 --- a/include/boost/fiber/detail/fiber_base.hpp +++ b/include/boost/fiber/detail/fiber_base.hpp @@ -26,7 +26,7 @@ #include #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -39,7 +39,13 @@ namespace detail { class BOOST_FIBERS_DECL fiber_base : private noncopyable { public: - typedef intrusive_ptr< fiber_base > ptr_t; + struct deleter + { + void operator()( fiber_base * f) + { f->deallocate_object(); } + }; + typedef shared_ptr< fiber_base > ptr_t; + //typedef intrusive_ptr< fiber_base > ptr_t; private: template< typename X, typename Y, typename Z > @@ -69,7 +75,7 @@ public: friend class fiber_base; fiber_base::ptr_t impl_; - + public: explicit id( fiber_base::ptr_t const& impl) BOOST_NOEXCEPT : impl_( impl) {} diff --git a/include/boost/fiber/fiber.hpp b/include/boost/fiber/fiber.hpp index 5a85d93f..e259ff21 100644 --- a/include/boost/fiber/fiber.hpp +++ b/include/boost/fiber/fiber.hpp @@ -53,7 +53,7 @@ private: typedef base_t::ptr_t ptr_t; typedef void ( dummy::*safe_bool)(); - static void spawn_( detail::fiber_base::ptr_t const&); + static void spawn_( fiber &); ptr_t impl_; @@ -66,7 +66,7 @@ public: impl_() {} - explicit fiber( ptr_t const& impl) BOOST_NOEXCEPT : + fiber( ptr_t const& impl) BOOST_NOEXCEPT : impl_( impl) {} @@ -85,8 +85,8 @@ public: 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) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename StackAllocator > @@ -101,8 +101,8 @@ public: 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) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename StackAllocator, typename Allocator > @@ -117,8 +117,8 @@ public: 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) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } #endif template< typename Fn > @@ -137,8 +137,8 @@ public: 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) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename Fn, typename StackAllocator > @@ -157,8 +157,8 @@ public: 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) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename Fn, typename StackAllocator, typename Allocator > explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr, @@ -176,8 +176,8 @@ public: 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) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } #else template< typename Fn > @@ -196,8 +196,8 @@ public: typename object_t::allocator_t a( alloc); impl_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename Fn, typename StackAllocator > @@ -216,8 +216,8 @@ public: typename object_t::allocator_t a( alloc); impl_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename Fn, typename StackAllocator, typename Allocator > @@ -236,8 +236,8 @@ public: typename object_t::allocator_t a( alloc); impl_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename Fn > @@ -256,8 +256,8 @@ public: typename object_t::allocator_t a( alloc); impl_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename Fn, typename StackAllocator > @@ -276,8 +276,8 @@ public: typename object_t::allocator_t a( alloc); impl_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } template< typename Fn, typename StackAllocator, typename Allocator > @@ -296,8 +296,8 @@ public: typename object_t::allocator_t a( alloc); impl_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); - spawn_( impl_); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a), detail::fiber_base::deleter() ); + spawn_( * this); } #endif @@ -317,16 +317,23 @@ public: } operator safe_bool() const BOOST_NOEXCEPT - { return joinable() ? & dummy::nonnull : 0; } + { return ( ! empty() && ! impl_->is_terminated() ) ? & dummy::nonnull : 0; } bool operator!() const BOOST_NOEXCEPT - { return ! joinable(); } + { return empty() || impl_->is_terminated(); } + + void swap( fiber & other) BOOST_NOEXCEPT + { impl_.swap( other.impl_); } + + bool empty() const BOOST_NOEXCEPT + { return 0 == impl_.get(); } bool joinable() const BOOST_NOEXCEPT - { return impl_ && ! impl_->is_terminated(); } + { return ! empty(); } id get_id() const BOOST_NOEXCEPT - { return impl_ ? impl_->get_id() : id(); } + { return impl_ ? id( impl_) : id(); } + //{ return impl_ ? impl_->get_id() : id(); } int priority() const BOOST_NOEXCEPT; @@ -338,9 +345,6 @@ public: void join(); void interrupt() BOOST_NOEXCEPT; - - void swap( fiber & other) BOOST_NOEXCEPT - { impl_.swap( other.impl_); } }; inline diff --git a/include/boost/fiber/round_robin.hpp b/include/boost/fiber/round_robin.hpp index 2718cec6..f1588146 100644 --- a/include/boost/fiber/round_robin.hpp +++ b/include/boost/fiber/round_robin.hpp @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -50,8 +49,6 @@ public: ~round_robin() BOOST_NOEXCEPT; - void add( detail::fiber_base::ptr_t const&); - void priority( detail::fiber_base::ptr_t const&, int); void join( detail::fiber_base::ptr_t const&); @@ -65,7 +62,7 @@ public: void yield(); - void migrate_to( BOOST_RV_REF( fiber) f); + void migrate_to( fiber const&); fiber steel_from(); }; diff --git a/src/detail/fiber_base.cpp b/src/detail/fiber_base.cpp index a9f4e98f..8b7f0de5 100644 --- a/src/detail/fiber_base.cpp +++ b/src/detail/fiber_base.cpp @@ -71,7 +71,7 @@ fiber_base::release() // so they can be resumed // protect against concurrent access to joining_ unique_lock< spinlock > lk( joining_mtx_); - BOOST_FOREACH( fiber_base::ptr_t & p, joining_) + BOOST_FOREACH( fiber_base::ptr_t p, joining_) { std::stringstream ss; ss << p->get_id(); diff --git a/src/fiber.cpp b/src/fiber.cpp index 9fe0a09a..59a0cf48 100644 --- a/src/fiber.cpp +++ b/src/fiber.cpp @@ -25,8 +25,8 @@ namespace boost { namespace fibers { void -fiber::spawn_( detail::fiber_base::ptr_t const& f) -{ detail::scheduler::instance().add( f); } +fiber::spawn_( fiber & f) +{ detail::scheduler::instance().migrate_to( f); } int fiber::priority() const diff --git a/src/mutex.cpp b/src/mutex.cpp index 0c3a770b..98cdbb9f 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -34,7 +34,7 @@ mutex::lock() { while ( LOCKED == state_.exchange( LOCKED, memory_order_seq_cst) ) { - if ( ! this_fiber::is_fiberized() ) ::abort(); + BOOST_ASSERT( this_fiber::is_fiberized() ); unique_lock< detail::spinlock > lk( waiting_mtx_); waiting_.push_back( diff --git a/src/round_robin.cpp b/src/round_robin.cpp index a2fdbbbc..7a36f417 100644 --- a/src/round_robin.cpp +++ b/src/round_robin.cpp @@ -54,16 +54,6 @@ round_robin::~round_robin() #endif } -void -round_robin::add( detail::fiber_base::ptr_t const& f) -{ - BOOST_ASSERT( f); - BOOST_ASSERT( ! f->is_running() ); - BOOST_ASSERT( ! f->is_terminated() ); - - wqueue_.push_back( f); -} - bool round_robin::run() { @@ -228,9 +218,14 @@ round_robin::priority( detail::fiber_base::ptr_t const& f, int prio) } void -round_robin::migrate_to( BOOST_RV_REF( fiber) f) +round_robin::migrate_to( fiber const& f_) { - add( detail::scheduler::extract( f) ); + detail::fiber_base::ptr_t f = detail::scheduler::extract( f_); + BOOST_ASSERT( f); + BOOST_ASSERT( ! f->is_running() ); + BOOST_ASSERT( ! f->is_terminated() ); + + wqueue_.push_back( f); } fiber diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index cffe5208..07a3a44f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,7 +24,7 @@ rule fiber-test ( source ) } test-suite fibers : -# [ fiber-test test_fiber ] + [ fiber-test test_fiber ] # [ fiber-test test_mutex ] # [ fiber-test test_condition ] # [ fiber-test test_generic_locks ] @@ -34,5 +34,5 @@ test-suite fibers : # [ fiber-test test_futures ] # [ fiber-test test_then ] # [ fiber-test test_round_robin ] - [ fiber-test test_fiber_steeling ] +# [ fiber-test test_fiber_steeling ] ; diff --git a/test/test_fiber_steeling.cpp b/test/test_fiber_steeling.cpp index af9e055c..a07d2d40 100644 --- a/test/test_fiber_steeling.cpp +++ b/test/test_fiber_steeling.cpp @@ -89,10 +89,10 @@ void fn_steel_fibers( boost::fibers::round_robin * other_ds, boost::barrier * b, if ( f) { ++( * count); - ds.migrate_to( boost::move( f) ); + ds.migrate_to( f); while ( boost::fibers::run() ); } - BOOST_ASSERT( ! f); + f.detach(); } }