#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 |