annotate DEPENDENCIES/generic/include/boost/thread/pthread/condition_variable.hpp @ 125:34e428693f5d vext

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