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