diff options
Diffstat (limited to 'boost/thread')
-rw-r--r-- | boost/thread/concurrent_queues/sync_bounded_queue.hpp | 6 | ||||
-rw-r--r-- | boost/thread/detail/config.hpp | 2 | ||||
-rw-r--r-- | boost/thread/detail/thread.hpp | 26 | ||||
-rw-r--r-- | boost/thread/future.hpp | 36 | ||||
-rw-r--r-- | boost/thread/pthread/condition_variable.hpp | 26 | ||||
-rw-r--r-- | boost/thread/pthread/pthread_mutex_scoped_lock.hpp | 24 | ||||
-rw-r--r-- | boost/thread/pthread/thread_data.hpp | 15 | ||||
-rw-r--r-- | boost/thread/win32/condition_variable.hpp | 81 |
8 files changed, 138 insertions, 78 deletions
diff --git a/boost/thread/concurrent_queues/sync_bounded_queue.hpp b/boost/thread/concurrent_queues/sync_bounded_queue.hpp index e34fa56f37..fd36f8c1a4 100644 --- a/boost/thread/concurrent_queues/sync_bounded_queue.hpp +++ b/boost/thread/concurrent_queues/sync_bounded_queue.hpp @@ -127,7 +127,7 @@ namespace concurrent inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT { if (full(lk)) return capacity(lk); - return ((out_+capacity(lk)-in_) % capacity(lk)); + return ((in_+capacity(lk)-out_) % capacity(lk)); } inline void throw_if_closed(unique_lock<mutex>&); @@ -484,7 +484,9 @@ namespace concurrent queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk) { if (empty(lk) && closed(lk)) {return queue_op_status::closed;} - wait_until_not_empty(lk); + bool is_closed = false; + wait_until_not_empty(lk, is_closed); + if (is_closed) {return queue_op_status::closed;} pull_front(elem, lk); return queue_op_status::success; } diff --git a/boost/thread/detail/config.hpp b/boost/thread/detail/config.hpp index 6d1595ebc7..9eff05f5be 100644 --- a/boost/thread/detail/config.hpp +++ b/boost/thread/detail/config.hpp @@ -12,7 +12,7 @@ #include <boost/detail/workaround.hpp> #include <boost/thread/detail/platform.hpp> -//#define BOOST_THREAD_USEFIXES_TIMESPEC +#define BOOST_THREAD_USEFIXES_TIMESPEC //#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC //#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS // ATTRIBUTE_MAY_ALIAS diff --git a/boost/thread/detail/thread.hpp b/boost/thread/detail/thread.hpp index bd2f149a0e..6424e48385 100644 --- a/boost/thread/detail/thread.hpp +++ b/boost/thread/detail/thread.hpp @@ -155,7 +155,15 @@ namespace boost }; #endif } - +namespace thread_detail { +#ifdef BOOST_THREAD_USES_CHRONO +#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC) + typedef chrono::steady_clock internal_clock_t; +#else + typedef chrono::system_clock internal_clock_t; +#endif +#endif +} class BOOST_THREAD_DECL thread { public: @@ -483,19 +491,13 @@ namespace boost } #endif -#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC) - typedef chrono::steady_clock my_clock_t; -#else - typedef chrono::system_clock my_clock_t; -#endif - template <class Clock, class Duration> bool try_join_until(const chrono::time_point<Clock, Duration>& t) { using namespace chrono; bool joined= false; do { - my_clock_t::time_point s_now = my_clock_t::now(); + thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_clock_t::now(); typename Clock::duration d = ceil<nanoseconds>(t-Clock::now()); if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached joined = try_join_until(s_now + d); @@ -503,10 +505,10 @@ namespace boost return true; } template <class Duration> - bool try_join_until(const chrono::time_point<my_clock_t, Duration>& t) + bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, Duration>& t) { using namespace chrono; - typedef time_point<my_clock_t, nanoseconds> nano_sys_tmpt; + typedef time_point<thread_detail::internal_clock_t, nanoseconds> nano_sys_tmpt; return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); } #endif @@ -521,7 +523,7 @@ namespace boost //} #ifdef BOOST_THREAD_USES_CHRONO - bool try_join_until(const chrono::time_point<my_clock_t, chrono::nanoseconds>& tp) + bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp) { chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); return do_try_join_until(rel_time.count()); @@ -542,7 +544,7 @@ namespace boost } #endif #ifdef BOOST_THREAD_USES_CHRONO - bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) + bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp) { using namespace chrono; nanoseconds d = tp.time_since_epoch(); diff --git a/boost/thread/future.hpp b/boost/thread/future.hpp index 59712c7e2f..7e113e9dee 100644 --- a/boost/thread/future.hpp +++ b/boost/thread/future.hpp @@ -1335,7 +1335,7 @@ namespace boost bool valid() const BOOST_NOEXCEPT { - return future_ != 0 && future_->valid(); + return future_.get() != 0 && future_->valid(); } void wait() const @@ -1639,7 +1639,9 @@ namespace boost base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) { } +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP inline explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION +#endif explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) : base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) @@ -1680,7 +1682,7 @@ namespace boost // retrieving the value move_dest_type get() { - if (this->future_ == 0) + if (this->future_.get() == 0) { boost::throw_exception(future_uninitialized()); } @@ -1700,7 +1702,7 @@ namespace boost get_or(BOOST_THREAD_RV_REF(R2) v) { - if (this->future_ == 0) + if (this->future_.get() == 0) { boost::throw_exception(future_uninitialized()); } @@ -1726,7 +1728,7 @@ namespace boost typename boost::disable_if< is_void<R2>, move_dest_type>::type get_or(R2 const& v) // EXTENSION { - if (this->future_ == 0) + if (this->future_.get() == 0) { boost::throw_exception(future_uninitialized()); } @@ -1941,7 +1943,7 @@ namespace boost // retrieving the value move_dest_type get() { - if (this->future_ == 0) + if (this->future_.get() == 0) { boost::throw_exception(future_uninitialized()); } @@ -1957,7 +1959,7 @@ namespace boost } move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION { - if (this->future_ == 0) + if (this->future_.get() == 0) { boost::throw_exception(future_uninitialized()); } @@ -1976,7 +1978,7 @@ namespace boost move_dest_type get_or(R const& v) // EXTENSION { - if (this->future_ == 0) + if (this->future_.get() == 0) { boost::throw_exception(future_uninitialized()); } @@ -4747,7 +4749,7 @@ namespace detail { inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); // keep state alive as we move ourself but hold the lock shared_ptr<detail::shared_state_base> sentinel(this->future_); @@ -4811,7 +4813,7 @@ namespace detail { inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); // keep state alive as we move ourself but hold the lock shared_ptr<detail::shared_state_base> sentinel(this->future_); @@ -4835,7 +4837,7 @@ namespace detail { return this->then(this->launch_policy(), boost::forward<F>(func)); #else typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); // keep state alive as we move ourself but hold the lock shared_ptr<detail::shared_state_base> sentinel(this->future_); @@ -4865,7 +4867,7 @@ namespace detail { BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { typedef BOOST_THREAD_FUTURE<R2> R; typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); // keep state alive as we move ourself but hold the lock shared_ptr<detail::shared_state_base> sentinel(this->future_); @@ -4939,7 +4941,7 @@ namespace detail { BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { typedef BOOST_THREAD_FUTURE<R2> R; typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); // keep state alive as we move ourself but hold the lock shared_ptr<detail::shared_state_base> sentinel(this->future_); @@ -4965,7 +4967,7 @@ namespace detail { #else typedef BOOST_THREAD_FUTURE<R2> R; typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); // keep state alive as we move ourself but hold the lock shared_ptr<detail::shared_state_base> sentinel(this->future_); @@ -4995,7 +4997,7 @@ namespace detail { shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const { typedef typename boost::result_of<F(shared_future<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); boost::unique_lock<boost::mutex> lock(this->future_->mutex); if (underlying_cast<int>(policy) & int(launch::async)) { @@ -5064,7 +5066,7 @@ namespace detail { shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const { typedef typename boost::result_of<F(shared_future<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); boost::unique_lock<boost::mutex> lock(this->future_->mutex); return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex, @@ -5085,7 +5087,7 @@ namespace detail { return this->then(this->launch_policy(), boost::forward<F>(func)); #else typedef typename boost::result_of<F(shared_future<R>)>::type future_type; - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); boost::unique_lock<boost::mutex> lock(this->future_->mutex); launch policy = this->launch_policy(lock); @@ -5257,7 +5259,7 @@ namespace detail BOOST_THREAD_FUTURE<R2> BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap() { - BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized()); // keep state alive as we move ourself but hold the lock shared_ptr<detail::shared_state_base> sentinel(this->future_); diff --git a/boost/thread/pthread/condition_variable.hpp b/boost/thread/pthread/condition_variable.hpp index 46f49ce842..5dcb3a0e38 100644 --- a/boost/thread/pthread/condition_variable.hpp +++ b/boost/thread/pthread/condition_variable.hpp @@ -45,9 +45,17 @@ namespace boost m_.unlock(); m=&m_; } - ~lock_on_exit() + void deactivate() { - if(m) + if (m) + { + m->lock(); + } + m = 0; + } + ~lock_on_exit() BOOST_NOEXCEPT_IF(false) + { + if (m) { m->lock(); } @@ -70,10 +78,13 @@ namespace boost detail::interruption_checker check_for_interruption(&internal_mutex,&cond); pthread_mutex_t* the_mutex = &internal_mutex; guard.activate(m); + res = pthread_cond_wait(&cond,the_mutex); + check_for_interruption.check(); + guard.deactivate(); #else pthread_mutex_t* the_mutex = m.mutex()->native_handle(); -#endif res = pthread_cond_wait(&cond,the_mutex); +#endif } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); @@ -101,10 +112,13 @@ namespace boost detail::interruption_checker check_for_interruption(&internal_mutex,&cond); pthread_mutex_t* the_mutex = &internal_mutex; guard.activate(m); + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); + check_for_interruption.check(); + guard.deactivate(); #else pthread_mutex_t* the_mutex = m.mutex()->native_handle(); -#endif cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); +#endif } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); @@ -176,6 +190,8 @@ namespace boost #endif guard.activate(m); res=pthread_cond_wait(&cond,&internal_mutex); + check_for_interruption.check(); + guard.deactivate(); } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); @@ -404,6 +420,8 @@ namespace boost #endif guard.activate(m); res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); + check_for_interruption.check(); + guard.deactivate(); } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); diff --git a/boost/thread/pthread/pthread_mutex_scoped_lock.hpp b/boost/thread/pthread/pthread_mutex_scoped_lock.hpp index cdbf8c6740..e3b9990311 100644 --- a/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +++ b/boost/thread/pthread/pthread_mutex_scoped_lock.hpp @@ -1,6 +1,6 @@ #ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP #define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP -// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -20,41 +20,47 @@ namespace boost pthread_mutex_t* m; bool locked; public: - explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_): + explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_) BOOST_NOEXCEPT: m(m_),locked(true) { BOOST_VERIFY(!pthread_mutex_lock(m)); } - void unlock() + void unlock() BOOST_NOEXCEPT { BOOST_VERIFY(!pthread_mutex_unlock(m)); locked=false; } - - ~pthread_mutex_scoped_lock() + void check() BOOST_NOEXCEPT + { + if(locked) + { + unlock(); + } + } + ~pthread_mutex_scoped_lock() BOOST_NOEXCEPT { if(locked) { unlock(); } } - + }; class pthread_mutex_scoped_unlock { pthread_mutex_t* m; public: - explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_): + explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_) BOOST_NOEXCEPT: m(m_) { BOOST_VERIFY(!pthread_mutex_unlock(m)); } - ~pthread_mutex_scoped_unlock() + ~pthread_mutex_scoped_unlock() BOOST_NOEXCEPT { BOOST_VERIFY(!pthread_mutex_lock(m)); } - + }; } } diff --git a/boost/thread/pthread/thread_data.hpp b/boost/thread/pthread/thread_data.hpp index 458bcd5422..836e6927c8 100644 --- a/boost/thread/pthread/thread_data.hpp +++ b/boost/thread/pthread/thread_data.hpp @@ -177,6 +177,7 @@ namespace boost thread_data_base* const thread_info; pthread_mutex_t* m; bool set; + bool done; void check_for_interruption() { @@ -193,7 +194,7 @@ namespace boost public: explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond): thread_info(detail::get_current_thread_data()),m(cond_mutex), - set(thread_info && thread_info->interrupt_enabled) + set(thread_info && thread_info->interrupt_enabled), done(false) { if(set) { @@ -208,9 +209,10 @@ namespace boost BOOST_VERIFY(!pthread_mutex_lock(m)); } } - ~interruption_checker() + void check() { - if(set) + if ( ! done) { + if (set) { BOOST_VERIFY(!pthread_mutex_unlock(m)); lock_guard<mutex> guard(thread_info->data_mutex); @@ -221,6 +223,13 @@ namespace boost { BOOST_VERIFY(!pthread_mutex_unlock(m)); } + done = true; + } + } + + ~interruption_checker() BOOST_NOEXCEPT_IF(false) + { + check(); } }; #endif diff --git a/boost/thread/win32/condition_variable.hpp b/boost/thread/win32/condition_variable.hpp index 23e9e44484..f4b535f74b 100644 --- a/boost/thread/win32/condition_variable.hpp +++ b/boost/thread/win32/condition_variable.hpp @@ -142,32 +142,38 @@ namespace boost struct relocker { BOOST_THREAD_NO_COPYABLE(relocker) - lock_type& lock; - bool unlocked; + lock_type& _lock; + bool _unlocked; relocker(lock_type& lock_): - lock(lock_),unlocked(false) + _lock(lock_), _unlocked(false) {} void unlock() { - lock.unlock(); - unlocked=true; + if ( ! _unlocked ) + { + _lock.unlock(); + _unlocked=true; + } } - ~relocker() + void lock() { - if(unlocked) - { - lock.lock(); - } - + if ( _unlocked ) + { + _lock.lock(); + _unlocked=false; + } + } + ~relocker() BOOST_NOEXCEPT_IF(false) + { + lock(); } }; entry_ptr get_wait_entry() { - boost::lock_guard<boost::mutex> internal_lock(internal_mutex); - + boost::lock_guard<boost::mutex> lk(internal_mutex); if(!wake_sem) { wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); @@ -190,18 +196,32 @@ namespace boost struct entry_manager { - entry_ptr const entry; + entry_ptr entry; boost::mutex& internal_mutex; + BOOST_THREAD_NO_COPYABLE(entry_manager) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + entry_manager(entry_ptr&& entry_, boost::mutex& mutex_): + entry(static_cast< entry_ptr&& >(entry_)), internal_mutex(mutex_) + {} +#else entry_manager(entry_ptr const& entry_, boost::mutex& mutex_): entry(entry_), internal_mutex(mutex_) {} +#endif - ~entry_manager() + void remove_waiter() { + if (entry) { boost::lock_guard<boost::mutex> internal_lock(internal_mutex); entry->remove_waiter(); + entry.reset(); + } + } + ~entry_manager() BOOST_NOEXCEPT_IF(false) + { + remove_waiter(); } list_entry* operator->() @@ -215,23 +235,24 @@ namespace boost template<typename lock_type> bool do_wait(lock_type& lock,timeout abs_time) { - relocker<lock_type> locker(lock); - - entry_manager entry(get_wait_entry(), internal_mutex); - - locker.unlock(); + relocker<lock_type> locker(lock); + entry_manager entry(get_wait_entry(), internal_mutex); + locker.unlock(); - bool woken=false; - while(!woken) - { - if(!entry->wait(abs_time)) - { - return false; - } + bool woken=false; + while(!woken) + { + if(!entry->wait(abs_time)) + { + return false; + } - woken=entry->woken(); - } - return woken; + woken=entry->woken(); + } + // do it here to avoid throwing on the destructor + entry->remove_waiter(); + locker.lock(); + return woken; } template<typename lock_type,typename predicate_type> |