diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 3699a75f..164906c7 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -36,7 +36,6 @@ lib boost_fibers condition.cpp detail/fiber_base.cpp detail/scheduler.cpp - detail/spinlock.cpp fiber.cpp future.cpp interruption.cpp diff --git a/include/boost/fiber/algorithm.hpp b/include/boost/fiber/algorithm.hpp index 28d1e900..996f07b6 100644 --- a/include/boost/fiber/algorithm.hpp +++ b/include/boost/fiber/algorithm.hpp @@ -14,7 +14,6 @@ #include #include -#include #include #ifdef BOOST_HAS_ABI_HEADERS @@ -41,7 +40,7 @@ struct BOOST_FIBERS_DECL algorithm : private noncopyable virtual bool run() = 0; - virtual void wait( unique_lock< detail::spinlock > &) = 0; + virtual void wait() = 0; virtual void yield() = 0; diff --git a/include/boost/fiber/bounded_channel.hpp b/include/boost/fiber/bounded_channel.hpp index 584b71cd..9a90183c 100644 --- a/include/boost/fiber/bounded_channel.hpp +++ b/include/boost/fiber/bounded_channel.hpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -73,14 +72,14 @@ private: template< typename X > friend void intrusive_ptr_release( bounded_channel< X > * p); - enum state + enum state_t { ACTIVE = 0, DEACTIVE }; - atomic< state > state_; - atomic< std::size_t > count_; + state_t state_; + std::size_t count_; typename node_type::ptr head_; mutable mutex head_mtx_; typename node_type::ptr tail_; diff --git a/include/boost/fiber/condition.hpp b/include/boost/fiber/condition.hpp index 4387b6a9..8976c311 100644 --- a/include/boost/fiber/condition.hpp +++ b/include/boost/fiber/condition.hpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -21,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -42,7 +40,6 @@ namespace fibers { class BOOST_FIBERS_DECL condition : private noncopyable { private: - detail::spinlock splk_; std::deque< detail::notify::ptr_t > waiting_; public: @@ -70,12 +67,11 @@ public: if ( n) { // store this fiber in order to be notified later - unique_lock< detail::spinlock > lk( splk_); waiting_.push_back( n); lt.unlock(); // suspend fiber - detail::scheduler::instance().wait( lk); + detail::scheduler::instance().wait(); // check if fiber was interrupted this_fiber::interruption_point(); @@ -85,9 +81,7 @@ public: // notifier for main-fiber n = detail::scheduler::instance().notifier(); // store this fiber in order to be notified later - unique_lock< detail::spinlock > lk( splk_); waiting_.push_back( n); - lk.unlock(); lt.unlock(); while ( ! n->is_ready() ) @@ -100,7 +94,6 @@ public: catch (...) { // remove fiber from waiting_ - unique_lock< detail::spinlock > lk( splk_); waiting_.erase( std::find( waiting_.begin(), waiting_.end(), n) ); throw; diff --git a/include/boost/fiber/detail/fiber_base.hpp b/include/boost/fiber/detail/fiber_base.hpp index ad6436ed..a343ea0e 100644 --- a/include/boost/fiber/detail/fiber_base.hpp +++ b/include/boost/fiber/detail/fiber_base.hpp @@ -11,8 +11,6 @@ #include #include -#include -#include #include #include #include @@ -24,7 +22,6 @@ #include #include #include -#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -43,18 +40,20 @@ private: template< typename X, typename Y > friend class fiber_object; - static const int READY; - static const int RUNNING; - static const int WAITING; - static const int TERMINATED; + enum state_t + { + READY = 0, + RUNNING, + WAITING, + TERMINATED + }; - atomic< int > state_; - atomic< int > flags_; - atomic< int > priority_; + state_t state_; + int flags_; + int priority_; context::fcontext_t caller_; context::fcontext_t * callee_; exception_ptr except_; - spinlock waiting_mtx_; std::vector< ptr_t > waiting_; protected: @@ -193,7 +192,8 @@ public: // - other fiber calls set_ready() on this fiber happend before this // fiber calls set_terminated() // - this fiber stack gets unwound and set_terminated() is called at the end - int previous = state_.exchange( TERMINATED); + state_t previous = TERMINATED; + std::swap( state_, previous); BOOST_ASSERT( RUNNING == previous); //BOOST_ASSERT( RUNNING == previous || READY == previous); } @@ -219,13 +219,15 @@ public: if ( result || TERMINATED == expected || READY == expected) return; } #endif - int previous = state_.exchange( READY); + state_t previous = READY; + std::swap( state_, previous); BOOST_ASSERT( WAITING == previous || RUNNING == previous || READY == previous); } void set_running() BOOST_NOEXCEPT { - int previous = state_.exchange( RUNNING); + state_t previous = RUNNING; + std::swap( state_, previous); BOOST_ASSERT( READY == previous); } @@ -240,7 +242,8 @@ public: // - other fiber calls set_ready() on this fiber happend before this // fiber calls set_waiting() // - this fiber might wait on some sync. primitive calling set_waiting() - int previous = state_.exchange( WAITING); + state_t previous = WAITING; + std::swap( state_, previous); BOOST_ASSERT( RUNNING == previous); //BOOST_ASSERT( RUNNING == previous || READY == previous); } diff --git a/include/boost/fiber/detail/notify.hpp b/include/boost/fiber/detail/notify.hpp index ddac2ce5..5567b623 100644 --- a/include/boost/fiber/detail/notify.hpp +++ b/include/boost/fiber/detail/notify.hpp @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -28,7 +27,7 @@ namespace detail { class notify : private noncopyable { private: - atomic< std::size_t > use_count_; + std::size_t use_count_; public: typedef intrusive_ptr< notify > ptr_t; diff --git a/include/boost/fiber/detail/spinlock.hpp b/include/boost/fiber/detail/spinlock.hpp deleted file mode 100644 index ccdb7a1a..00000000 --- a/include/boost/fiber/detail/spinlock.hpp +++ /dev/null @@ -1,39 +0,0 @@ - -// 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) -// -// based on boost::interprocess::sync::interprocess_spin::mutex - -#ifndef BOOST_FIBERS_SPINLOCK_H -#define BOOST_FIBERS_SPINLOCK_H - -#include -#include - -#include - -namespace boost { -namespace fibers { -namespace detail { - -class BOOST_FIBERS_DECL spinlock : private noncopyable -{ -private: - static const int LOCKED; - static const int UNLOCKED; - - atomic< int > state_; - -public: - spinlock(); - - void lock(); - - void unlock(); -}; - -}}} - -#endif // BOOST_FIBERS_SPINLOCK_H diff --git a/include/boost/fiber/future/detail/future_base.hpp b/include/boost/fiber/future/detail/future_base.hpp index 85006b25..c651ade6 100644 --- a/include/boost/fiber/future/detail/future_base.hpp +++ b/include/boost/fiber/future/detail/future_base.hpp @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -36,7 +35,7 @@ template< typename R > class future_base : public noncopyable { private: - atomic< std::size_t > use_count_; + std::size_t use_count_; mutable mutex mtx_; mutable condition waiters_; bool ready_; @@ -228,7 +227,7 @@ template< typename R > class future_base< R & > : public noncopyable { private: - atomic< std::size_t > use_count_; + std::size_t use_count_; mutable mutex mtx_; mutable condition waiters_; bool ready_; @@ -372,7 +371,7 @@ template<> class future_base< void > : public noncopyable { private: - atomic< std::size_t > use_count_; + std::size_t use_count_; mutable mutex mtx_; mutable condition waiters_; bool ready_; diff --git a/include/boost/fiber/future/detail/task_base.hpp b/include/boost/fiber/future/detail/task_base.hpp index a4f2833d..6773d8e9 100644 --- a/include/boost/fiber/future/detail/task_base.hpp +++ b/include/boost/fiber/future/detail/task_base.hpp @@ -9,7 +9,6 @@ #include -#include #include #include #include diff --git a/include/boost/fiber/future/packaged_task.hpp b/include/boost/fiber/future/packaged_task.hpp index 96d2ddd2..34f16399 100644 --- a/include/boost/fiber/future/packaged_task.hpp +++ b/include/boost/fiber/future/packaged_task.hpp @@ -9,7 +9,6 @@ #include -#include #include #include #include @@ -40,7 +39,7 @@ private: typedef void ( dummy::*safe_bool)(); - atomic< bool > obtained_; + bool obtained_; ptr_t task_; BOOST_MOVABLE_BUT_NOT_COPYABLE( packaged_task); @@ -304,7 +303,7 @@ public: void swap( packaged_task & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two packaged_task - obtained_ = other.obtained_.exchange( obtained_.load() ); + std::swap( obtained_, other.obtained_); task_.swap( other.task_); } @@ -371,7 +370,7 @@ private: typedef void ( dummy::*safe_bool)(); - atomic< bool > obtained_; + bool obtained_; ptr_t task_; BOOST_MOVABLE_BUT_NOT_COPYABLE( packaged_task); @@ -635,7 +634,7 @@ public: void swap( packaged_task & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two packaged_task - obtained_ = other.obtained_.exchange( obtained_.load() ); + std::swap( obtained_, other.obtained_); task_.swap( other.task_); } diff --git a/include/boost/fiber/future/promise.hpp b/include/boost/fiber/future/promise.hpp index ca3ff50c..19048301 100644 --- a/include/boost/fiber/future/promise.hpp +++ b/include/boost/fiber/future/promise.hpp @@ -9,7 +9,6 @@ #include -#include #include #include #include @@ -34,7 +33,7 @@ private: typedef void ( dummy::*safe_bool)(); - atomic< bool > obtained_; + bool obtained_; ptr_t future_; BOOST_MOVABLE_BUT_NOT_COPYABLE( promise); @@ -124,7 +123,7 @@ public: void swap( promise & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two promises - obtained_ = other.obtained_.exchange( obtained_.load() ); + std::swap( obtained_, other.obtained_); future_.swap( other.future_); } @@ -215,7 +214,7 @@ private: typedef void ( dummy::*safe_bool)(); - atomic< bool > obtained_; + bool obtained_; ptr_t future_; BOOST_MOVABLE_BUT_NOT_COPYABLE( promise); @@ -305,7 +304,7 @@ public: void swap( promise & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two promises - obtained_ = other.obtained_.exchange( obtained_.load() ); + std::swap( obtained_, other.obtained_); future_.swap( other.future_); } @@ -368,7 +367,7 @@ private: typedef void ( dummy::*safe_bool)(); - atomic< bool > obtained_; + bool obtained_; ptr_t future_; BOOST_MOVABLE_BUT_NOT_COPYABLE( promise); @@ -458,7 +457,7 @@ public: void swap( promise & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two promises - obtained_ = other.obtained_.exchange( obtained_.load() ); + std::swap( obtained_, other.obtained_); future_.swap( other.future_); } diff --git a/include/boost/fiber/mutex.hpp b/include/boost/fiber/mutex.hpp index 82585766..0f0b7c5d 100644 --- a/include/boost/fiber/mutex.hpp +++ b/include/boost/fiber/mutex.hpp @@ -11,14 +11,12 @@ #include -#include #include #include #include #include #include -#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -35,11 +33,13 @@ namespace fibers { class BOOST_FIBERS_DECL mutex : private noncopyable { private: - static const int LOCKED; - static const int UNLOCKED; + enum state_t + { + LOCKED = 0, + UNLOCKED + }; - atomic< int > state_; - detail::spinlock splk_; + volatile state_t state_; std::deque< detail::notify::ptr_t > waiting_; diff --git a/include/boost/fiber/round_robin.hpp b/include/boost/fiber/round_robin.hpp index 29cad4e1..f6b914d1 100644 --- a/include/boost/fiber/round_robin.hpp +++ b/include/boost/fiber/round_robin.hpp @@ -18,7 +18,6 @@ #include #include -#include #include #include @@ -43,7 +42,6 @@ private: detail::fiber_base::ptr_t active_fiber_; detail::notify::ptr_t notifier_; wqueue_t wqueue_; - detail::spinlock rqueue_mtx_; rqueue_t rqueue_; public: @@ -62,7 +60,7 @@ public: bool run(); - void wait( unique_lock< detail::spinlock > &); + void wait(); void yield(); diff --git a/src/condition.cpp b/src/condition.cpp index 41ef451f..1447f9cd 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -20,7 +20,6 @@ namespace boost { namespace fibers { condition::condition() : - splk_(), waiting_() {} @@ -33,12 +32,10 @@ condition::notify_one() detail::notify::ptr_t n; // get one waiting fiber - unique_lock< detail::spinlock > lk( splk_); if ( ! waiting_.empty() ) { n.swap( waiting_.front() ); waiting_.pop_front(); } - lk.unlock(); // notify waiting fiber if ( n) @@ -51,9 +48,7 @@ condition::notify_all() std::deque< detail::notify::ptr_t > waiting; // get all waiting fibers - unique_lock< detail::spinlock > lk( splk_); waiting.swap( waiting_); - lk.unlock(); // notify all waiting fibers while ( ! waiting.empty() ) diff --git a/src/detail/fiber_base.cpp b/src/detail/fiber_base.cpp index d4872c2e..9673d6c0 100644 --- a/src/detail/fiber_base.cpp +++ b/src/detail/fiber_base.cpp @@ -22,11 +22,6 @@ namespace boost { namespace fibers { namespace detail { -const int fiber_base::READY = 0; -const int fiber_base::RUNNING = 1; -const int fiber_base::WAITING = 2; -const int fiber_base::TERMINATED = 3; - fiber_base::fiber_base( context::fcontext_t * callee, bool preserve_fpu) : state_( READY), flags_( 0), @@ -34,7 +29,6 @@ fiber_base::fiber_base( context::fcontext_t * callee, bool preserve_fpu) : caller_(), callee_( callee), except_(), - waiting_mtx_(), waiting_() { if ( preserve_fpu) flags_ |= flag_preserve_fpu; } @@ -72,9 +66,7 @@ fiber_base::release() std::vector< ptr_t > waiting; // get all waiting fibers - unique_lock< spinlock > lk( waiting_mtx_); waiting.swap( waiting_); - lk.unlock(); // notify all waiting fibers BOOST_FOREACH( fiber_base::ptr_t p, waiting) @@ -85,7 +77,6 @@ bool fiber_base::join( ptr_t const& p) { // protect against concurrent access to waiting_ - unique_lock< spinlock > lk( waiting_mtx_); if ( is_terminated() ) return false; waiting_.push_back( p); return true; diff --git a/src/detail/spinlock.cpp b/src/detail/spinlock.cpp deleted file mode 100644 index 30246efe..00000000 --- a/src/detail/spinlock.cpp +++ /dev/null @@ -1,44 +0,0 @@ - -// 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) - -#define BOOST_FIBERS_SOURCE - -#include - -#include - -#include -#include - -namespace boost { -namespace fibers { -namespace detail { - -const int spinlock::LOCKED = 0; -const int spinlock::UNLOCKED = 1; - -spinlock::spinlock() : - state_( UNLOCKED) -{} - -void -spinlock::lock() -{ - while ( LOCKED == state_.exchange( LOCKED) ) - { - // busy-wait - if ( scheduler::instance().active() ) - scheduler::instance().yield(); - else - thread_yield(); - } -} - -void -spinlock::unlock() -{ state_ = UNLOCKED; } - -}}} diff --git a/src/mutex.cpp b/src/mutex.cpp index 44fd464a..93c6b000 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -22,12 +22,8 @@ namespace boost { namespace fibers { -const int mutex::LOCKED = 0; -const int mutex::UNLOCKED = 1; - mutex::mutex() : state_( UNLOCKED), - splk_(), waiting_() {} @@ -37,7 +33,7 @@ mutex::~mutex() void mutex::lock() { - while ( LOCKED == state_.exchange( LOCKED) ) + while ( LOCKED == state_) { detail::notify::ptr_t n( detail::scheduler::instance().active() ); try @@ -45,11 +41,10 @@ mutex::lock() if ( n) { // store this fiber in order to be notified later - unique_lock< detail::spinlock > lk( splk_); waiting_.push_back( n); // suspend this fiber - detail::scheduler::instance().wait( lk); + detail::scheduler::instance().wait(); } else { @@ -57,9 +52,7 @@ mutex::lock() n = detail::scheduler::instance().notifier(); // store this fiber in order to be notified later - unique_lock< detail::spinlock > lk( splk_); waiting_.push_back( n); - lk.unlock(); // wait until main-fiber gets notified while ( ! n->is_ready() ) @@ -72,29 +65,34 @@ mutex::lock() catch (...) { // remove fiber from waiting_ - unique_lock< detail::spinlock > lk( splk_); waiting_.erase( std::find( waiting_.begin(), waiting_.end(), n) ); throw; } } + state_ = LOCKED; } bool mutex::try_lock() -{ return UNLOCKED == state_.exchange( LOCKED); } +{ + if ( UNLOCKED == state_) + { + state_ = LOCKED; + return true; + } + return false; +} void mutex::unlock() { detail::notify::ptr_t n; - unique_lock< detail::spinlock > lk( splk_); if ( ! waiting_.empty() ) { n.swap( waiting_.front() ); waiting_.pop_front(); } - lk.unlock(); state_ = UNLOCKED; diff --git a/src/round_robin.cpp b/src/round_robin.cpp index b8e3630c..b70943b0 100644 --- a/src/round_robin.cpp +++ b/src/round_robin.cpp @@ -34,7 +34,7 @@ namespace detail { class main_notifier : public detail::notify { private: - mutable atomic< bool > ready_; + mutable bool ready_; public: main_notifier() : @@ -42,7 +42,14 @@ public: {} bool is_ready() const BOOST_NOEXCEPT - { return ready_.exchange( false); } + { + if ( ready_) + { + ready_ = false; + return true; + } + return false; + } void set_ready() BOOST_NOEXCEPT { ready_ = true; } @@ -54,7 +61,6 @@ round_robin::round_robin() : active_fiber_(), notifier_( new detail::main_notifier() ), wqueue_(), - rqueue_mtx_(), rqueue_() {} @@ -62,7 +68,6 @@ round_robin::~round_robin() { #if 0 BOOST_ASSERT( ! active_fiber_); - unique_lock< detail::spinlock > lk( rqueue_mtx_); BOOST_FOREACH( detail::fiber_base::ptr_t const& p, rqueue_) { p->release(); @@ -113,10 +118,7 @@ round_robin::run() if ( f->interruption_requested() ) f->set_ready(); if ( f->is_ready() ) - { - unique_lock< detail::spinlock > lk( rqueue_mtx_); rqueue_.push_back( f); - } else wqueue.push_back( f); } // exchange local with global waiting queue @@ -127,11 +129,9 @@ round_robin::run() detail::fiber_base::ptr_t f; do { - unique_lock< detail::spinlock > lk( rqueue_mtx_); if ( rqueue_.empty() ) return false; f.swap( rqueue_.front() ); rqueue_.pop_front(); - lk.unlock(); if ( f->is_ready() ) break; if ( f->is_waiting() ) wqueue_.push_back( f); @@ -146,7 +146,7 @@ round_robin::run() } void -round_robin::wait( unique_lock< detail::spinlock > & lk) +round_robin::wait() { BOOST_ASSERT( active_fiber_); //FIXME: mabye other threads can change the state of active fiber? @@ -158,8 +158,6 @@ round_robin::wait( unique_lock< detail::spinlock > & lk) wqueue_.push_back( active_fiber_); // store active fiber in local var detail::fiber_base::ptr_t tmp = active_fiber_; - // release lock - lk.unlock(); // suspend fiber tmp->suspend(); // fiber is resumed