summaryrefslogtreecommitdiff
path: root/boost/thread/pthread/condition_variable.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread/pthread/condition_variable.hpp')
-rw-r--r--boost/thread/pthread/condition_variable.hpp171
1 files changed, 140 insertions, 31 deletions
diff --git a/boost/thread/pthread/condition_variable.hpp b/boost/thread/pthread/condition_variable.hpp
index 48ed8ff731..aa7100766e 100644
--- a/boost/thread/pthread/condition_variable.hpp
+++ b/boost/thread/pthread/condition_variable.hpp
@@ -4,11 +4,17 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-10 Anthony Williams
+// (C) Copyright 2011 Vicente J. Botet Escriba
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/pthread/thread_data.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -59,18 +65,22 @@ namespace boost
this_thread::interruption_point();
if(res)
{
- boost::throw_exception(condition_error());
+ boost::throw_exception(condition_error(res, "boost:: condition_variable constructor failed in pthread_cond_wait"));
}
}
- inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
+ inline bool condition_variable::do_timed_wait(
+ unique_lock<mutex>& m,
+ struct timespec const &timeout)
{
+ if (!m.owns_lock())
+ boost::throw_exception(condition_error(EPERM, "condition_variable do_timed_wait: mutex not locked"));
+
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
int cond_res;
{
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
- struct timespec const timeout=detail::get_timespec(wait_until);
cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
this_thread::interruption_point();
@@ -80,18 +90,18 @@ namespace boost
}
if(cond_res)
{
- boost::throw_exception(condition_error());
+ boost::throw_exception(condition_error(cond_res, "condition_variable failed in pthread_cond_timedwait"));
}
return true;
}
- inline void condition_variable::notify_one()
+ inline void condition_variable::notify_one() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
- inline void condition_variable::notify_all()
+ inline void condition_variable::notify_all() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
@@ -102,22 +112,20 @@ namespace boost
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
- condition_variable_any(condition_variable_any&);
- condition_variable_any& operator=(condition_variable_any&);
-
public:
+ BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_cond_init"));
}
}
~condition_variable_any()
@@ -139,7 +147,7 @@ namespace boost
this_thread::interruption_point();
if(res)
{
- boost::throw_exception(condition_error());
+ boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_wait"));
}
}
@@ -153,23 +161,7 @@ namespace boost
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
struct timespec const timeout=detail::get_timespec(wait_until);
- int res=0;
- {
- thread_cv_detail::lock_on_exit<lock_type> guard;
- detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
- guard.activate(m);
- res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
- }
- this_thread::interruption_point();
- if(res==ETIMEDOUT)
- {
- return false;
- }
- if(res)
- {
- boost::throw_exception(condition_error());
- }
- return true;
+ return do_timed_wait(m, timeout);
}
template<typename lock_type>
bool timed_wait(lock_type& m,xtime const& wait_until)
@@ -206,17 +198,134 @@ namespace boost
return timed_wait(m,get_system_time()+wait_duration,pred);
}
- void notify_one()
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class lock_type,class Duration>
+ cv_status
+ wait_until(
+ lock_type& lock,
+ const chrono::time_point<chrono::system_clock, Duration>& t)
+ {
+ using namespace chrono;
+ typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
+ wait_until(lock,
+ nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
+ return system_clock::now() < t ? cv_status::no_timeout :
+ cv_status::timeout;
+ }
+
+ template <class lock_type, class Clock, class Duration>
+ cv_status
+ wait_until(
+ lock_type& lock,
+ const chrono::time_point<Clock, Duration>& t)
+ {
+ using namespace chrono;
+ system_clock::time_point s_now = system_clock::now();
+ typename Clock::time_point c_now = Clock::now();
+ wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
+ return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
+ }
+
+ template <class lock_type, class Clock, class Duration, class Predicate>
+ bool
+ wait_until(
+ lock_type& lock,
+ const chrono::time_point<Clock, Duration>& t,
+ Predicate pred)
+ {
+ while (!pred())
+ {
+ if (wait_until(lock, t) == cv_status::timeout)
+ return pred();
+ }
+ return true;
+ }
+
+
+ template <class lock_type, class Rep, class Period>
+ cv_status
+ wait_for(
+ lock_type& lock,
+ const chrono::duration<Rep, Period>& d)
+ {
+ using namespace chrono;
+ system_clock::time_point s_now = system_clock::now();
+ steady_clock::time_point c_now = steady_clock::now();
+ wait_until(lock, s_now + ceil<nanoseconds>(d));
+ return steady_clock::now() - c_now < d ? cv_status::no_timeout :
+ cv_status::timeout;
+
+ }
+
+
+ template <class lock_type, class Rep, class Period, class Predicate>
+ bool
+ wait_for(
+ lock_type& lock,
+ const chrono::duration<Rep, Period>& d,
+ Predicate pred)
+ {
+ while (!pred())
+ {
+ if (wait_for(lock, d) == cv_status::timeout)
+ return pred();
+ }
+ return true;
+ }
+
+ template <class lock_type>
+ inline void wait_until(
+ lock_type& lk,
+ chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
+ {
+ using namespace chrono;
+ nanoseconds d = tp.time_since_epoch();
+ timespec ts;
+ seconds s = duration_cast<seconds>(d);
+ ts.tv_sec = static_cast<long>(s.count());
+ ts.tv_nsec = static_cast<long>((d - s).count());
+ do_timed_wait(lk, ts);
+ }
+#endif
+
+ void notify_one() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
- void notify_all()
+ void notify_all() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
+ private: // used by boost::thread::try_join_until
+
+ template <class lock_type>
+ inline bool do_timed_wait(
+ lock_type& m,
+ struct timespec const &timeout)
+ {
+ int res=0;
+ {
+ thread_cv_detail::lock_on_exit<lock_type> guard;
+ detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
+ guard.activate(m);
+ res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
+ }
+ this_thread::interruption_point();
+ if(res==ETIMEDOUT)
+ {
+ return false;
+ }
+ if(res)
+ {
+ boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_timedwait"));
+ }
+ return true;
+ }
+
+
};
}