summaryrefslogtreecommitdiff
path: root/boost/thread
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread')
-rw-r--r--boost/thread/concurrent_queues/sync_bounded_queue.hpp6
-rw-r--r--boost/thread/detail/config.hpp2
-rw-r--r--boost/thread/detail/thread.hpp26
-rw-r--r--boost/thread/future.hpp36
-rw-r--r--boost/thread/pthread/condition_variable.hpp26
-rw-r--r--boost/thread/pthread/pthread_mutex_scoped_lock.hpp24
-rw-r--r--boost/thread/pthread/thread_data.hpp15
-rw-r--r--boost/thread/win32/condition_variable.hpp81
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>