Chris@16: #ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP Chris@16: #define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // (C) Copyright 2007-8 Anthony Williams Chris@16: // (C) Copyright 2011-2012 Vicente J. Botet Escriba Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: #include Chris@16: #endif Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: #include Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: Chris@16: class condition_variable Chris@16: { Chris@16: private: Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: pthread_mutex_t internal_mutex; Chris@16: #endif Chris@16: pthread_cond_t cond; Chris@16: Chris@16: public: Chris@16: //private: // used by boost::thread::try_join_until Chris@16: Chris@16: inline bool do_wait_until( Chris@16: unique_lock& lock, Chris@16: struct timespec const &timeout); Chris@16: Chris@16: bool do_wait_for( Chris@16: unique_lock& lock, Chris@16: struct timespec const &timeout) Chris@16: { Chris@16: return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now())); Chris@16: } Chris@16: Chris@16: public: Chris@16: BOOST_THREAD_NO_COPYABLE(condition_variable) Chris@16: condition_variable() Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: int const res=pthread_mutex_init(&internal_mutex,NULL); Chris@16: if(res) Chris@16: { Chris@16: boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init")); Chris@16: } Chris@16: #endif Chris@16: int const res2=pthread_cond_init(&cond,NULL); Chris@16: if(res2) Chris@16: { Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); Chris@16: #endif Chris@16: boost::throw_exception(thread_resource_error(res2, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init")); Chris@16: } Chris@16: } Chris@16: ~condition_variable() Chris@16: { Chris@16: int ret; Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: do { Chris@16: ret = pthread_mutex_destroy(&internal_mutex); Chris@16: } while (ret == EINTR); Chris@16: BOOST_ASSERT(!ret); Chris@16: #endif Chris@16: do { Chris@16: ret = pthread_cond_destroy(&cond); Chris@16: } while (ret == EINTR); Chris@16: BOOST_ASSERT(!ret); Chris@16: } Chris@16: Chris@16: void wait(unique_lock& m); Chris@16: Chris@16: template Chris@16: void wait(unique_lock& m,predicate_type pred) Chris@16: { Chris@16: while(!pred()) wait(m); Chris@16: } Chris@16: Chris@16: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: inline bool timed_wait( Chris@16: unique_lock& m, Chris@16: boost::system_time const& abs_time) Chris@16: { Chris@16: #if defined BOOST_THREAD_WAIT_BUG Chris@16: struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG); Chris@16: return do_wait_until(m, timeout); Chris@16: #else Chris@16: struct timespec const timeout=detail::to_timespec(abs_time); Chris@16: return do_wait_until(m, timeout); Chris@16: #endif Chris@16: } Chris@16: bool timed_wait( Chris@16: unique_lock& m, Chris@16: xtime const& abs_time) Chris@16: { Chris@16: return timed_wait(m,system_time(abs_time)); Chris@16: } Chris@16: Chris@16: template Chris@16: bool timed_wait( Chris@16: unique_lock& m, Chris@16: duration_type const& wait_duration) Chris@16: { Chris@16: return timed_wait(m,get_system_time()+wait_duration); Chris@16: } Chris@16: Chris@16: template Chris@16: bool timed_wait( Chris@16: unique_lock& m, Chris@16: boost::system_time const& abs_time,predicate_type pred) Chris@16: { Chris@16: while (!pred()) Chris@16: { Chris@16: if(!timed_wait(m, abs_time)) Chris@16: return pred(); Chris@16: } Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool timed_wait( Chris@16: unique_lock& m, Chris@16: xtime const& abs_time,predicate_type pred) Chris@16: { Chris@16: return timed_wait(m,system_time(abs_time),pred); Chris@16: } Chris@16: Chris@16: template Chris@16: bool timed_wait( Chris@16: unique_lock& m, Chris@16: duration_type const& wait_duration,predicate_type pred) Chris@16: { Chris@16: return timed_wait(m,get_system_time()+wait_duration,pred); Chris@16: } Chris@16: #endif Chris@16: Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: Chris@16: template Chris@16: cv_status Chris@16: wait_until( Chris@16: unique_lock& lock, Chris@16: const chrono::time_point& t) Chris@16: { Chris@16: using namespace chrono; Chris@16: typedef time_point nano_sys_tmpt; Chris@16: wait_until(lock, Chris@16: nano_sys_tmpt(ceil(t.time_since_epoch()))); Chris@16: return system_clock::now() < t ? cv_status::no_timeout : Chris@16: cv_status::timeout; Chris@16: } Chris@16: Chris@16: template Chris@16: cv_status Chris@16: wait_until( Chris@16: unique_lock& lock, Chris@16: const chrono::time_point& t) Chris@16: { Chris@16: using namespace chrono; Chris@16: system_clock::time_point s_now = system_clock::now(); Chris@16: typename Clock::time_point c_now = Clock::now(); Chris@16: wait_until(lock, s_now + ceil(t - c_now)); Chris@16: return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; Chris@16: } Chris@16: Chris@16: template Chris@16: bool Chris@16: wait_until( Chris@16: unique_lock& lock, Chris@16: const chrono::time_point& t, Chris@16: Predicate pred) Chris@16: { Chris@16: while (!pred()) Chris@16: { Chris@16: if (wait_until(lock, t) == cv_status::timeout) Chris@16: return pred(); Chris@16: } Chris@16: return true; Chris@16: } Chris@16: Chris@16: Chris@16: template Chris@16: cv_status Chris@16: wait_for( Chris@16: unique_lock& lock, Chris@16: const chrono::duration& d) Chris@16: { Chris@16: using namespace chrono; Chris@16: system_clock::time_point s_now = system_clock::now(); Chris@16: steady_clock::time_point c_now = steady_clock::now(); Chris@16: wait_until(lock, s_now + ceil(d)); Chris@16: return steady_clock::now() - c_now < d ? cv_status::no_timeout : Chris@16: cv_status::timeout; Chris@16: Chris@16: } Chris@16: Chris@16: Chris@16: template Chris@16: bool Chris@16: wait_for( Chris@16: unique_lock& lock, Chris@16: const chrono::duration& d, Chris@16: Predicate pred) Chris@16: { Chris@16: return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); Chris@16: Chris@16: // while (!pred()) Chris@16: // { Chris@16: // if (wait_for(lock, d) == cv_status::timeout) Chris@16: // return pred(); Chris@16: // } Chris@16: // return true; Chris@16: } Chris@16: #endif Chris@16: Chris@16: #define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE Chris@16: typedef pthread_cond_t* native_handle_type; Chris@16: native_handle_type native_handle() Chris@16: { Chris@16: return &cond; Chris@16: } Chris@16: Chris@16: void notify_one() BOOST_NOEXCEPT; Chris@16: void notify_all() BOOST_NOEXCEPT; Chris@16: Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: inline cv_status wait_until( Chris@16: unique_lock& lk, Chris@16: chrono::time_point tp) Chris@16: { Chris@16: using namespace chrono; Chris@16: nanoseconds d = tp.time_since_epoch(); Chris@16: timespec ts = boost::detail::to_timespec(d); Chris@16: if (do_wait_until(lk, ts)) return cv_status::no_timeout; Chris@16: else return cv_status::timeout; Chris@16: } Chris@16: #endif Chris@16: }; Chris@16: Chris@16: BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk); Chris@16: Chris@16: } Chris@16: Chris@16: Chris@16: #include Chris@16: Chris@16: #endif