diff --git a/include/boost/fiber/condition.hpp b/include/boost/fiber/condition.hpp index c859f011..64b89e25 100644 --- a/include/boost/fiber/condition.hpp +++ b/include/boost/fiber/condition.hpp @@ -80,6 +80,7 @@ public: // lock spinlock unique_lock< detail::spinlock > lk( splk_); + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); // store this fiber in waiting-queue // in order notify (resume) this fiber later waiting_.push_back( n); @@ -104,6 +105,7 @@ public: // lock spinlock unique_lock< detail::spinlock > lk( splk_); + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); // store this main-notifier in waiting-queue // in order to be notified later waiting_.push_back( n); diff --git a/include/boost/fiber/future/detail/future_traits.hpp b/include/boost/fiber/future/detail/future_traits.hpp deleted file mode 100644 index f955c5fd..00000000 --- a/include/boost/fiber/future/detail/future_traits.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// (C) Copyright 2008-9 Anthony Williams -// -// 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_FUTURE_TRAITS_H -#define BOOST_FIBERS_DETAIL_FUTURE_TRAITS_H - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -template -struct future_traits -{ - typedef boost::scoped_ptr storage_type; -#ifdef BOOST_HAS_RVALUE_REFS - typedef T const& source_reference_type; - struct dummy; - typedef typename boost::mpl::if_,dummy&,T&&>::type rvalue_source_type; - typedef typename boost::mpl::if_,T,T&&>::type move_dest_type; -#else - typedef T& source_reference_type; - typedef typename boost::mpl::if_, BOOST_RV_REF( T),T const&>::type rvalue_source_type; - typedef typename boost::mpl::if_,BOOST_RV_REF( T),T>::type move_dest_type; -#endif - - static void init(storage_type& storage,source_reference_type t) - { storage.reset(new T(t)); } - - static void init(storage_type& storage,rvalue_source_type t) - { storage.reset(new T(static_cast(t))); } - - static void cleanup(storage_type& storage) - { storage.reset(); } -}; - -template -struct future_traits -{ - typedef T* storage_type; - typedef T& source_reference_type; - struct rvalue_source_type {}; - typedef T& move_dest_type; - - static void init(storage_type& storage,T& t) - { storage=&t; } - - static void cleanup(storage_type& storage) - { storage=0; } -}; - -template<> -struct future_traits -{ - typedef bool storage_type; - typedef void move_dest_type; - - static void init(storage_type& storage) - { storage=true; } - - static void cleanup(storage_type& storage) - { storage=false; } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_FUTURE_TRAITS_H diff --git a/include/boost/fiber/future/detail/future_base.hpp b/include/boost/fiber/future/detail/shared_state.hpp similarity index 94% rename from include/boost/fiber/future/detail/future_base.hpp rename to include/boost/fiber/future/detail/shared_state.hpp index 0109dd4a..407865e6 100644 --- a/include/boost/fiber/future/detail/future_base.hpp +++ b/include/boost/fiber/future/detail/shared_state.hpp @@ -4,12 +4,13 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_FIBERS_DETAIL_FUTURE_BASE_H -#define BOOST_FIBERS_DETAIL_FUTURE_BASE_H +#ifndef BOOST_FIBERS_DETAIL_SHARED_STATE_H +#define BOOST_FIBERS_DETAIL_SHARED_STATE_H #include #include +#include #include #include #include @@ -33,10 +34,10 @@ namespace fibers { namespace detail { template< typename R > -class future_base : public noncopyable +class shared_state : public noncopyable { private: - std::size_t use_count_; + atomic< std::size_t > use_count_; mutable mutex mtx_; mutable condition waiters_; bool ready_; @@ -154,14 +155,14 @@ protected: virtual void deallocate_future() = 0; public: - typedef intrusive_ptr< future_base > ptr_t; + typedef intrusive_ptr< shared_state > ptr_t; - future_base() : + shared_state() : use_count_( 0), mtx_(), ready_( false), value_(), except_() {} - virtual ~future_base() {} + virtual ~shared_state() {} void owner_destroyed() { @@ -261,10 +262,10 @@ public: void reset() { ready_ = false; } - friend inline void intrusive_ptr_add_ref( future_base * p) BOOST_NOEXCEPT + friend inline void intrusive_ptr_add_ref( shared_state * p) BOOST_NOEXCEPT { ++p->use_count_; } - friend inline void intrusive_ptr_release( future_base * p) + friend inline void intrusive_ptr_release( shared_state * p) { if ( 0 == --p->use_count_) p->deallocate_future(); @@ -272,10 +273,10 @@ public: }; template< typename R > -class future_base< R & > : public noncopyable +class shared_state< R & > : public noncopyable { private: - std::size_t use_count_; + atomic< std::size_t > use_count_; mutable mutex mtx_; mutable condition waiters_; bool ready_; @@ -369,14 +370,14 @@ protected: virtual void deallocate_future() = 0; public: - typedef intrusive_ptr< future_base > ptr_t; + typedef intrusive_ptr< shared_state > ptr_t; - future_base() : + shared_state() : use_count_( 0), mtx_(), ready_( false), value_( 0), except_() {} - virtual ~future_base() {} + virtual ~shared_state() {} void owner_destroyed() { @@ -452,10 +453,10 @@ public: void reset() { ready_ = false; } - friend inline void intrusive_ptr_add_ref( future_base * p) BOOST_NOEXCEPT + friend inline void intrusive_ptr_add_ref( shared_state * p) BOOST_NOEXCEPT { ++p->use_count_; } - friend inline void intrusive_ptr_release( future_base * p) + friend inline void intrusive_ptr_release( shared_state * p) { if ( 0 == --p->use_count_) p->deallocate_future(); @@ -463,10 +464,10 @@ public: }; template<> -class future_base< void > : public noncopyable +class shared_state< void > : public noncopyable { private: - std::size_t use_count_; + atomic< std::size_t > use_count_; mutable mutex mtx_; mutable condition waiters_; bool ready_; @@ -557,13 +558,13 @@ protected: virtual void deallocate_future() = 0; public: - typedef intrusive_ptr< future_base > ptr_t; + typedef intrusive_ptr< shared_state > ptr_t; - future_base() : + shared_state() : use_count_( 0), mtx_(), ready_( false), except_() {} - virtual ~future_base() {} + virtual ~shared_state() {} void owner_destroyed() { @@ -639,10 +640,10 @@ public: void reset() { ready_ = false; } - friend inline void intrusive_ptr_add_ref( future_base * p) BOOST_NOEXCEPT + friend inline void intrusive_ptr_add_ref( shared_state * p) BOOST_NOEXCEPT { ++p->use_count_; } - friend inline void intrusive_ptr_release( future_base * p) + friend inline void intrusive_ptr_release( shared_state * p) { if ( 0 == --p->use_count_) p->deallocate_future(); @@ -655,4 +656,4 @@ public: # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_FIBERS_DETAIL_FUTURE_BASE_H +#endif // BOOST_FIBERS_DETAIL_SHARED_STATE_H diff --git a/include/boost/fiber/future/detail/future_object.hpp b/include/boost/fiber/future/detail/shared_state_object.hpp similarity index 64% rename from include/boost/fiber/future/detail/future_object.hpp rename to include/boost/fiber/future/detail/shared_state_object.hpp index 62004bde..912bb590 100644 --- a/include/boost/fiber/future/detail/future_object.hpp +++ b/include/boost/fiber/future/detail/shared_state_object.hpp @@ -4,13 +4,13 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_FIBERS_DETAIL_FUTURE_OBJECT_H -#define BOOST_FIBERS_DETAIL_FUTURE_OBJECT_H +#ifndef BOOST_FIBERS_DETAIL_SHARED_STATE_OBJECT_H +#define BOOST_FIBERS_DETAIL_SHARED_STATE_OBJECT_H #include #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -21,15 +21,15 @@ namespace fibers { namespace detail { template< typename R, typename Allocator > -class future_object : public future_base< R > +class shared_state_object : public shared_state< R > { public: typedef typename Allocator::template rebind< - future_object< R, Allocator > + shared_state_object< R, Allocator > >::other allocator_t; - future_object( allocator_t const& alloc) : - future_base< R >(), alloc_( alloc) + shared_state_object( allocator_t const& alloc) : + shared_state< R >(), alloc_( alloc) {} protected: @@ -39,7 +39,7 @@ protected: private: allocator_t alloc_; - static void destroy_( allocator_t & alloc, future_object * p) + static void destroy_( allocator_t & alloc, shared_state_object * p) { alloc.destroy( p); alloc.deallocate( p, 1); @@ -52,4 +52,4 @@ private: # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_FIBERS_DETAIL_FUTURE_BASE_H +#endif // BOOST_FIBERS_DETAIL_SHARED_STATE_OBJECT_H diff --git a/include/boost/fiber/future/detail/task_base.hpp b/include/boost/fiber/future/detail/task_base.hpp index f445a3d6..eb5a54ec 100644 --- a/include/boost/fiber/future/detail/task_base.hpp +++ b/include/boost/fiber/future/detail/task_base.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -26,7 +26,7 @@ namespace fibers { namespace detail { template< typename R > -struct task_base : public future_base< R > +struct task_base : public shared_state< R > { typedef intrusive_ptr< task_base > ptr_t; @@ -41,4 +41,4 @@ struct task_base : public future_base< R > # include BOOST_ABI_SUFFIX #endif -#endif // BOOST_FIBERS_DETAIL_future_base_H +#endif // BOOST_FIBERS_DETAIL_shared_state_H diff --git a/include/boost/fiber/future/future.hpp b/include/boost/fiber/future/future.hpp index 83f95207..521fc7e8 100644 --- a/include/boost/fiber/future/future.hpp +++ b/include/boost/fiber/future/future.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include namespace boost { @@ -34,7 +34,7 @@ template< typename R > class future : private noncopyable { private: - typedef typename detail::future_base< R >::ptr_t ptr_t; + typedef typename detail::shared_state< R >::ptr_t ptr_t; friend class packaged_task< R() >; friend class promise< R >; @@ -45,17 +45,17 @@ private: typedef void ( dummy::*safe_bool)(); - ptr_t future_; + ptr_t state_; BOOST_MOVABLE_BUT_NOT_COPYABLE( future); future( ptr_t const& p) : - future_( p) + state_( p) {} public: future() BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with no shared state // after construction, valid() == false @@ -68,7 +68,7 @@ public: #ifndef BOOST_NO_RVALUE_REFERENCES future( future && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with the shared state of other using move semantics // after construction, other.valid() == false @@ -86,7 +86,7 @@ public: } #else future( BOOST_RV_REF( future< R >) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with the shared state of other using move semantics // after construction, other.valid() == false @@ -107,7 +107,7 @@ public: void swap( future & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two futures - future_.swap( other.future_); + state_.swap( other.state_); } operator safe_bool() const BOOST_NOEXCEPT @@ -122,7 +122,7 @@ public: // this is the case only for futures returned by // promise::get_future(), packaged_task::get_future() // or async() until the first time get()or share() is called - return 0 != future_.get(); + return 0 != state_.get(); } shared_future< R > share(); @@ -142,7 +142,7 @@ public: boost::throw_exception( future_uninitialized() ); ptr_t tmp; - tmp.swap( future_); + tmp.swap( state_); return tmp->get(); } @@ -153,7 +153,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - future_->wait(); + state_->wait(); } template< class Rep, class Period > @@ -164,7 +164,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_for( timeout_duration); + return state_->wait_for( timeout_duration); } future_status wait_until( clock_type::time_point const& timeout_time) const @@ -174,7 +174,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_until( timeout_time); + return state_->wait_until( timeout_time); } }; @@ -182,7 +182,7 @@ template< typename R > class future< R & > : private noncopyable { private: - typedef typename detail::future_base< R & >::ptr_t ptr_t; + typedef typename detail::shared_state< R & >::ptr_t ptr_t; friend class packaged_task< R&() >; friend class promise< R & >; @@ -193,17 +193,17 @@ private: typedef void ( dummy::*safe_bool)(); - ptr_t future_; + ptr_t state_; BOOST_MOVABLE_BUT_NOT_COPYABLE( future); future( ptr_t const& p) : - future_( p) + state_( p) {} public: future() BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with no shared state // after construction, valid() == false @@ -216,7 +216,7 @@ public: #ifndef BOOST_NO_RVALUE_REFERENCES future( future && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with the shared state of other using move semantics // after construction, other.valid() == false @@ -234,7 +234,7 @@ public: } #else future( BOOST_RV_REF( future< R & >) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with the shared state of other using move semantics // after construction, other.valid() == false @@ -255,7 +255,7 @@ public: void swap( future & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two futures - future_.swap( other.future_); + state_.swap( other.state_); } operator safe_bool() const BOOST_NOEXCEPT @@ -270,7 +270,7 @@ public: // this is the case only for futures returned by // promise::get_future(), packaged_task::get_future() // or async() until the first time get()or share() is called - return 0 != future_.get(); + return 0 != state_.get(); } shared_future< R & > share(); @@ -290,7 +290,7 @@ public: boost::throw_exception( future_uninitialized() ); ptr_t tmp; - tmp.swap( future_); + tmp.swap( state_); return tmp->get(); } @@ -301,7 +301,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - future_->wait(); + state_->wait(); } template< class Rep, class Period > @@ -312,7 +312,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_for( timeout_duration); + return state_->wait_for( timeout_duration); } future_status wait_until( clock_type::time_point const& timeout_time) const @@ -322,7 +322,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_until( timeout_time); + return state_->wait_until( timeout_time); } }; @@ -330,7 +330,7 @@ template<> class future< void > : private noncopyable { private: - typedef detail::future_base< void >::ptr_t ptr_t; + typedef detail::shared_state< void >::ptr_t ptr_t; friend class packaged_task< void() >; friend class promise< void >; @@ -341,17 +341,17 @@ private: typedef void ( dummy::*safe_bool)(); - ptr_t future_; + ptr_t state_; BOOST_MOVABLE_BUT_NOT_COPYABLE( future); future( ptr_t const& p) : - future_( p) + state_( p) {} public: future() BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with no shared state // after construction, valid() == false @@ -364,7 +364,7 @@ public: #ifndef BOOST_NO_RVALUE_REFERENCES future( future && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with the shared state of other using move semantics // after construction, other.valid() == false @@ -382,7 +382,7 @@ public: } #else future( BOOST_RV_REF( future< void >) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a future with the shared state of other using move semantics // after construction, other.valid() == false @@ -403,7 +403,7 @@ public: void swap( future & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two futures - future_.swap( other.future_); + state_.swap( other.state_); } operator safe_bool() const BOOST_NOEXCEPT @@ -418,7 +418,7 @@ public: // this is the case only for futures returned by // promise::get_future(), packaged_task::get_future() // or async() until the first time get()or share() is called - return 0 != future_.get(); + return 0 != state_.get(); } shared_future< void > share(); @@ -438,7 +438,7 @@ public: boost::throw_exception( future_uninitialized() ); ptr_t tmp; - tmp.swap( future_); + tmp.swap( state_); tmp->get(); } @@ -449,7 +449,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - future_->wait(); + state_->wait(); } template< class Rep, class Period > @@ -460,7 +460,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_for( timeout_duration); + return state_->wait_for( timeout_duration); } future_status wait_until( clock_type::time_point const& timeout_time) const @@ -470,7 +470,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_until( timeout_time); + return state_->wait_until( timeout_time); } }; @@ -484,7 +484,7 @@ template< typename R > class shared_future { private: - typedef typename detail::future_base< R >::ptr_t ptr_t; + typedef typename detail::shared_state< R >::ptr_t ptr_t; friend class future< R >; @@ -493,15 +493,15 @@ private: typedef void ( dummy::*safe_bool)(); - ptr_t future_; + ptr_t state_; explicit shared_future( ptr_t const& p) : - future_( p) + state_( p) {} public: shared_future() BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with no shared state // after construction, valid() == false @@ -514,7 +514,7 @@ public: } shared_future( shared_future const& other) : - future_( other.future_) + state_( other.state_) { //TODO: constructs a shared future that refers to the same shared state, // as other, if there's any @@ -522,15 +522,15 @@ public: #ifndef BOOST_NO_RVALUE_REFERENCES shared_future( future< R > && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false - future_.swap( other.future_); + state_.swap( other.state_); } shared_future( shared_future && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false @@ -548,15 +548,15 @@ public: } #else shared_future( BOOST_RV_REF( future< R >) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false - future_.swap( other.future_); + state_.swap( other.state_); } shared_future( BOOST_RV_REF( shared_future) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false @@ -593,7 +593,7 @@ public: void swap( shared_future & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two shared_futures - future_.swap( other.future_); + state_.swap( other.state_); } operator safe_bool() const BOOST_NOEXCEPT @@ -608,7 +608,7 @@ public: // this is the case only for shared_futures returned by // promise::get_shared_future(), packaged_task::get_shared_future() // or async() until the first time get()or share() is called - return 0 != future_.get(); + return 0 != state_.get(); } R get() @@ -626,7 +626,7 @@ public: boost::throw_exception( future_uninitialized() ); ptr_t tmp; - tmp.swap( future_); + tmp.swap( state_); return tmp->get(); } @@ -637,7 +637,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - future_->wait(); + state_->wait(); } template< class Rep, class Period > @@ -648,7 +648,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_for( timeout_duration); + return state_->wait_for( timeout_duration); } future_status wait_until( clock_type::time_point const& timeout_time) const @@ -658,7 +658,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_until( timeout_time); + return state_->wait_until( timeout_time); } }; @@ -666,7 +666,7 @@ template< typename R > class shared_future< R & > { private: - typedef typename detail::future_base< R & >::ptr_t ptr_t; + typedef typename detail::shared_state< R & >::ptr_t ptr_t; friend class future< R & >; @@ -675,15 +675,15 @@ private: typedef void ( dummy::*safe_bool)(); - ptr_t future_; + ptr_t state_; explicit shared_future( ptr_t const& p) : - future_( p) + state_( p) {} public: shared_future() BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with no shared state // after construction, valid() == false @@ -696,7 +696,7 @@ public: } shared_future( shared_future const& other) : - future_( other.future_) + state_( other.state_) { //TODO: constructs a shared future that refers to the same shared state, // as other, if there's any @@ -704,15 +704,15 @@ public: #ifndef BOOST_NO_RVALUE_REFERENCES shared_future( future< R & > && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false - future_.swap( other.future_); + state_.swap( other.state_); } shared_future( shared_future && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false @@ -730,15 +730,15 @@ public: } #else shared_future( BOOST_RV_REF( future< R & >) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false - future_.swap( other.future_); + state_.swap( other.state_); } shared_future( BOOST_RV_REF( shared_future) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false @@ -775,7 +775,7 @@ public: void swap( shared_future & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two shared_futures - future_.swap( other.future_); + state_.swap( other.state_); } operator safe_bool() const BOOST_NOEXCEPT @@ -790,7 +790,7 @@ public: // this is the case only for shared_futures returned by // promise::get_shared_future(), packaged_task::get_shared_future() // or async() until the first time get()or share() is called - return 0 != future_.get(); + return 0 != state_.get(); } R & get() @@ -808,7 +808,7 @@ public: boost::throw_exception( future_uninitialized() ); ptr_t tmp; - tmp.swap( future_); + tmp.swap( state_); return tmp->get(); } @@ -819,7 +819,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - future_->wait(); + state_->wait(); } template< class Rep, class Period > @@ -830,7 +830,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_for( timeout_duration); + return state_->wait_for( timeout_duration); } future_status wait_until( clock_type::time_point const& timeout_time) const @@ -840,7 +840,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_until( timeout_time); + return state_->wait_until( timeout_time); } }; @@ -848,7 +848,7 @@ template<> class shared_future< void > { private: - typedef detail::future_base< void >::ptr_t ptr_t; + typedef detail::shared_state< void >::ptr_t ptr_t; friend class future< void >; @@ -857,15 +857,15 @@ private: typedef void ( dummy::*safe_bool)(); - ptr_t future_; + ptr_t state_; shared_future( ptr_t const& p) : - future_( p) + state_( p) {} public: shared_future() BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with no shared state // after construction, valid() == false @@ -878,7 +878,7 @@ public: } shared_future( shared_future const& other) : - future_( other.future_) + state_( other.state_) { //TODO: constructs a shared future that refers to the same shared state, // as other, if there's any @@ -886,15 +886,15 @@ public: #ifndef BOOST_NO_RVALUE_REFERENCES shared_future( future< void > && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false - future_.swap( other.future_); + state_.swap( other.state_); } shared_future( shared_future && other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false @@ -912,15 +912,15 @@ public: } #else shared_future( BOOST_RV_REF( future< void >) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false - future_.swap( other.future_); + state_.swap( other.state_); } shared_future( BOOST_RV_REF( shared_future) other) BOOST_NOEXCEPT : - future_() + state_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false @@ -957,13 +957,13 @@ public: void swap( future< void > & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two shared_futures - future_.swap( other.future_); + state_.swap( other.state_); } void swap( shared_future & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two shared_futures - future_.swap( other.future_); + state_.swap( other.state_); } operator safe_bool() const BOOST_NOEXCEPT @@ -978,7 +978,7 @@ public: // this is the case only for shared_futures returned by // promise::get_shared_future(), packaged_task::get_shared_future() // or async() until the first time get()or share() is called - return 0 != future_.get(); + return 0 != state_.get(); } void get() @@ -996,7 +996,7 @@ public: boost::throw_exception( future_uninitialized() ); ptr_t tmp; - tmp.swap( future_); + tmp.swap( state_); tmp->get(); } @@ -1007,7 +1007,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - future_->wait(); + state_->wait(); } template< class Rep, class Period > @@ -1018,7 +1018,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_for( timeout_duration); + return state_->wait_for( timeout_duration); } future_status wait_until( clock_type::time_point const& timeout_time) const @@ -1028,7 +1028,7 @@ public: if ( ! valid() ) boost::throw_exception( future_uninitialized() ); - return future_->wait_until( timeout_time); + return state_->wait_until( timeout_time); } }; diff --git a/include/boost/fiber/future/promise.hpp b/include/boost/fiber/future/promise.hpp index f5b6b96e..99ed2175 100644 --- a/include/boost/fiber/future/promise.hpp +++ b/include/boost/fiber/future/promise.hpp @@ -16,8 +16,8 @@ #include #include -#include -#include +#include +#include #include namespace boost { @@ -27,7 +27,7 @@ template< typename R > class promise : private noncopyable { private: - typedef typename detail::future_base< R >::ptr_t ptr_t; + typedef typename detail::shared_state< R >::ptr_t ptr_t; struct dummy { void nonnull() {} }; @@ -47,7 +47,7 @@ public: // TODO: constructs the promise with an empty shared state // the shared state is allocated using alloc // alloc must meet the requirements of Allocator - typedef detail::future_object< + typedef detail::shared_state_object< R, std::allocator< promise< R > > > object_t; std::allocator< promise< R > > alloc; @@ -65,7 +65,7 @@ public: // TODO: constructs the promise with an empty shared state // the shared state is allocated using alloc // alloc must meet the requirements of Allocator - typedef detail::future_object< R, Allocator > object_t; + typedef detail::shared_state_object< R, Allocator > object_t; typename object_t::allocator_t a( alloc); future_ = ptr_t( // placement new @@ -208,7 +208,7 @@ template< typename R > class promise< R & > : private noncopyable { private: - typedef typename detail::future_base< R & >::ptr_t ptr_t; + typedef typename detail::shared_state< R & >::ptr_t ptr_t; struct dummy { void nonnull() {} }; @@ -228,7 +228,7 @@ public: // TODO: constructs the promise with an empty shared state // the shared state is allocated using alloc // alloc must meet the requirements of Allocator - typedef detail::future_object< + typedef detail::shared_state_object< R &, std::allocator< promise< R & > > > object_t; std::allocator< promise< R > > alloc; @@ -246,7 +246,7 @@ public: // TODO: constructs the promise with an empty shared state // the shared state is allocated using alloc // alloc must meet the requirements of Allocator - typedef detail::future_object< R &, Allocator > object_t; + typedef detail::shared_state_object< R &, Allocator > object_t; typename object_t::allocator_t a( alloc); future_ = ptr_t( // placement new @@ -361,7 +361,7 @@ template<> class promise< void > : private noncopyable { private: - typedef detail::future_base< void >::ptr_t ptr_t; + typedef detail::shared_state< void >::ptr_t ptr_t; struct dummy { void nonnull() {} }; @@ -381,7 +381,7 @@ public: // TODO: constructs the promise with an empty shared state // the shared state is allocated using alloc // alloc must meet the requirements of Allocator - typedef detail::future_object< + typedef detail::shared_state_object< void, std::allocator< promise< void > > > object_t; std::allocator< promise< void > > alloc; @@ -399,7 +399,7 @@ public: // TODO: constructs the promise with an empty shared state // the shared state is allocated using alloc // alloc must meet the requirements of Allocator - typedef detail::future_object< void, Allocator > object_t; + typedef detail::shared_state_object< void, Allocator > object_t; #if BOOST_MSVC object_t::allocator_t a( alloc); #else diff --git a/src/detail/spinlock.cpp b/src/detail/spinlock.cpp index 38b4a8d7..38ebd7b3 100644 --- a/src/detail/spinlock.cpp +++ b/src/detail/spinlock.cpp @@ -22,6 +22,7 @@ spinlock::spinlock() : void spinlock::lock() { + bool is_fiber = 0 != scheduler::instance()->active().get(); for (;;) { // access to CPU's cache @@ -30,7 +31,7 @@ spinlock::lock() while ( LOCKED == state_) { // busy-wait - if ( scheduler::instance()->active() ) + if ( is_fiber) scheduler::instance()->yield(); else this_thread::yield(); diff --git a/src/mutex.cpp b/src/mutex.cpp index ffbbfdc0..f56bfda0 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -53,6 +53,7 @@ mutex::lock() } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); // suspend this fiber @@ -61,11 +62,11 @@ mutex::lock() } else { - // local notification for main-fiber - n = detail::scheduler::instance()->get_main_notifier(); - for (;;) { + // local notification for main-fiber + n = detail::scheduler::instance()->get_main_notifier(); + unique_lock< detail::spinlock > lk( splk_); if ( UNLOCKED == state_) @@ -77,6 +78,7 @@ mutex::lock() } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); lk.unlock(); diff --git a/src/recursive_mutex.cpp b/src/recursive_mutex.cpp index 00404b95..a58065d1 100644 --- a/src/recursive_mutex.cpp +++ b/src/recursive_mutex.cpp @@ -61,6 +61,7 @@ recursive_mutex::lock() } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); // suspend this fiber @@ -69,11 +70,11 @@ recursive_mutex::lock() } else { - // local notification for main-fiber - n = detail::scheduler::instance()->get_main_notifier(); - for (;;) { + // local notification for main-fiber + n = detail::scheduler::instance()->get_main_notifier(); + unique_lock< detail::spinlock > lk( splk_); if ( UNLOCKED == state_) @@ -91,6 +92,7 @@ recursive_mutex::lock() } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); lk.unlock(); diff --git a/src/recursive_timed_mutex.cpp b/src/recursive_timed_mutex.cpp index 8e46b144..39fcd7ed 100644 --- a/src/recursive_timed_mutex.cpp +++ b/src/recursive_timed_mutex.cpp @@ -61,6 +61,7 @@ recursive_timed_mutex::lock() } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); // suspend this fiber @@ -69,11 +70,11 @@ recursive_timed_mutex::lock() } else { - // local notification for main-fiber - n = detail::scheduler::instance()->get_main_notifier(); - for (;;) { + // local notification for main-fiber + n = detail::scheduler::instance()->get_main_notifier(); + unique_lock< detail::spinlock > lk( splk_); if ( UNLOCKED == state_) @@ -91,6 +92,7 @@ recursive_timed_mutex::lock() } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); lk.unlock(); @@ -157,6 +159,7 @@ recursive_timed_mutex::try_lock_until( clock_type::time_point const& timeout_tim } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); // suspend this fiber until notified or timed-out @@ -173,11 +176,11 @@ recursive_timed_mutex::try_lock_until( clock_type::time_point const& timeout_tim } else { - // local notification for main-fiber - n = detail::scheduler::instance()->get_main_notifier(); - for (;;) { + // local notification for main-fiber + n = detail::scheduler::instance()->get_main_notifier(); + unique_lock< detail::spinlock > lk( splk_); if ( clock_type::now() > timeout_time) @@ -198,6 +201,7 @@ recursive_timed_mutex::try_lock_until( clock_type::time_point const& timeout_tim } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); lk.unlock(); diff --git a/src/timed_mutex.cpp b/src/timed_mutex.cpp index e07542ed..458863bc 100644 --- a/src/timed_mutex.cpp +++ b/src/timed_mutex.cpp @@ -53,6 +53,7 @@ timed_mutex::lock() } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); // suspend this fiber @@ -61,11 +62,11 @@ timed_mutex::lock() } else { - // local notification for main-fiber - n = detail::scheduler::instance()->get_main_notifier(); - for (;;) { + // local notification for main-fiber + n = detail::scheduler::instance()->get_main_notifier(); + unique_lock< detail::spinlock > lk( splk_); if ( UNLOCKED == state_) @@ -77,6 +78,7 @@ timed_mutex::lock() } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); lk.unlock(); @@ -131,6 +133,7 @@ timed_mutex::try_lock_until( clock_type::time_point const& timeout_time) } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); // suspend this fiber until notified or timed-out @@ -147,11 +150,11 @@ timed_mutex::try_lock_until( clock_type::time_point const& timeout_time) } else { - // local notification for main-fiber - n = detail::scheduler::instance()->get_main_notifier(); - for (;;) { + // local notification for main-fiber + n = detail::scheduler::instance()->get_main_notifier(); + unique_lock< detail::spinlock > lk( splk_); if ( clock_type::now() > timeout_time) @@ -166,6 +169,7 @@ timed_mutex::try_lock_until( clock_type::time_point const& timeout_time) } // store this fiber in order to be notified later + BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), n) ); waiting_.push_back( n); lk.unlock(); diff --git a/test/test_futures_mt.cpp b/test/test_futures_mt.cpp index 6ce244bc..17fbabb4 100644 --- a/test/test_futures_mt.cpp +++ b/test/test_futures_mt.cpp @@ -16,22 +16,24 @@ #include #include +boost::fibers::packaged_task< int() > pt; + int fn( int i) { return i; } -void exec( boost::shared_ptr< boost::fibers::packaged_task< int() > > pt) +void exec() { - boost::fibers::fiber f( boost::move( * pt) ); - f.join(); + boost::fibers::round_robin rr; + boost::fibers::set_scheduling_algorithm( & rr); + boost::fibers::fiber( boost::move( pt) ).join(); } boost::fibers::future< int > async( int i) { - boost::shared_ptr< boost::fibers::packaged_task< int() > > pt( - new boost::fibers::packaged_task< int() >( - boost::bind( fn, i) ) ); - boost::fibers::future< int > f( pt->get_future() ); - boost::thread( boost::bind( exec, pt) ).detach(); + boost::fibers::packaged_task< int() > tmp( boost::bind( fn, i) ); + boost::fibers::future< int > f( tmp.get_future() ); + pt = boost::move( tmp); + boost::thread( boost::bind( exec) ).detach(); return boost::move( f); }