boost_161_pthread_condition_variable.h
Go to the documentation of this file.
1 #ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
2 #define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 // (C) Copyright 2007-10 Anthony Williams
7 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
8 
9 // make sure we include our backported version first!!
10 // (before the system version might be included via some of the other header files)
12 
13 #include <boost/thread/pthread/timespec.hpp>
14 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
15 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
16 #include <boost/thread/pthread/thread_data.hpp>
17 #endif
18 //#include <boost/thread/pthread/condition_variable_fwd.hpp>
19 #ifdef BOOST_THREAD_USES_CHRONO
20 #include <boost/chrono/system_clocks.hpp>
21 #include <boost/chrono/ceil.hpp>
22 #endif
23 #include <boost/thread/detail/delete.hpp>
24 
25 #include <boost/config/abi_prefix.hpp>
26 
27 namespace boost
28 {
29 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
30  namespace this_thread
31  {
32  void BOOST_THREAD_DECL interruption_point();
33  }
34 #endif
35 
36  namespace thread_cv_detail
37  {
38  template<typename MutexType>
39  struct lock_on_exit
40  {
41  MutexType* m;
42 
44  m(0)
45  {}
46 
47  void activate(MutexType& m_)
48  {
49  m_.unlock();
50  m=&m_;
51  }
53  {
54  if(m)
55  {
56  m->lock();
57  }
58  }
59  };
60  }
61 
62  inline void condition_variable::wait(unique_lock<mutex>& m)
63  {
64 #if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
65  if(! m.owns_lock())
66  {
67  boost::throw_exception(condition_error(-1, "boost::condition_variable::wait() failed precondition mutex not owned"));
68  }
69 #endif
70  int res=0;
71  {
72 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
74  detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
75  pthread_mutex_t* the_mutex = &internal_mutex;
76  guard.activate(m);
77 #else
78  pthread_mutex_t* the_mutex = m.mutex()->native_handle();
79 #endif
80  res = pthread_cond_wait(&cond,the_mutex);
81  }
82 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
83  this_thread::interruption_point();
84 #endif
85  if(res && res != EINTR)
86  {
87  boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait"));
88  }
89  }
90 
92  unique_lock<mutex>& m,
93  struct timespec const &timeout)
94  {
95 #if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
96  if (!m.owns_lock())
97  {
98  boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned"));
99  }
100 #endif
101  int cond_res;
102  {
103 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
105  detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
106  pthread_mutex_t* the_mutex = &internal_mutex;
107  guard.activate(m);
108 #else
109  pthread_mutex_t* the_mutex = m.mutex()->native_handle();
110 #endif
111  cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
112  }
113 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
114  this_thread::interruption_point();
115 #endif
116  if(cond_res==ETIMEDOUT)
117  {
118  return false;
119  }
120  if(cond_res)
121  {
122  boost::throw_exception(condition_error(cond_res, "boost::condition_variable::do_wait_until failed in pthread_cond_timedwait"));
123  }
124  return true;
125  }
126 
127  inline void condition_variable::notify_one() BOOST_NOEXCEPT
128  {
129 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
130  boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
131 #endif
132  BOOST_VERIFY(!pthread_cond_signal(&cond));
133  }
134 
135  inline void condition_variable::notify_all() BOOST_NOEXCEPT
136  {
137 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
138  boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
139 #endif
140  BOOST_VERIFY(!pthread_cond_broadcast(&cond));
141  }
142 
144  {
145  pthread_mutex_t internal_mutex;
146  pthread_cond_t cond;
147 
148  public:
149  BOOST_THREAD_NO_COPYABLE(condition_variable_any)
151  {
152  int const res=pthread_mutex_init(&internal_mutex,NULL);
153  if(res)
154  {
155  boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
156  }
157  int const res2 = detail::monotonic_pthread_cond_init(cond);
158  if(res2)
159  {
160  BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
161  boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init"));
162  }
163  }
165  {
166  BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
167  BOOST_VERIFY(!pthread_cond_destroy(&cond));
168  }
169 
170  template<typename lock_type>
171  void wait(lock_type& m)
172  {
173  int res=0;
174  {
176 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
177  detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
178 #else
179  boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
180 #endif
181  guard.activate(m);
182  res=pthread_cond_wait(&cond,&internal_mutex);
183  }
184 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
185  this_thread::interruption_point();
186 #endif
187  if(res)
188  {
189  boost::throw_exception(condition_error(res, "boost::condition_variable_any::wait() failed in pthread_cond_wait"));
190  }
191  }
192 
193  template<typename lock_type,typename predicate_type>
194  void wait(lock_type& m,predicate_type pred)
195  {
196  while(!pred()) wait(m);
197  }
198 
199 #if defined BOOST_THREAD_USES_DATETIME
200  template<typename lock_type>
201  bool timed_wait(lock_type& m,boost::system_time const& abs_time)
202  {
203  struct timespec const timeout=detail::to_timespec(abs_time);
204  return do_wait_until(m, timeout);
205  }
206  template<typename lock_type>
207  bool timed_wait(lock_type& m,xtime const& abs_time)
208  {
209  return timed_wait(m,system_time(abs_time));
210  }
211 
212  template<typename lock_type,typename duration_type>
213  bool timed_wait(lock_type& m,duration_type const& wait_duration)
214  {
215  return timed_wait(m,get_system_time()+wait_duration);
216  }
217 
218  template<typename lock_type,typename predicate_type>
219  bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
220  {
221  while (!pred())
222  {
223  if(!timed_wait(m, abs_time))
224  return pred();
225  }
226  return true;
227  }
228 
229  template<typename lock_type,typename predicate_type>
230  bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred)
231  {
232  return timed_wait(m,system_time(abs_time),pred);
233  }
234 
235  template<typename lock_type,typename duration_type,typename predicate_type>
236  bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
237  {
238  return timed_wait(m,get_system_time()+wait_duration,pred);
239  }
240 #endif
241 #ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
242 
243 #ifdef BOOST_THREAD_USES_CHRONO
244  template <class lock_type,class Duration>
245  cv_status
246  wait_until(
247  lock_type& lock,
248  const chrono::time_point<chrono::system_clock, Duration>& t)
249  {
250  using namespace chrono;
251  typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
252  wait_until(lock,
253  nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
254  return system_clock::now() < t ? cv_status::no_timeout :
255  cv_status::timeout;
256  }
257 
258  template <class lock_type, class Clock, class Duration>
259  cv_status
260  wait_until(
261  lock_type& lock,
262  const chrono::time_point<Clock, Duration>& t)
263  {
264  using namespace chrono;
265  system_clock::time_point s_now = system_clock::now();
266  typename Clock::time_point c_now = Clock::now();
267  wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
268  return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
269  }
270 
271  template <class lock_type, class Rep, class Period>
272  cv_status
273  wait_for(
274  lock_type& lock,
275  const chrono::duration<Rep, Period>& d)
276  {
277  using namespace chrono;
278  system_clock::time_point s_now = system_clock::now();
279  steady_clock::time_point c_now = steady_clock::now();
280  wait_until(lock, s_now + ceil<nanoseconds>(d));
281  return steady_clock::now() - c_now < d ? cv_status::no_timeout :
282  cv_status::timeout;
283 
284  }
285 
286  template <class lock_type>
287  cv_status wait_until(
288  lock_type& lk,
289  chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
290  {
291  using namespace chrono;
292  nanoseconds d = tp.time_since_epoch();
293  timespec ts = boost::detail::to_timespec(d);
294  if (do_wait_until(lk, ts)) return cv_status::no_timeout;
295  else return cv_status::timeout;
296  }
297 #endif
298 #else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
299 #ifdef BOOST_THREAD_USES_CHRONO
300 
301  template <class lock_type, class Duration>
302  cv_status
303  wait_until(
304  lock_type& lock,
305  const chrono::time_point<chrono::steady_clock, Duration>& t)
306  {
307  using namespace chrono;
308  typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
309  wait_until(lock,
310  nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
311  return steady_clock::now() < t ? cv_status::no_timeout :
312  cv_status::timeout;
313  }
314 
315  template <class lock_type, class Clock, class Duration>
316  cv_status
317  wait_until(
318  lock_type& lock,
319  const chrono::time_point<Clock, Duration>& t)
320  {
321  using namespace chrono;
322  steady_clock::time_point s_now = steady_clock::now();
323  typename Clock::time_point c_now = Clock::now();
324  wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
325  return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
326  }
327 
328  template <class lock_type, class Rep, class Period>
329  cv_status
330  wait_for(
331  lock_type& lock,
332  const chrono::duration<Rep, Period>& d)
333  {
334  using namespace chrono;
335  steady_clock::time_point c_now = steady_clock::now();
336  wait_until(lock, c_now + ceil<nanoseconds>(d));
337  return steady_clock::now() - c_now < d ? cv_status::no_timeout :
338  cv_status::timeout;
339  }
340 
341  template <class lock_type>
342  inline cv_status wait_until(
343  lock_type& lock,
344  chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
345  {
346  using namespace chrono;
347  nanoseconds d = tp.time_since_epoch();
348  timespec ts = boost::detail::to_timespec(d);
349  if (do_wait_until(lock, ts)) return cv_status::no_timeout;
350  else return cv_status::timeout;
351  }
352 
353 #endif
354 #endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
355 
356 #ifdef BOOST_THREAD_USES_CHRONO
357  template <class lock_type, class Clock, class Duration, class Predicate>
358  bool
359  wait_until(
360  lock_type& lock,
361  const chrono::time_point<Clock, Duration>& t,
362  Predicate pred)
363  {
364  while (!pred())
365  {
366  if (wait_until(lock, t) == cv_status::timeout)
367  return pred();
368  }
369  return true;
370  }
371 
372  template <class lock_type, class Rep, class Period, class Predicate>
373  bool
374  wait_for(
375  lock_type& lock,
376  const chrono::duration<Rep, Period>& d,
377  Predicate pred)
378  {
379  return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
380  }
381 #endif
382 
383  void notify_one() BOOST_NOEXCEPT
384  {
385  boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
386  BOOST_VERIFY(!pthread_cond_signal(&cond));
387  }
388 
389  void notify_all() BOOST_NOEXCEPT
390  {
391  boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
392  BOOST_VERIFY(!pthread_cond_broadcast(&cond));
393  }
394  private: // used by boost::thread::try_join_until
395 
396  template <class lock_type>
398  lock_type& m,
399  struct timespec const &timeout)
400  {
401  int res=0;
402  {
404 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
405  detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
406 #else
407  boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
408 #endif
409  guard.activate(m);
410  res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
411  }
412 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
413  this_thread::interruption_point();
414 #endif
415  if(res==ETIMEDOUT)
416  {
417  return false;
418  }
419  if(res)
420  {
421  boost::throw_exception(condition_error(res, "boost::condition_variable_any::do_wait_until() failed in pthread_cond_timedwait"));
422  }
423  return true;
424  }
425  };
426 
427 }
428 
429 #include <boost/config/abi_suffix.hpp>
430 
431 #endif
d
bool do_wait_until(unique_lock< mutex > &lock, struct timespec const &timeout)
void wait(lock_type &m, predicate_type pred)
int monotonic_pthread_cond_init(pthread_cond_t &cond)
bool do_wait_until(lock_type &m, struct timespec const &timeout)


roscpp
Author(s): Morgan Quigley, Josh Faust, Brian Gerkey, Troy Straszheim
autogenerated on Sun Feb 3 2019 03:29:54