condition_variables.qbk 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. [/
  2. (C) Copyright 2007-11 Anthony Williams.
  3. (C) Copyright 2011-12 Vicente J. Botet Escriba.
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt).
  7. ]
  8. [section:condvar_ref Condition Variables]
  9. [heading Synopsis]
  10. namespace boost
  11. {
  12. enum class cv_status;
  13. {
  14. no_timeout,
  15. timeout
  16. };
  17. class condition_variable;
  18. class condition_variable_any;
  19. void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
  20. }
  21. The classes `condition_variable` and `condition_variable_any` provide a
  22. mechanism for one thread to wait for notification from another thread that a
  23. particular condition has become true. The general usage pattern is that one
  24. thread locks a mutex and then calls `wait` on an instance of
  25. `condition_variable` or `condition_variable_any`. When the thread is woken from
  26. the wait, then it checks to see if the appropriate condition is now true, and
  27. continues if so. If the condition is not true, then the thread then calls `wait`
  28. again to resume waiting. In the simplest case, this condition is just a boolean
  29. variable:
  30. boost::condition_variable cond;
  31. boost::mutex mut;
  32. bool data_ready;
  33. void process_data();
  34. void wait_for_data_to_process()
  35. {
  36. boost::unique_lock<boost::mutex> lock(mut);
  37. while(!data_ready)
  38. {
  39. cond.wait(lock);
  40. }
  41. process_data();
  42. }
  43. Notice that the `lock` is passed to `wait`: `wait` will atomically add the
  44. thread to the set of threads waiting on the condition variable, and unlock the
  45. mutex. When the thread is woken, the mutex will be locked again before the call
  46. to `wait` returns. This allows other threads to acquire the mutex in order to
  47. update the shared data, and ensures that the data associated with the condition
  48. is correctly synchronized.
  49. In the mean time, another thread sets the condition to `true`, and then calls
  50. either `notify_one` or `notify_all` on the condition variable to wake one
  51. waiting thread or all the waiting threads respectively.
  52. void retrieve_data();
  53. void prepare_data();
  54. void prepare_data_for_processing()
  55. {
  56. retrieve_data();
  57. prepare_data();
  58. {
  59. boost::lock_guard<boost::mutex> lock(mut);
  60. data_ready=true;
  61. }
  62. cond.notify_one();
  63. }
  64. Note that the same mutex is locked before the shared data is updated, but that
  65. the mutex does not have to be locked across the call to `notify_one`.
  66. This example uses an object of type `condition_variable`, but would work just as
  67. well with an object of type `condition_variable_any`: `condition_variable_any`
  68. is more general, and will work with any kind of lock or mutex, whereas
  69. `condition_variable` requires that the lock passed to `wait` is an instance of
  70. `boost::unique_lock<boost::mutex>`. This enables `condition_variable` to make
  71. optimizations in some cases, based on the knowledge of the mutex type;
  72. `condition_variable_any` typically has a more complex implementation than
  73. `condition_variable`.
  74. [section:condition_variable Class `condition_variable`]
  75. //#include <boost/thread/condition_variable.hpp>
  76. namespace boost
  77. {
  78. class condition_variable
  79. {
  80. public:
  81. condition_variable();
  82. ~condition_variable();
  83. void notify_one() noexcept;
  84. void notify_all() noexcept;
  85. void wait(boost::unique_lock<boost::mutex>& lock);
  86. template<typename predicate_type>
  87. void wait(boost::unique_lock<boost::mutex>& lock,predicate_type predicate);
  88. template <class Clock, class Duration>
  89. typename cv_status::type
  90. wait_until(
  91. unique_lock<mutex>& lock,
  92. const chrono::time_point<Clock, Duration>& t);
  93. template <class Clock, class Duration, class Predicate>
  94. bool
  95. wait_until(
  96. unique_lock<mutex>& lock,
  97. const chrono::time_point<Clock, Duration>& t,
  98. Predicate pred);
  99. template <class Rep, class Period>
  100. typename cv_status::type
  101. wait_for(
  102. unique_lock<mutex>& lock,
  103. const chrono::duration<Rep, Period>& d);
  104. template <class Rep, class Period, class Predicate>
  105. bool
  106. wait_for(
  107. unique_lock<mutex>& lock,
  108. const chrono::duration<Rep, Period>& d,
  109. Predicate pred);
  110. #if defined BOOST_THREAD_USES_DATETIME
  111. bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time);
  112. template<typename duration_type>
  113. bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time);
  114. template<typename predicate_type>
  115. bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time,predicate_type predicate);
  116. template<typename duration_type,typename predicate_type>
  117. bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time,predicate_type predicate);
  118. bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time);
  119. template<typename predicate_type>
  120. bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time,predicate_type predicate);
  121. #endif
  122. };
  123. }
  124. [section:constructor `condition_variable()`]
  125. [variablelist
  126. [[Effects:] [Constructs an object of class `condition_variable`.]]
  127. [[Throws:] [__thread_resource_error__ if an error occurs.]]
  128. ]
  129. [endsect]
  130. [section:destructor `~condition_variable()`]
  131. [variablelist
  132. [[Precondition:] [All threads waiting on `*this` have been notified by a call to
  133. `notify_one` or `notify_all` (though the respective calls to `wait` or
  134. `timed_wait` need not have returned).]]
  135. [[Effects:] [Destroys the object.]]
  136. [[Throws:] [Nothing.]]
  137. ]
  138. [endsect]
  139. [section:notify_one `void notify_one()`]
  140. [variablelist
  141. [[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
  142. to `wait` or `timed_wait`, unblocks one of those threads.]]
  143. [[Throws:] [Nothing.]]
  144. ]
  145. [endsect]
  146. [section:notify_all `void notify_all()`]
  147. [variablelist
  148. [[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
  149. to `wait` or `timed_wait`, unblocks all of those threads.]]
  150. [[Throws:] [Nothing.]]
  151. ]
  152. [endsect]
  153. [section:wait `void wait(boost::unique_lock<boost::mutex>& lock)`]
  154. [variablelist
  155. [[Precondition:] [`lock` is locked by the current thread, and either no other
  156. thread is currently waiting on `*this`, or the execution of the `mutex()` member
  157. function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
  158. in all the threads currently waiting on `*this` would return the same value as
  159. `lock->mutex()` for this call to `wait`.]]
  160. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  161. thread will unblock when notified by a call to `this->notify_one()` or
  162. `this->notify_all()`, or spuriously. When the thread is unblocked (for whatever
  163. reason), the lock is reacquired by invoking `lock.lock()` before the call to
  164. `wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
  165. function exits with an exception.]]
  166. [[Postcondition:] [`lock` is locked by the current thread.]]
  167. [[Throws:] [__thread_resource_error__ if an error
  168. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  169. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  170. ]
  171. [endsect]
  172. [section:wait_predicate `template<typename predicate_type> void wait(boost::unique_lock<boost::mutex>& lock, predicate_type pred)`]
  173. [variablelist
  174. [[Effects:] [As-if ``
  175. while(!pred())
  176. {
  177. wait(lock);
  178. }
  179. ``]]
  180. ]
  181. [endsect]
  182. [section:timed_wait `bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time)`]
  183. [variablelist
  184. [[Precondition:] [`lock` is locked by the current thread, and either no other
  185. thread is currently waiting on `*this`, or the execution of the `mutex()` member
  186. function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
  187. in all the threads currently waiting on `*this` would return the same value as
  188. `lock->mutex()` for this call to `wait`.]]
  189. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  190. thread will unblock when notified by a call to `this->notify_one()` or
  191. `this->notify_all()`, when the time as reported by `boost::get_system_time()`
  192. would be equal to or later than the specified `abs_time`, or spuriously. When
  193. the thread is unblocked (for whatever reason), the lock is reacquired by
  194. invoking `lock.lock()` before the call to `wait` returns. The lock is also
  195. reacquired by invoking `lock.lock()` if the function exits with an exception.]]
  196. [[Returns:] [`false` if the call is returning because the time specified by
  197. `abs_time` was reached, `true` otherwise.]]
  198. [[Postcondition:] [`lock` is locked by the current thread.]]
  199. [[Throws:] [__thread_resource_error__ if an error
  200. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  201. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  202. ]
  203. [endsect]
  204. [section:timed_wait_rel `template<typename duration_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time)`]
  205. [variablelist
  206. [[Precondition:] [`lock` is locked by the current thread, and either no other
  207. thread is currently waiting on `*this`, or the execution of the `mutex()` member
  208. function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
  209. in all the threads currently waiting on `*this` would return the same value as
  210. `lock->mutex()` for this call to `wait`.]]
  211. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  212. thread will unblock when notified by a call to `this->notify_one()` or
  213. `this->notify_all()`, after the period of time indicated by the `rel_time`
  214. argument has elapsed, or spuriously. When the thread is unblocked (for whatever
  215. reason), the lock is reacquired by invoking `lock.lock()` before the call to
  216. `wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
  217. function exits with an exception.]]
  218. [[Returns:] [`false` if the call is returning because the time period specified
  219. by `rel_time` has elapsed, `true` otherwise.]]
  220. [[Postcondition:] [`lock` is locked by the current thread.]]
  221. [[Throws:] [__thread_resource_error__ if an error
  222. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  223. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  224. ]
  225. [note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
  226. [endsect]
  227. [section:timed_wait_predicate `template<typename predicate_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock, boost::system_time const& abs_time, predicate_type pred)`]
  228. [variablelist
  229. [[Effects:] [As-if ``
  230. while(!pred())
  231. {
  232. if(!timed_wait(lock,abs_time))
  233. {
  234. return pred();
  235. }
  236. }
  237. return true;
  238. ``]]
  239. ]
  240. [endsect]
  241. [section:wait_until `template <class Clock, class Duration> cv_status wait_until(boost::unique_lock<boost::mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time)`]
  242. [variablelist
  243. [[Precondition:] [`lock` is locked by the current thread, and either no other
  244. thread is currently waiting on `*this`, or the execution of the `mutex()` member
  245. function on the `lock` objects supplied in the calls to `wait` or `wait_for` or `wait_until`
  246. in all the threads currently waiting on `*this` would return the same value as
  247. `lock->mutex()` for this call to `wait`.]]
  248. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  249. thread will unblock when notified by a call to `this->notify_one()` or
  250. `this->notify_all()`, when the time as reported by `Clock::now()`
  251. would be equal to or later than the specified `abs_time`, or spuriously. When
  252. the thread is unblocked (for whatever reason), the lock is reacquired by
  253. invoking `lock.lock()` before the call to `wait` returns. The lock is also
  254. reacquired by invoking `lock.lock()` if the function exits with an exception.]]
  255. [[Returns:] [`cv_status::timeout` if the call is returning because the time specified by
  256. `abs_time` was reached, `cv_status::no_timeout` otherwise.]]
  257. [[Postcondition:] [`lock` is locked by the current thread.]]
  258. [[Throws:] [__thread_resource_error__ if an error
  259. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  260. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  261. ]
  262. [endsect]
  263. [section:wait_for `template <class Rep, class Period> cv_status wait_for(boost::unique_lock<boost::mutex>& lock, const chrono::duration<Rep, Period>& rel_time)`]
  264. [variablelist
  265. [[Precondition:] [`lock` is locked by the current thread, and either no other
  266. thread is currently waiting on `*this`, or the execution of the `mutex()` member
  267. function on the `lock` objects supplied in the calls to `wait` or `wait_until` or `wait_for`
  268. in all the threads currently waiting on `*this` would return the same value as
  269. `lock->mutex()` for this call to `wait`.]]
  270. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  271. thread will unblock when notified by a call to `this->notify_one()` or
  272. `this->notify_all()`, after the period of time indicated by the `rel_time`
  273. argument has elapsed, or spuriously. When the thread is unblocked (for whatever
  274. reason), the lock is reacquired by invoking `lock.lock()` before the call to
  275. `wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
  276. function exits with an exception.]]
  277. [[Returns:] [`cv_status::timeout ` if the call is returning because the time period specified
  278. by `rel_time` has elapsed, `cv_status::no_timeout ` otherwise.]]
  279. [[Postcondition:] [`lock` is locked by the current thread.]]
  280. [[Throws:] [__thread_resource_error__ if an error
  281. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  282. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  283. ]
  284. [note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
  285. [endsect]
  286. [section:wait_until_predicate `template <class Clock, class Duration, class Predicate> bool wait_until(boost::unique_lock<boost::mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred)`]
  287. [variablelist
  288. [[Effects:] [As-if ``
  289. while(!pred())
  290. {
  291. if(!wait_until(lock,abs_time))
  292. {
  293. return pred();
  294. }
  295. }
  296. return true;
  297. ``]]
  298. ]
  299. [endsect]
  300. [section:wait_for_predicate `template <class Rep, class Period, class Predicate> bool wait_for(boost::unique_lock<boost::mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred)`]
  301. [variablelist
  302. [[Effects:] [As-if ``
  303. return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
  304. ``]]
  305. ]
  306. [endsect]
  307. [endsect]
  308. [section:condition_variable_any Class `condition_variable_any`]
  309. //#include <boost/thread/condition_variable.hpp>
  310. namespace boost
  311. {
  312. class condition_variable_any
  313. {
  314. public:
  315. condition_variable_any();
  316. ~condition_variable_any();
  317. void notify_one();
  318. void notify_all();
  319. template<typename lock_type>
  320. void wait(lock_type& lock);
  321. template<typename lock_type,typename predicate_type>
  322. void wait(lock_type& lock,predicate_type predicate);
  323. template <class lock_type, class Clock, class Duration>
  324. cv_status wait_until(
  325. lock_type& lock,
  326. const chrono::time_point<Clock, Duration>& t);
  327. template <class lock_type, class Clock, class Duration, class Predicate>
  328. bool wait_until(
  329. lock_type& lock,
  330. const chrono::time_point<Clock, Duration>& t,
  331. Predicate pred);
  332. template <class lock_type, class Rep, class Period>
  333. cv_status wait_for(
  334. lock_type& lock,
  335. const chrono::duration<Rep, Period>& d);
  336. template <class lock_type, class Rep, class Period, class Predicate>
  337. bool wait_for(
  338. lock_type& lock,
  339. const chrono::duration<Rep, Period>& d,
  340. Predicate pred);
  341. #if defined BOOST_THREAD_USES_DATETIME
  342. template<typename lock_type>
  343. bool timed_wait(lock_type& lock,boost::system_time const& abs_time);
  344. template<typename lock_type,typename duration_type>
  345. bool timed_wait(lock_type& lock,duration_type const& rel_time);
  346. template<typename lock_type,typename predicate_type>
  347. bool timed_wait(lock_type& lock,boost::system_time const& abs_time,predicate_type predicate);
  348. template<typename lock_type,typename duration_type,typename predicate_type>
  349. bool timed_wait(lock_type& lock,duration_type const& rel_time,predicate_type predicate);
  350. template<typename lock_type>
  351. bool timed_wait(lock_type>& lock,boost::xtime const& abs_time);
  352. template<typename lock_type,typename predicate_type>
  353. bool timed_wait(lock_type& lock,boost::xtime const& abs_time,predicate_type predicate);
  354. #endif
  355. };
  356. }
  357. [section:constructor `condition_variable_any()`]
  358. [variablelist
  359. [[Effects:] [Constructs an object of class `condition_variable_any`.]]
  360. [[Throws:] [__thread_resource_error__ if an error occurs.]]
  361. ]
  362. [endsect]
  363. [section:destructor `~condition_variable_any()`]
  364. [variablelist
  365. [[Precondition:] [All threads waiting on `*this` have been notified by a call to
  366. `notify_one` or `notify_all` (though the respective calls to `wait` or
  367. `timed_wait` need not have returned).]]
  368. [[Effects:] [Destroys the object.]]
  369. [[Throws:] [Nothing.]]
  370. ]
  371. [endsect]
  372. [section:notify_one `void notify_one()`]
  373. [variablelist
  374. [[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
  375. to `wait` or `timed_wait`, unblocks one of those threads.]]
  376. [[Throws:] [Nothing.]]
  377. ]
  378. [endsect]
  379. [section:notify_all `void notify_all()`]
  380. [variablelist
  381. [[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
  382. to `wait` or `timed_wait`, unblocks all of those threads.]]
  383. [[Throws:] [Nothing.]]
  384. ]
  385. [endsect]
  386. [section:wait `template<typename lock_type> void wait(lock_type& lock)`]
  387. [variablelist
  388. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  389. thread will unblock when notified by a call to `this->notify_one()` or
  390. `this->notify_all()`, or spuriously. When the thread is unblocked (for whatever
  391. reason), the lock is reacquired by invoking `lock.lock()` before the call to
  392. `wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
  393. function exits with an exception.]]
  394. [[Postcondition:] [`lock` is locked by the current thread.]]
  395. [[Throws:] [__thread_resource_error__ if an error
  396. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  397. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  398. ]
  399. [endsect]
  400. [section:wait_predicate `template<typename lock_type,typename predicate_type> void wait(lock_type& lock, predicate_type pred)`]
  401. [variablelist
  402. [[Effects:] [As-if ``
  403. while(!pred())
  404. {
  405. wait(lock);
  406. }
  407. ``]]
  408. ]
  409. [endsect]
  410. [section:timed_wait `template<typename lock_type> bool timed_wait(lock_type& lock,boost::system_time const& abs_time)`]
  411. [variablelist
  412. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  413. thread will unblock when notified by a call to `this->notify_one()` or
  414. `this->notify_all()`, when the time as reported by `boost::get_system_time()`
  415. would be equal to or later than the specified `abs_time`, or spuriously. When
  416. the thread is unblocked (for whatever reason), the lock is reacquired by
  417. invoking `lock.lock()` before the call to `wait` returns. The lock is also
  418. reacquired by invoking `lock.lock()` if the function exits with an exception.]]
  419. [[Returns:] [`false` if the call is returning because the time specified by
  420. `abs_time` was reached, `true` otherwise.]]
  421. [[Postcondition:] [`lock` is locked by the current thread.]]
  422. [[Throws:] [__thread_resource_error__ if an error
  423. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  424. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  425. ]
  426. [endsect]
  427. [section:timed_wait_rel `template<typename lock_type,typename duration_type> bool timed_wait(lock_type& lock,duration_type const& rel_time)`]
  428. [variablelist
  429. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  430. thread will unblock when notified by a call to `this->notify_one()` or
  431. `this->notify_all()`, after the period of time indicated by the `rel_time`
  432. argument has elapsed, or spuriously. When the thread is unblocked (for whatever
  433. reason), the lock is reacquired by invoking `lock.lock()` before the call to
  434. `wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
  435. function exits with an exception.]]
  436. [[Returns:] [`false` if the call is returning because the time period specified
  437. by `rel_time` has elapsed, `true` otherwise.]]
  438. [[Postcondition:] [`lock` is locked by the current thread.]]
  439. [[Throws:] [__thread_resource_error__ if an error
  440. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  441. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  442. ]
  443. [note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
  444. [endsect]
  445. [section:timed_wait_predicate `template<typename lock_type,typename predicate_type> bool timed_wait(lock_type& lock, boost::system_time const& abs_time, predicate_type pred)`]
  446. [variablelist
  447. [[Effects:] [As-if ``
  448. while(!pred())
  449. {
  450. if(!timed_wait(lock,abs_time))
  451. {
  452. return pred();
  453. }
  454. }
  455. return true;
  456. ``]]
  457. ]
  458. [endsect]
  459. [section:wait_until `template <class lock_type, class Clock, class Duration> cv_status wait_until(lock_type& lock, const chrono::time_point<Clock, Duration>& abs_time)`]
  460. [variablelist
  461. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  462. thread will unblock when notified by a call to `this->notify_one()` or
  463. `this->notify_all()`, when the time as reported by `Clock::now()`
  464. would be equal to or later than the specified `abs_time`, or spuriously. When
  465. the thread is unblocked (for whatever reason), the lock is reacquired by
  466. invoking `lock.lock()` before the call to `wait` returns. The lock is also
  467. reacquired by invoking `lock.lock()` if the function exits with an exception.]]
  468. [[Returns:] [`cv_status::timeout` if the call is returning because the time specified by
  469. `abs_time` was reached, `cv_status::no_timeout` otherwise.]]
  470. [[Postcondition:] [`lock` is locked by the current thread.]]
  471. [[Throws:] [__thread_resource_error__ if an error
  472. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  473. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  474. ]
  475. [endsect]
  476. [section:wait_for `template <class lock_type, class Rep, class Period> cv_status wait_for(lock_type& lock, const chrono::duration<Rep, Period>& rel_time)`]
  477. [variablelist
  478. [[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
  479. thread will unblock when notified by a call to `this->notify_one()` or
  480. `this->notify_all()`, after the period of time indicated by the `rel_time`
  481. argument has elapsed, or spuriously. When the thread is unblocked (for whatever
  482. reason), the lock is reacquired by invoking `lock.lock()` before the call to
  483. `wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
  484. function exits with an exception.]]
  485. [[Returns:] [`cv_status::timeout` if the call is returning because the time specified by
  486. `abs_time` was reached, `cv_status::no_timeout` otherwise.]]
  487. [[Postcondition:] [`lock` is locked by the current thread.]]
  488. [[Throws:] [__thread_resource_error__ if an error
  489. occurs. __thread_interrupted__ if the wait was interrupted by a call to
  490. __interrupt__ on the __thread__ object associated with the current thread of execution.]]
  491. ]
  492. [note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
  493. [endsect]
  494. [section:wait_until_predicate `template <class lock_type, class Clock, class Duration, class Predicate> bool wait_until(lock_type& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred)`]
  495. [variablelist
  496. [[Effects:] [As-if ``
  497. while(!pred())
  498. {
  499. if(!__cvany_wait_until(lock,abs_time))
  500. {
  501. return pred();
  502. }
  503. }
  504. return true;
  505. ``]]
  506. ]
  507. [endsect]
  508. [section:wait_for_predicate `template <class lock_type, class Rep, class Period, class Predicate> bool wait_for(lock_type& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred)`]
  509. [variablelist
  510. [[Effects:] [As-if ``
  511. return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
  512. ``]]
  513. ]
  514. [endsect]
  515. [endsect]
  516. [section:condition Typedef `condition` DEPRECATED V3]
  517. // #include <boost/thread/condition.hpp>
  518. namespace boost
  519. {
  520. typedef condition_variable_any condition;
  521. }
  522. The typedef `condition` is provided for backwards compatibility with previous boost releases.
  523. [endsect]
  524. [section:notify_all_at_thread_exit Non-member Function `notify_all_at_thread_exit`()]
  525. // #include <boost/thread/condition_variable.hpp>
  526. namespace boost
  527. {
  528. void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
  529. }
  530. [variablelist
  531. [[Requires:] [`lk` is locked by the calling thread and either no other thread is waiting on `cond`, or `lk.mutex()` returns the same value for each of the lock arguments supplied by all concurrently waiting (via `wait`, `wait_for`, or `wait_until`) threads.]]
  532. [[Effects:] [transfers ownership of the lock associated with `lk` into internal storage and schedules `cond` to be notified when the current thread exits, after all objects of thread storage duration associated with the current thread have been destroyed. This notification shall be as if
  533. ``
  534. lk.unlock();
  535. cond.notify_all();
  536. ``
  537. ]]
  538. ]
  539. [/
  540. [[Synchronization:] [The call to notify_all_at_thread_exit and the completion of the destructors for all the current threadÕs variables of thread storage duration synchronize with (1.10) calls to functions waiting on cond.
  541. ]]
  542. [[Note:] [The supplied lock will be held until the thread exits, and care must be taken to ensure that this does not cause deadlock due to lock ordering issues. After calling notify_all_at_thread_exit it is recommended that the thread should be exited as soon as possible, and that no blocking or time-consuming tasks are run on that thread.
  543. ]]
  544. [[Note:] [It is the userÕs responsibility to ensure that waiting threads do not erroneously assume that the thread has finished if they experience spurious wakeups. This typically requires that the condition being waited for is satisfied while holding the lock on lk, and that this lock is not released and reacquired prior to calling notify_all_at_thread_exit.
  545. ]]
  546. ]
  547. [endsect]
  548. [endsect]