diff --git a/include/boost/fiber/condition.hpp b/include/boost/fiber/condition.hpp index 9b589b43..e9b62f2a 100644 --- a/include/boost/fiber/condition.hpp +++ b/include/boost/fiber/condition.hpp @@ -94,7 +94,7 @@ public: lt.unlock(); lk.unlock(); - while ( ! n->woken_up() ) + while ( ! n->is_ready() ) { fprintf(stdout, "condition: main-fiber not woken-up\n"); // run scheduler diff --git a/include/boost/fiber/detail/fiber_base.hpp b/include/boost/fiber/detail/fiber_base.hpp index 205a8942..53291322 100644 --- a/include/boost/fiber/detail/fiber_base.hpp +++ b/include/boost/fiber/detail/fiber_base.hpp @@ -55,11 +55,11 @@ private: std::vector< ptr_t > joining_; void add_ref() BOOST_NOEXCEPT - { use_count_.fetch_add( 1, memory_order_seq_cst); } + { ++use_count_; } void release_ref() { - if ( 1 == use_count_.fetch_sub( 1, memory_order_seq_cst) ) + if ( 0 == --use_count_) deallocate_object(); } diff --git a/include/boost/fiber/detail/notify.hpp b/include/boost/fiber/detail/notify.hpp index c59d4a90..8c7b96bb 100644 --- a/include/boost/fiber/detail/notify.hpp +++ b/include/boost/fiber/detail/notify.hpp @@ -27,9 +27,6 @@ namespace detail { class notify : private noncopyable { -private: - atomic< bool > wake_up_; - protected: virtual void add_ref() BOOST_NOEXCEPT = 0; virtual void release_ref() = 0; @@ -37,17 +34,11 @@ protected: public: typedef intrusive_ptr< notify > ptr_t; - notify() : - wake_up_( false) - {} - virtual ~notify() {}; - bool woken_up() BOOST_NOEXCEPT - { return wake_up_.exchange( false, memory_order_seq_cst); } + virtual bool is_ready() const BOOST_NOEXCEPT = 0; - void wake_up() BOOST_NOEXCEPT - { wake_up_.exchange( true, memory_order_seq_cst); } + virtual void set_ready() BOOST_NOEXCEPT = 0; friend inline void intrusive_ptr_add_ref( notify * p) BOOST_NOEXCEPT { p->add_ref(); } diff --git a/include/boost/fiber/future.hpp b/include/boost/fiber/future.hpp index 36b8505a..3e07b6d6 100644 --- a/include/boost/fiber/future.hpp +++ b/include/boost/fiber/future.hpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -116,7 +117,7 @@ namespace fibers { struct future_object_base { boost::exception_ptr exception; - bool done; + atomic< bool > done; boost::fibers::mutex mutex; boost::fibers::condition waiters; typedef std::list waiter_list; diff --git a/src/condition.cpp b/src/condition.cpp index 9c0459fd..a4b6e760 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -42,7 +42,7 @@ condition::notify_one() lk.unlock(); if ( n) - n->wake_up(); + n->set_ready(); } void @@ -56,7 +56,7 @@ condition::notify_all() BOOST_FOREACH( detail::notify::ptr_t const& n, waiting) { - n->wake_up(); + n->set_ready(); } } diff --git a/src/detail/fiber_base.cpp b/src/detail/fiber_base.cpp index d6b51dad..7a7c7421 100644 --- a/src/detail/fiber_base.cpp +++ b/src/detail/fiber_base.cpp @@ -23,7 +23,6 @@ namespace fibers { namespace detail { fiber_base::fiber_base( context::fcontext_t * callee, bool preserve_fpu) : - notify(), use_count_( 0), state_( state_ready), flags_( 0), @@ -69,7 +68,7 @@ fiber_base::release() // protect against concurrent access to joining_ unique_lock< spinlock > lk( joining_mtx_); BOOST_FOREACH( fiber_base::ptr_t p, joining_) - { p->wake_up(); } + { p->set_ready(); } joining_.clear(); } diff --git a/src/mutex.cpp b/src/mutex.cpp index 98d6b7ff..0a28cca7 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -36,7 +36,7 @@ mutex::~mutex() void mutex::lock() { - if ( LOCKED == state_.exchange( LOCKED, memory_order_seq_cst) ) + while ( LOCKED == state_.exchange( LOCKED, memory_order_seq_cst) ) { detail::notify::ptr_t n( detail::scheduler::instance().active() ); try @@ -59,7 +59,7 @@ mutex::lock() waiting_.push_back( n); lk.unlock(); - while ( ! n->woken_up() ) + while ( ! n->is_ready() ) { fprintf(stdout, "mutex: main-fiber not woken-up\n"); // run scheduler @@ -98,7 +98,7 @@ mutex::unlock() state_ = UNLOCKED; if ( n) - n->wake_up(); + n->set_ready(); } }} diff --git a/src/round_robin.cpp b/src/round_robin.cpp index 35f16caa..708d8baf 100644 --- a/src/round_robin.cpp +++ b/src/round_robin.cpp @@ -35,22 +35,27 @@ class main_notifier : public detail::notify { private: atomic< std::size_t > use_count_; + mutable atomic< bool > ready_; void add_ref() BOOST_NOEXCEPT - { use_count_.fetch_add( 1, memory_order_seq_cst); } + { ++use_count_; } void release_ref() - { - if ( 1 == use_count_.fetch_sub( 1, memory_order_seq_cst) ) - delete this; - } + { if ( 0 == --use_count_) delete this; } public: main_notifier() : - detail::notify(), - use_count_( 0) + use_count_( 0), ready_( false) {} + bool is_ready() const BOOST_NOEXCEPT + { + return ready_.exchange( false, memory_order_seq_cst); + } + + void set_ready() BOOST_NOEXCEPT + { ready_ = true; } + friend inline void intrusive_ptr_add_ref( main_notifier * p) BOOST_NOEXCEPT { p->add_ref(); } @@ -120,7 +125,8 @@ round_robin::run() // set fiber to state_ready if interruption was requested // or the fiber was woken up - if ( f->interruption_requested() || f->woken_up() ) f->set_ready(); + if ( f->interruption_requested() ) + f->set_ready(); if ( f->is_ready() ) { unique_lock< detail::spinlock > lk( rqueue_mtx_); @@ -185,10 +191,7 @@ round_robin::yield() BOOST_ASSERT( active_fiber_->is_running() ); // set active fiber to state_waiting - active_fiber_->set_waiting(); - // set active_fiber to state_ready - active_fiber_->wake_up(); - // suspends active fiber and adds it to wqueue_ + active_fiber_->set_ready(); // Note: adding to rqueue_ could result in a raise // between adding to rqueue_ and calling yield another // thread could steel fiber from rqueue_ and resume it @@ -221,7 +224,7 @@ round_robin::join( detail::fiber_base::ptr_t const& f) // f must be already terminated therefore we set // active fiber to state_ready // FIXME: better state_running and no suspend - active_fiber_->wake_up(); + active_fiber_->set_ready(); // store active fiber in local var detail::fiber_base::ptr_t tmp = active_fiber_; // suspend fiber until f terminates