34 #ifndef ROSCPP_INTERNAL_CONDITION_VARIABLE_H 35 #define ROSCPP_INTERNAL_CONDITION_VARIABLE_H 37 #include <boost/thread/condition_variable.hpp> 42 #if !defined(BOOST_THREAD_PLATFORM_PTHREAD) || \ 43 defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) || \ 44 defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) 51 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 52 pthread_mutex_t internal_mutex;
59 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 60 res = pthread_mutex_init(&internal_mutex, NULL);
63 boost::throw_exception(boost::thread_resource_error(res,
"ros::internal::condition_variable_monotonic::condition_variable_monotonic() constructor failed in pthread_mutex_init"));
68 pthread_condattr_t attr;
69 res = pthread_condattr_init(&attr);
71 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
72 res = pthread_cond_init(&cond, &attr);
73 pthread_condattr_destroy(&attr);
78 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 79 BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
81 boost::throw_exception(boost::thread_resource_error(res,
"ros::internal::condition_variable_monotonic::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
85 void notify_one() BOOST_NOEXCEPT
87 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 88 boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
90 BOOST_VERIFY(!pthread_cond_signal(&cond));
93 void notify_all() BOOST_NOEXCEPT
95 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 96 boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
98 BOOST_VERIFY(!pthread_cond_broadcast(&cond));
101 template <
class Duration>
102 boost::cv_status wait_until(
103 boost::unique_lock<boost::mutex> &lock,
104 const boost::chrono::time_point<boost::chrono::steady_clock, Duration> &t)
106 typedef boost::chrono::time_point<boost::chrono::steady_clock, boost::chrono::nanoseconds>
109 nano_sys_tmpt(boost::chrono::ceil<boost::chrono::nanoseconds>(t.time_since_epoch())));
110 return boost::chrono::steady_clock::now() < t ?
111 boost::cv_status::no_timeout :
112 boost::cv_status::timeout;
115 template <
class Clock,
class Duration>
116 boost::cv_status wait_until(
117 boost::unique_lock<boost::mutex> &lock,
118 const boost::chrono::time_point<Clock, Duration> &t)
120 boost::chrono::steady_clock::time_point s_now = boost::chrono::steady_clock::now();
121 typename Clock::time_point c_now = Clock::now();
122 wait_until(lock, s_now + boost::chrono::ceil<boost::chrono::nanoseconds>(t - c_now));
123 return Clock::now() < t ? boost::cv_status::no_timeout : boost::cv_status::timeout;
126 template <
class Rep,
class Period>
127 boost::cv_status wait_for(
128 boost::unique_lock<boost::mutex> &lock,
129 const boost::chrono::duration<Rep, Period> &
d)
131 boost::chrono::steady_clock::time_point c_now = boost::chrono::steady_clock::now();
132 wait_until(lock, c_now + boost::chrono::ceil<boost::chrono::nanoseconds>(d));
133 return boost::chrono::steady_clock::now() - c_now < d ?
134 boost::cv_status::no_timeout :
135 boost::cv_status::timeout;
138 boost::cv_status wait_until(
139 boost::unique_lock<boost::mutex> &lk,
140 boost::chrono::time_point<boost::chrono::steady_clock, boost::chrono::nanoseconds> tp)
142 boost::chrono::nanoseconds d = tp.time_since_epoch();
143 timespec ts = boost::detail::to_timespec(d);
144 if (do_wait_until(lk, ts))
145 return boost::cv_status::no_timeout;
147 return boost::cv_status::timeout;
150 void wait(boost::unique_lock<boost::mutex> &m)
154 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 155 boost::thread_cv_detail::lock_on_exit<boost::unique_lock<boost::mutex>> guard;
156 boost::detail::interruption_checker check_for_interruption(&internal_mutex, &cond);
157 pthread_mutex_t *the_mutex = &internal_mutex;
159 res = pthread_cond_wait(&cond, the_mutex);
160 #if BOOST_VERSION >= 106600 161 check_for_interruption.unlock_if_locked();
163 #elif BOOST_VERSION >= 106500 164 check_for_interruption.check();
168 pthread_mutex_t *the_mutex = m.mutex()->native_handle();
169 res = pthread_cond_wait(&cond, the_mutex);
172 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 173 boost::this_thread::interruption_point();
175 if (res && res != EINTR)
177 boost::throw_exception(boost::condition_error(res,
"ros::internal::condition_variable_monotonic::wait failed in pthread_cond_wait"));
182 boost::unique_lock<boost::mutex> &m,
183 struct timespec
const &timeout)
187 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 188 boost::thread_cv_detail::lock_on_exit<boost::unique_lock<boost::mutex>> guard;
189 boost::detail::interruption_checker check_for_interruption(&internal_mutex, &cond);
190 pthread_mutex_t *the_mutex = &internal_mutex;
192 cond_res = pthread_cond_timedwait(&cond, the_mutex, &timeout);
193 #if BOOST_VERSION >= 106600 194 check_for_interruption.unlock_if_locked();
196 #elif BOOST_VERSION >= 106500 197 check_for_interruption.check();
201 pthread_mutex_t *the_mutex = m.mutex()->native_handle();
202 cond_res = pthread_cond_timedwait(&cond, the_mutex, &timeout);
205 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 206 boost::this_thread::interruption_point();
208 if (cond_res == ETIMEDOUT)
214 boost::throw_exception(boost::condition_error(cond_res,
"ros::internal::condition_variable_monotonic::do_wait_until failed in pthread_cond_timedwait"));
221 "sizeof(ros::internal::condition_variable_monotonic) != sizeof(boost::condition_variable)");
228 #endif // ROSCPP_INTERNAL_CONDITION_VARIABLE_H
boost::condition_variable condition_variable_monotonic