| #ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP |
| #define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP |
| // 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) |
| // (C) Copyright 2007-10 Anthony Williams |
| |
| #include "timespec.hpp" |
| #include "pthread_mutex_scoped_lock.hpp" |
| #include "thread_data.hpp" |
| #include "condition_variable_fwd.hpp" |
| |
| #include <boost/config/abi_prefix.hpp> |
| |
| namespace boost |
| { |
| namespace this_thread |
| { |
| void BOOST_THREAD_DECL interruption_point(); |
| } |
| |
| namespace thread_cv_detail |
| { |
| template<typename MutexType> |
| struct lock_on_exit |
| { |
| MutexType* m; |
| |
| lock_on_exit(): |
| m(0) |
| {} |
| |
| void activate(MutexType& m_) |
| { |
| m_.unlock(); |
| m=&m_; |
| } |
| ~lock_on_exit() |
| { |
| if(m) |
| { |
| m->lock(); |
| } |
| } |
| }; |
| } |
| |
| inline void condition_variable::wait(unique_lock<mutex>& m) |
| { |
| thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; |
| detail::interruption_checker check_for_interruption(&internal_mutex,&cond); |
| guard.activate(m); |
| int const res=pthread_cond_wait(&cond,&internal_mutex); |
| BOOST_ASSERT(!res); |
| this_thread::interruption_point(); |
| } |
| |
| inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until) |
| { |
| thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; |
| detail::interruption_checker check_for_interruption(&internal_mutex,&cond); |
| guard.activate(m); |
| struct timespec const timeout=detail::get_timespec(wait_until); |
| int const cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); |
| this_thread::interruption_point(); |
| if(cond_res==ETIMEDOUT) |
| { |
| return false; |
| } |
| BOOST_ASSERT(!cond_res); |
| return true; |
| } |
| |
| inline void condition_variable::notify_one() |
| { |
| boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); |
| BOOST_VERIFY(!pthread_cond_signal(&cond)); |
| } |
| |
| inline void condition_variable::notify_all() |
| { |
| boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); |
| BOOST_VERIFY(!pthread_cond_broadcast(&cond)); |
| } |
| |
| class condition_variable_any |
| { |
| pthread_mutex_t internal_mutex; |
| pthread_cond_t cond; |
| |
| condition_variable_any(condition_variable_any&); |
| condition_variable_any& operator=(condition_variable_any&); |
| |
| public: |
| condition_variable_any() |
| { |
| int const res=pthread_mutex_init(&internal_mutex,NULL); |
| if(res) |
| { |
| boost::throw_exception(thread_resource_error()); |
| } |
| int const res2=pthread_cond_init(&cond,NULL); |
| if(res2) |
| { |
| BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); |
| boost::throw_exception(thread_resource_error()); |
| } |
| } |
| ~condition_variable_any() |
| { |
| BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); |
| BOOST_VERIFY(!pthread_cond_destroy(&cond)); |
| } |
| |
| template<typename lock_type> |
| void wait(lock_type& m) |
| { |
| 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_wait(&cond,&internal_mutex); |
| this_thread::interruption_point(); |
| } |
| if(res) |
| { |
| boost::throw_exception(condition_error()); |
| } |
| } |
| |
| template<typename lock_type,typename predicate_type> |
| void wait(lock_type& m,predicate_type pred) |
| { |
| while(!pred()) wait(m); |
| } |
| |
| template<typename lock_type> |
| 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; |
| } |
| template<typename lock_type> |
| bool timed_wait(lock_type& m,xtime const& wait_until) |
| { |
| return timed_wait(m,system_time(wait_until)); |
| } |
| |
| template<typename lock_type,typename duration_type> |
| bool timed_wait(lock_type& m,duration_type const& wait_duration) |
| { |
| return timed_wait(m,get_system_time()+wait_duration); |
| } |
| |
| template<typename lock_type,typename predicate_type> |
| bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred) |
| { |
| while (!pred()) |
| { |
| if(!timed_wait(m, wait_until)) |
| return pred(); |
| } |
| return true; |
| } |
| |
| template<typename lock_type,typename predicate_type> |
| bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred) |
| { |
| return timed_wait(m,system_time(wait_until),pred); |
| } |
| |
| template<typename lock_type,typename duration_type,typename predicate_type> |
| bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) |
| { |
| return timed_wait(m,get_system_time()+wait_duration,pred); |
| } |
| |
| void notify_one() |
| { |
| boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); |
| BOOST_VERIFY(!pthread_cond_signal(&cond)); |
| } |
| |
| void notify_all() |
| { |
| boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); |
| BOOST_VERIFY(!pthread_cond_broadcast(&cond)); |
| } |
| }; |
| |
| } |
| |
| #include <boost/config/abi_suffix.hpp> |
| |
| #endif |