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
9[section:condvar_ref Condition Variables]
10
11[heading Synopsis]
12
13  namespace boost
14  {
15    enum class cv_status;
16    {
17      no_timeout,
18      timeout
19    };
20    class condition_variable;
21    class condition_variable_any;
22    void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
23  }
24
25The classes `condition_variable` and `condition_variable_any` provide a
26mechanism for one thread to wait for notification from another thread that a
27particular condition has become true. The general usage pattern is that one
28thread locks a mutex and then calls `wait` on an instance of
29`condition_variable` or `condition_variable_any`. When the thread is woken from
30the wait, then it checks to see if the appropriate condition is now true, and
31continues if so. If the condition is not true, then the thread then calls `wait`
32again to resume waiting. In the simplest case, this condition is just a boolean
33variable:
34
35    boost::condition_variable cond;
36    boost::mutex mut;
37    bool data_ready;
38
39    void process_data();
40
41    void wait_for_data_to_process()
42    {
43        boost::unique_lock<boost::mutex> lock(mut);
44        while(!data_ready)
45        {
46            cond.wait(lock);
47        }
48        process_data();
49    }
50
51Notice that the `lock` is passed to `wait`: `wait` will atomically add the
52thread to the set of threads waiting on the condition variable, and unlock the
53mutex. When the thread is woken, the mutex will be locked again before the call
54to `wait` returns. This allows other threads to acquire the mutex in order to
55update the shared data, and ensures that the data associated with the condition
56is correctly synchronized.
57
58In the mean time, another thread sets the condition to `true`, and then calls
59either `notify_one` or `notify_all` on the condition variable to wake one
60waiting thread or all the waiting threads respectively.
61
62    void retrieve_data();
63    void prepare_data();
64
65    void prepare_data_for_processing()
66    {
67        retrieve_data();
68        prepare_data();
69        {
70            boost::lock_guard<boost::mutex> lock(mut);
71            data_ready=true;
72        }
73        cond.notify_one();
74    }
75
76Note that the same mutex is locked before the shared data is updated, but that
77the mutex does not have to be locked across the call to `notify_one`.
78
79This example uses an object of type `condition_variable`, but would work just as
80well with an object of type `condition_variable_any`: `condition_variable_any`
81is more general, and will work with any kind of lock or mutex, whereas
82`condition_variable` requires that the lock passed to `wait` is an instance of
83`boost::unique_lock<boost::mutex>`. This enables `condition_variable` to make
84optimizations in some cases, based on the knowledge of the mutex type;
85`condition_variable_any` typically has a more complex implementation than
86`condition_variable`.
87
88[section:condition_variable Class `condition_variable`]
89
90    //#include <boost/thread/condition_variable.hpp>
91
92    namespace boost
93    {
94        class condition_variable
95        {
96        public:
97            condition_variable();
98            ~condition_variable();
99
100            void notify_one() noexcept;
101            void notify_all() noexcept;
102
103            void wait(boost::unique_lock<boost::mutex>& lock);
104
105            template<typename predicate_type>
106            void wait(boost::unique_lock<boost::mutex>& lock,predicate_type predicate);
107
108            template <class Clock, class Duration>
109            typename cv_status::type
110            wait_until(
111                unique_lock<mutex>& lock,
112                const chrono::time_point<Clock, Duration>& t);
113
114            template <class Clock, class Duration, class Predicate>
115            bool
116            wait_until(
117                unique_lock<mutex>& lock,
118                const chrono::time_point<Clock, Duration>& t,
119                Predicate pred);
120
121            template <class Rep, class Period>
122            typename cv_status::type
123            wait_for(
124                unique_lock<mutex>& lock,
125                const chrono::duration<Rep, Period>& d);
126
127            template <class Rep, class Period, class Predicate>
128            bool
129            wait_for(
130                unique_lock<mutex>& lock,
131                const chrono::duration<Rep, Period>& d,
132                Predicate pred);
133
134        #if defined BOOST_THREAD_USES_DATETIME
135            bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time);
136            template<typename duration_type>
137            bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time);
138            template<typename predicate_type>
139            bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time,predicate_type predicate);
140            template<typename duration_type,typename predicate_type>
141            bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time,predicate_type predicate);
142            bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time);
143
144            template<typename predicate_type>
145            bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time,predicate_type predicate);
146        #endif
147
148        };
149    }
150
151[section:constructor `condition_variable()`]
152
153[variablelist
154
155[[Effects:] [Constructs an object of class `condition_variable`.]]
156
157[[Throws:] [__thread_resource_error__ if an error occurs.]]
158
159]
160
161[endsect]
162
163[section:destructor `~condition_variable()`]
164
165[variablelist
166
167[[Precondition:] [All threads waiting on `*this` have been notified by a call to
168`notify_one` or `notify_all` (though the respective calls to `wait` or
169`timed_wait` need not have returned).]]
170
171[[Effects:] [Destroys the object.]]
172
173[[Throws:] [Nothing.]]
174
175]
176
177[endsect]
178
179[section:notify_one `void notify_one()`]
180
181[variablelist
182
183[[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
184to `wait` or `timed_wait`, unblocks one of those threads.]]
185
186[[Throws:] [Nothing.]]
187
188]
189
190[endsect]
191
192[section:notify_all `void notify_all()`]
193
194[variablelist
195
196[[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
197to `wait` or `timed_wait`, unblocks all of those threads.]]
198
199[[Throws:] [Nothing.]]
200
201]
202
203[endsect]
204
205[section:wait `void wait(boost::unique_lock<boost::mutex>& lock)`]
206
207[variablelist
208
209[[Precondition:] [`lock` is locked by the current thread, and either no other
210thread is currently waiting on `*this`, or the execution of the `mutex()` member
211function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
212in all the threads currently waiting on `*this` would return the same value as
213`lock->mutex()` for this call to `wait`.]]
214
215[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
216thread will unblock when notified by a call to `this->notify_one()` or
217`this->notify_all()`, or spuriously. When the thread is unblocked (for whatever
218reason), the lock is reacquired by invoking `lock.lock()` before the call to
219`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
220function exits with an exception.]]
221
222[[Postcondition:] [`lock` is locked by the current thread.]]
223
224[[Throws:] [__thread_resource_error__ if an error
225occurs. __thread_interrupted__ if the wait was interrupted by a call to
226__interrupt__ on the __thread__ object associated with the current thread of execution.]]
227
228]
229
230[endsect]
231
232[section:wait_predicate `template<typename predicate_type> void wait(boost::unique_lock<boost::mutex>& lock, predicate_type pred)`]
233
234[variablelist
235
236[[Effects:] [As-if ``
237while(!pred())
238{
239    wait(lock);
240}
241``]]
242
243]
244
245[endsect]
246
247[section:timed_wait `bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time)`]
248
249[variablelist
250
251[[Precondition:] [`lock` is locked by the current thread, and either no other
252thread is currently waiting on `*this`, or the execution of the `mutex()` member
253function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
254in all the threads currently waiting on `*this` would return the same value as
255`lock->mutex()` for this call to `wait`.]]
256
257[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
258thread will unblock when notified by a call to `this->notify_one()` or
259`this->notify_all()`, when the time as reported by `boost::get_system_time()`
260would be equal to or later than the specified `abs_time`, or spuriously. When
261the thread is unblocked (for whatever reason), the lock is reacquired by
262invoking `lock.lock()` before the call to `wait` returns. The lock is also
263reacquired by invoking `lock.lock()` if the function exits with an exception.]]
264
265[[Returns:] [`false` if the call is returning because the time specified by
266`abs_time` was reached, `true` otherwise.]]
267
268[[Postcondition:] [`lock` is locked by the current thread.]]
269
270[[Throws:] [__thread_resource_error__ if an error
271occurs. __thread_interrupted__ if the wait was interrupted by a call to
272__interrupt__ on the __thread__ object associated with the current thread of execution.]]
273
274]
275
276[endsect]
277
278[section:timed_wait_rel `template<typename duration_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time)`]
279
280[variablelist
281
282[[Precondition:] [`lock` is locked by the current thread, and either no other
283thread is currently waiting on `*this`, or the execution of the `mutex()` member
284function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
285in all the threads currently waiting on `*this` would return the same value as
286`lock->mutex()` for this call to `wait`.]]
287
288[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
289thread will unblock when notified by a call to `this->notify_one()` or
290`this->notify_all()`, after the period of time indicated by the `rel_time`
291argument has elapsed, or spuriously. When the thread is unblocked (for whatever
292reason), the lock is reacquired by invoking `lock.lock()` before the call to
293`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
294function exits with an exception.]]
295
296[[Returns:] [`false` if the call is returning because the time period specified
297by `rel_time` has elapsed, `true` otherwise.]]
298
299[[Postcondition:] [`lock` is locked by the current thread.]]
300
301[[Throws:] [__thread_resource_error__ if an error
302occurs. __thread_interrupted__ if the wait was interrupted by a call to
303__interrupt__ on the __thread__ object associated with the current thread of execution.]]
304
305]
306
307[note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
308
309[endsect]
310
311[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)`]
312
313[variablelist
314
315[[Effects:] [As-if ``
316while(!pred())
317{
318    if(!timed_wait(lock,abs_time))
319    {
320        return pred();
321    }
322}
323return true;
324``]]
325
326]
327
328[endsect]
329
330
331[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)`]
332
333[variablelist
334
335[[Precondition:] [`lock` is locked by the current thread, and either no other
336thread is currently waiting on `*this`, or the execution of the `mutex()` member
337function on the `lock` objects supplied in the calls to `wait` or `wait_for` or `wait_until`
338in all the threads currently waiting on `*this` would return the same value as
339`lock->mutex()` for this call to `wait`.]]
340
341[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
342thread will unblock when notified by a call to `this->notify_one()` or
343`this->notify_all()`, when the time as reported by `Clock::now()`
344would be equal to or later than the specified `abs_time`, or spuriously. When
345the thread is unblocked (for whatever reason), the lock is reacquired by
346invoking `lock.lock()` before the call to `wait` returns. The lock is also
347reacquired by invoking `lock.lock()` if the function exits with an exception.]]
348
349[[Returns:] [`cv_status::timeout` if the call is returning because the time specified by
350`abs_time` was reached, `cv_status::no_timeout` otherwise.]]
351
352[[Postcondition:] [`lock` is locked by the current thread.]]
353
354[[Throws:] [__thread_resource_error__ if an error
355occurs. __thread_interrupted__ if the wait was interrupted by a call to
356__interrupt__ on the __thread__ object associated with the current thread of execution.]]
357
358]
359
360[endsect]
361
362[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)`]
363
364
365[variablelist
366
367[[Precondition:] [`lock` is locked by the current thread, and either no other
368thread is currently waiting on `*this`, or the execution of the `mutex()` member
369function on the `lock` objects supplied in the calls to `wait` or `wait_until` or `wait_for`
370in all the threads currently waiting on `*this` would return the same value as
371`lock->mutex()` for this call to `wait`.]]
372
373[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
374thread will unblock when notified by a call to `this->notify_one()` or
375`this->notify_all()`, after the period of time indicated by the `rel_time`
376argument has elapsed, or spuriously. When the thread is unblocked (for whatever
377reason), the lock is reacquired by invoking `lock.lock()` before the call to
378`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
379function exits with an exception.]]
380
381[[Returns:] [`cv_status::timeout ` if the call is returning because the time period specified
382by `rel_time` has elapsed, `cv_status::no_timeout ` otherwise.]]
383
384[[Postcondition:] [`lock` is locked by the current thread.]]
385
386[[Throws:] [__thread_resource_error__ if an error
387occurs. __thread_interrupted__ if the wait was interrupted by a call to
388__interrupt__ on the __thread__ object associated with the current thread of execution.]]
389
390]
391
392[note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
393
394[endsect]
395
396[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)`]
397
398
399[variablelist
400
401[[Effects:] [As-if ``
402while(!pred())
403{
404    if(!wait_until(lock,abs_time))
405    {
406        return pred();
407    }
408}
409return true;
410``]]
411
412]
413
414[endsect]
415
416[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)`]
417
418
419[variablelist
420
421[[Effects:] [As-if ``
422return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
423``]]
424
425]
426
427[endsect]
428
429
430
431
432[endsect]
433
434[section:condition_variable_any Class `condition_variable_any`]
435
436    //#include <boost/thread/condition_variable.hpp>
437
438    namespace boost
439    {
440        class condition_variable_any
441        {
442        public:
443            condition_variable_any();
444            ~condition_variable_any();
445
446            void notify_one();
447            void notify_all();
448
449            template<typename lock_type>
450            void wait(lock_type& lock);
451
452            template<typename lock_type,typename predicate_type>
453            void wait(lock_type& lock,predicate_type predicate);
454
455            template <class lock_type, class Clock, class Duration>
456            cv_status wait_until(
457                lock_type& lock,
458                const chrono::time_point<Clock, Duration>& t);
459
460            template <class lock_type, class Clock, class Duration, class Predicate>
461            bool wait_until(
462                lock_type& lock,
463                const chrono::time_point<Clock, Duration>& t,
464                Predicate pred);
465
466
467            template <class lock_type, class Rep, class Period>
468            cv_status wait_for(
469                lock_type& lock,
470                const chrono::duration<Rep, Period>& d);
471
472            template <class lock_type, class Rep, class Period, class Predicate>
473            bool wait_for(
474                lock_type& lock,
475                const chrono::duration<Rep, Period>& d,
476                Predicate pred);
477
478        #if defined BOOST_THREAD_USES_DATETIME
479            template<typename lock_type>
480            bool timed_wait(lock_type& lock,boost::system_time const& abs_time);
481            template<typename lock_type,typename duration_type>
482            bool timed_wait(lock_type& lock,duration_type const& rel_time);
483            template<typename lock_type,typename predicate_type>
484            bool timed_wait(lock_type& lock,boost::system_time const& abs_time,predicate_type predicate);
485            template<typename lock_type,typename duration_type,typename predicate_type>
486            bool timed_wait(lock_type& lock,duration_type const& rel_time,predicate_type predicate);
487            template<typename lock_type>
488            bool timed_wait(lock_type>& lock,boost::xtime const& abs_time);
489            template<typename lock_type,typename predicate_type>
490            bool timed_wait(lock_type& lock,boost::xtime const& abs_time,predicate_type predicate);
491        #endif
492        };
493    }
494
495[section:constructor `condition_variable_any()`]
496
497[variablelist
498
499[[Effects:] [Constructs an object of class `condition_variable_any`.]]
500
501[[Throws:] [__thread_resource_error__ if an error occurs.]]
502
503]
504
505[endsect]
506
507[section:destructor `~condition_variable_any()`]
508
509[variablelist
510
511[[Precondition:] [All threads waiting on `*this` have been notified by a call to
512`notify_one` or `notify_all` (though the respective calls to `wait` or
513`timed_wait` need not have returned).]]
514
515[[Effects:] [Destroys the object.]]
516
517[[Throws:] [Nothing.]]
518
519]
520
521[endsect]
522
523[section:notify_one `void notify_one()`]
524
525[variablelist
526
527[[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
528to `wait` or `timed_wait`, unblocks one of those threads.]]
529
530[[Throws:] [Nothing.]]
531
532]
533
534[endsect]
535
536[section:notify_all `void notify_all()`]
537
538[variablelist
539
540[[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
541to `wait` or `timed_wait`, unblocks all of those threads.]]
542
543[[Throws:] [Nothing.]]
544
545]
546
547[endsect]
548
549[section:wait `template<typename lock_type> void wait(lock_type& lock)`]
550
551[variablelist
552
553[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
554thread will unblock when notified by a call to `this->notify_one()` or
555`this->notify_all()`, or spuriously. When the thread is unblocked (for whatever
556reason), the lock is reacquired by invoking `lock.lock()` before the call to
557`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
558function exits with an exception.]]
559
560[[Postcondition:] [`lock` is locked by the current thread.]]
561
562[[Throws:] [__thread_resource_error__ if an error
563occurs. __thread_interrupted__ if the wait was interrupted by a call to
564__interrupt__ on the __thread__ object associated with the current thread of execution.]]
565
566]
567
568[endsect]
569
570[section:wait_predicate `template<typename lock_type,typename predicate_type> void wait(lock_type& lock, predicate_type pred)`]
571
572[variablelist
573
574[[Effects:] [As-if ``
575while(!pred())
576{
577    wait(lock);
578}
579``]]
580
581]
582
583[endsect]
584
585[section:timed_wait `template<typename lock_type> bool timed_wait(lock_type& lock,boost::system_time const& abs_time)`]
586
587[variablelist
588
589[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
590thread will unblock when notified by a call to `this->notify_one()` or
591`this->notify_all()`, when the time as reported by `boost::get_system_time()`
592would be equal to or later than the specified `abs_time`, or spuriously. When
593the thread is unblocked (for whatever reason), the lock is reacquired by
594invoking `lock.lock()` before the call to `wait` returns. The lock is also
595reacquired by invoking `lock.lock()` if the function exits with an exception.]]
596
597[[Returns:] [`false` if the call is returning because the time specified by
598`abs_time` was reached, `true` otherwise.]]
599
600[[Postcondition:] [`lock` is locked by the current thread.]]
601
602[[Throws:] [__thread_resource_error__ if an error
603occurs. __thread_interrupted__ if the wait was interrupted by a call to
604__interrupt__ on the __thread__ object associated with the current thread of execution.]]
605
606]
607
608[endsect]
609
610[section:timed_wait_rel `template<typename lock_type,typename duration_type> bool timed_wait(lock_type& lock,duration_type const& rel_time)`]
611
612[variablelist
613
614[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
615thread will unblock when notified by a call to `this->notify_one()` or
616`this->notify_all()`, after the period of time indicated by the `rel_time`
617argument has elapsed, or spuriously. When the thread is unblocked (for whatever
618reason), the lock is reacquired by invoking `lock.lock()` before the call to
619`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
620function exits with an exception.]]
621
622[[Returns:] [`false` if the call is returning because the time period specified
623by `rel_time` has elapsed, `true` otherwise.]]
624
625[[Postcondition:] [`lock` is locked by the current thread.]]
626
627[[Throws:] [__thread_resource_error__ if an error
628occurs. __thread_interrupted__ if the wait was interrupted by a call to
629__interrupt__ on the __thread__ object associated with the current thread of execution.]]
630
631]
632
633[note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
634
635[endsect]
636
637[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)`]
638
639[variablelist
640
641[[Effects:] [As-if ``
642while(!pred())
643{
644    if(!timed_wait(lock,abs_time))
645    {
646        return pred();
647    }
648}
649return true;
650``]]
651
652]
653
654[endsect]
655
656[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)`]
657
658[variablelist
659
660[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
661thread will unblock when notified by a call to `this->notify_one()` or
662`this->notify_all()`, when the time as reported by `Clock::now()`
663would be equal to or later than the specified `abs_time`, or spuriously. When
664the thread is unblocked (for whatever reason), the lock is reacquired by
665invoking `lock.lock()` before the call to `wait` returns. The lock is also
666reacquired by invoking `lock.lock()` if the function exits with an exception.]]
667
668[[Returns:] [`cv_status::timeout` if the call is returning because the time specified by
669`abs_time` was reached, `cv_status::no_timeout` otherwise.]]
670
671[[Postcondition:] [`lock` is locked by the current thread.]]
672
673[[Throws:] [__thread_resource_error__ if an error
674occurs. __thread_interrupted__ if the wait was interrupted by a call to
675__interrupt__ on the __thread__ object associated with the current thread of execution.]]
676
677]
678
679[endsect]
680
681[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)`]
682
683[variablelist
684
685[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
686thread will unblock when notified by a call to `this->notify_one()` or
687`this->notify_all()`, after the period of time indicated by the `rel_time`
688argument has elapsed, or spuriously. When the thread is unblocked (for whatever
689reason), the lock is reacquired by invoking `lock.lock()` before the call to
690`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
691function exits with an exception.]]
692
693[[Returns:] [`cv_status::timeout` if the call is returning because the time specified by
694`abs_time` was reached, `cv_status::no_timeout` otherwise.]]
695
696[[Postcondition:] [`lock` is locked by the current thread.]]
697
698[[Throws:] [__thread_resource_error__ if an error
699occurs. __thread_interrupted__ if the wait was interrupted by a call to
700__interrupt__ on the __thread__ object associated with the current thread of execution.]]
701
702]
703
704[note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
705
706[endsect]
707
708[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)`]
709
710[variablelist
711
712[[Effects:] [As-if ``
713while(!pred())
714{
715    if(!__cvany_wait_until(lock,abs_time))
716    {
717        return pred();
718    }
719}
720return true;
721``]]
722
723]
724
725[endsect]
726
727[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)`]
728
729[variablelist
730
731[[Effects:] [As-if ``
732return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
733``]]
734
735]
736
737[endsect]
738
739[endsect]
740
741[section:condition Typedef `condition` DEPRECATED V3]
742
743  // #include <boost/thread/condition.hpp>
744  namespace boost
745  {
746
747    typedef condition_variable_any condition;
748
749  }
750
751The typedef `condition` is provided for backwards compatibility with previous boost releases.
752
753[endsect]
754
755
756[section:notify_all_at_thread_exit Non-member Function `notify_all_at_thread_exit`()]
757
758  // #include <boost/thread/condition_variable.hpp>
759
760  namespace boost
761  {
762    void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
763  }
764
765[variablelist
766
767[[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.]]
768[[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
769
770``
771  lk.unlock();
772  cond.notify_all();
773``
774
775]]
776
777]
778
779[/
780[[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.
781]]
782[[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.
783]]
784[[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.
785]]
786]
787
788[endsect]
789
790[endsect]
791