17a984708SDavid Chisnall// -*- C++ -*- 27a984708SDavid Chisnall//===---------------------- condition_variable ----------------------------===// 37a984708SDavid Chisnall// 47a984708SDavid Chisnall// The LLVM Compiler Infrastructure 57a984708SDavid Chisnall// 67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open 77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details. 87a984708SDavid Chisnall// 97a984708SDavid Chisnall//===----------------------------------------------------------------------===// 107a984708SDavid Chisnall 117a984708SDavid Chisnall#ifndef _LIBCPP_CONDITION_VARIABLE 127a984708SDavid Chisnall#define _LIBCPP_CONDITION_VARIABLE 137a984708SDavid Chisnall 147a984708SDavid Chisnall/* 157a984708SDavid Chisnall condition_variable synopsis 167a984708SDavid Chisnall 177a984708SDavid Chisnallnamespace std 187a984708SDavid Chisnall{ 197a984708SDavid Chisnall 207a984708SDavid Chisnallenum class cv_status { no_timeout, timeout }; 217a984708SDavid Chisnall 227a984708SDavid Chisnallclass condition_variable 237a984708SDavid Chisnall{ 247a984708SDavid Chisnallpublic: 257a984708SDavid Chisnall condition_variable(); 267a984708SDavid Chisnall ~condition_variable(); 277a984708SDavid Chisnall 287a984708SDavid Chisnall condition_variable(const condition_variable&) = delete; 297a984708SDavid Chisnall condition_variable& operator=(const condition_variable&) = delete; 307a984708SDavid Chisnall 31936e9439SDimitry Andric void notify_one() noexcept; 32936e9439SDimitry Andric void notify_all() noexcept; 337a984708SDavid Chisnall 347a984708SDavid Chisnall void wait(unique_lock<mutex>& lock); 357a984708SDavid Chisnall template <class Predicate> 367a984708SDavid Chisnall void wait(unique_lock<mutex>& lock, Predicate pred); 377a984708SDavid Chisnall 387a984708SDavid Chisnall template <class Clock, class Duration> 397a984708SDavid Chisnall cv_status 407a984708SDavid Chisnall wait_until(unique_lock<mutex>& lock, 417a984708SDavid Chisnall const chrono::time_point<Clock, Duration>& abs_time); 427a984708SDavid Chisnall 437a984708SDavid Chisnall template <class Clock, class Duration, class Predicate> 447a984708SDavid Chisnall bool 457a984708SDavid Chisnall wait_until(unique_lock<mutex>& lock, 467a984708SDavid Chisnall const chrono::time_point<Clock, Duration>& abs_time, 477a984708SDavid Chisnall Predicate pred); 487a984708SDavid Chisnall 497a984708SDavid Chisnall template <class Rep, class Period> 507a984708SDavid Chisnall cv_status 517a984708SDavid Chisnall wait_for(unique_lock<mutex>& lock, 527a984708SDavid Chisnall const chrono::duration<Rep, Period>& rel_time); 537a984708SDavid Chisnall 547a984708SDavid Chisnall template <class Rep, class Period, class Predicate> 557a984708SDavid Chisnall bool 567a984708SDavid Chisnall wait_for(unique_lock<mutex>& lock, 577a984708SDavid Chisnall const chrono::duration<Rep, Period>& rel_time, 587a984708SDavid Chisnall Predicate pred); 597a984708SDavid Chisnall 607a984708SDavid Chisnall typedef pthread_cond_t* native_handle_type; 617a984708SDavid Chisnall native_handle_type native_handle(); 627a984708SDavid Chisnall}; 637a984708SDavid Chisnall 647a984708SDavid Chisnallvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); 657a984708SDavid Chisnall 667a984708SDavid Chisnallclass condition_variable_any 677a984708SDavid Chisnall{ 687a984708SDavid Chisnallpublic: 697a984708SDavid Chisnall condition_variable_any(); 707a984708SDavid Chisnall ~condition_variable_any(); 717a984708SDavid Chisnall 727a984708SDavid Chisnall condition_variable_any(const condition_variable_any&) = delete; 737a984708SDavid Chisnall condition_variable_any& operator=(const condition_variable_any&) = delete; 747a984708SDavid Chisnall 75936e9439SDimitry Andric void notify_one() noexcept; 76936e9439SDimitry Andric void notify_all() noexcept; 777a984708SDavid Chisnall 787a984708SDavid Chisnall template <class Lock> 797a984708SDavid Chisnall void wait(Lock& lock); 807a984708SDavid Chisnall template <class Lock, class Predicate> 817a984708SDavid Chisnall void wait(Lock& lock, Predicate pred); 827a984708SDavid Chisnall 837a984708SDavid Chisnall template <class Lock, class Clock, class Duration> 847a984708SDavid Chisnall cv_status 857a984708SDavid Chisnall wait_until(Lock& lock, 867a984708SDavid Chisnall const chrono::time_point<Clock, Duration>& abs_time); 877a984708SDavid Chisnall 887a984708SDavid Chisnall template <class Lock, class Clock, class Duration, class Predicate> 897a984708SDavid Chisnall bool 907a984708SDavid Chisnall wait_until(Lock& lock, 917a984708SDavid Chisnall const chrono::time_point<Clock, Duration>& abs_time, 927a984708SDavid Chisnall Predicate pred); 937a984708SDavid Chisnall 947a984708SDavid Chisnall template <class Lock, class Rep, class Period> 957a984708SDavid Chisnall cv_status 967a984708SDavid Chisnall wait_for(Lock& lock, 977a984708SDavid Chisnall const chrono::duration<Rep, Period>& rel_time); 987a984708SDavid Chisnall 997a984708SDavid Chisnall template <class Lock, class Rep, class Period, class Predicate> 1007a984708SDavid Chisnall bool 1017a984708SDavid Chisnall wait_for(Lock& lock, 1027a984708SDavid Chisnall const chrono::duration<Rep, Period>& rel_time, 1037a984708SDavid Chisnall Predicate pred); 1047a984708SDavid Chisnall}; 1057a984708SDavid Chisnall 1067a984708SDavid Chisnall} // std 1077a984708SDavid Chisnall 1087a984708SDavid Chisnall*/ 1097a984708SDavid Chisnall 1107a984708SDavid Chisnall#include <__config> 1117a984708SDavid Chisnall#include <__mutex_base> 1127a984708SDavid Chisnall#include <memory> 1137a984708SDavid Chisnall 1147a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1157a984708SDavid Chisnall#pragma GCC system_header 1167a984708SDavid Chisnall#endif 1177a984708SDavid Chisnall 118d72607e9SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS 119d72607e9SDimitry Andric 1207a984708SDavid Chisnall_LIBCPP_BEGIN_NAMESPACE_STD 1217a984708SDavid Chisnall 1221bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS condition_variable_any 1237a984708SDavid Chisnall{ 1247a984708SDavid Chisnall condition_variable __cv_; 1257a984708SDavid Chisnall shared_ptr<mutex> __mut_; 1267a984708SDavid Chisnallpublic: 1279729cf09SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1287a984708SDavid Chisnall condition_variable_any(); 1297a984708SDavid Chisnall 1309729cf09SDimitry Andric _LIBCPP_INLINE_VISIBILITY 131936e9439SDimitry Andric void notify_one() _NOEXCEPT; 1329729cf09SDimitry Andric _LIBCPP_INLINE_VISIBILITY 133936e9439SDimitry Andric void notify_all() _NOEXCEPT; 1347a984708SDavid Chisnall 1357a984708SDavid Chisnall template <class _Lock> 136*540d2a8bSDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 1377a984708SDavid Chisnall void wait(_Lock& __lock); 1387a984708SDavid Chisnall template <class _Lock, class _Predicate> 1399729cf09SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1407a984708SDavid Chisnall void wait(_Lock& __lock, _Predicate __pred); 1417a984708SDavid Chisnall 1427a984708SDavid Chisnall template <class _Lock, class _Clock, class _Duration> 143*540d2a8bSDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 1447a984708SDavid Chisnall cv_status 1457a984708SDavid Chisnall wait_until(_Lock& __lock, 1467a984708SDavid Chisnall const chrono::time_point<_Clock, _Duration>& __t); 1477a984708SDavid Chisnall 1487a984708SDavid Chisnall template <class _Lock, class _Clock, class _Duration, class _Predicate> 1497a984708SDavid Chisnall bool 1509729cf09SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1517a984708SDavid Chisnall wait_until(_Lock& __lock, 1527a984708SDavid Chisnall const chrono::time_point<_Clock, _Duration>& __t, 1537a984708SDavid Chisnall _Predicate __pred); 1547a984708SDavid Chisnall 1557a984708SDavid Chisnall template <class _Lock, class _Rep, class _Period> 1567a984708SDavid Chisnall cv_status 1579729cf09SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1587a984708SDavid Chisnall wait_for(_Lock& __lock, 1597a984708SDavid Chisnall const chrono::duration<_Rep, _Period>& __d); 1607a984708SDavid Chisnall 1617a984708SDavid Chisnall template <class _Lock, class _Rep, class _Period, class _Predicate> 1627a984708SDavid Chisnall bool 1639729cf09SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1647a984708SDavid Chisnall wait_for(_Lock& __lock, 1657a984708SDavid Chisnall const chrono::duration<_Rep, _Period>& __d, 1667a984708SDavid Chisnall _Predicate __pred); 1677a984708SDavid Chisnall}; 1687a984708SDavid Chisnall 1699729cf09SDimitry Andricinline 1707a984708SDavid Chisnallcondition_variable_any::condition_variable_any() 1717a984708SDavid Chisnall : __mut_(make_shared<mutex>()) {} 1727a984708SDavid Chisnall 1739729cf09SDimitry Andricinline 1747a984708SDavid Chisnallvoid 175936e9439SDimitry Andriccondition_variable_any::notify_one() _NOEXCEPT 1767a984708SDavid Chisnall{ 1771e0896acSDavid Chisnall {lock_guard<mutex> __lx(*__mut_);} 1787a984708SDavid Chisnall __cv_.notify_one(); 1797a984708SDavid Chisnall} 1807a984708SDavid Chisnall 1819729cf09SDimitry Andricinline 1827a984708SDavid Chisnallvoid 183936e9439SDimitry Andriccondition_variable_any::notify_all() _NOEXCEPT 1847a984708SDavid Chisnall{ 1851e0896acSDavid Chisnall {lock_guard<mutex> __lx(*__mut_);} 1867a984708SDavid Chisnall __cv_.notify_all(); 1877a984708SDavid Chisnall} 1887a984708SDavid Chisnall 1897a984708SDavid Chisnallstruct __lock_external 1907a984708SDavid Chisnall{ 1917a984708SDavid Chisnall template <class _Lock> 1927a984708SDavid Chisnall void operator()(_Lock* __m) {__m->lock();} 1937a984708SDavid Chisnall}; 1947a984708SDavid Chisnall 1957a984708SDavid Chisnalltemplate <class _Lock> 1967a984708SDavid Chisnallvoid 1977a984708SDavid Chisnallcondition_variable_any::wait(_Lock& __lock) 1987a984708SDavid Chisnall{ 1997a984708SDavid Chisnall shared_ptr<mutex> __mut = __mut_; 2007a984708SDavid Chisnall unique_lock<mutex> __lk(*__mut); 2017a984708SDavid Chisnall __lock.unlock(); 2021e0896acSDavid Chisnall unique_ptr<_Lock, __lock_external> __lxx(&__lock); 2031e0896acSDavid Chisnall lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock); 2047a984708SDavid Chisnall __cv_.wait(__lk); 2057a984708SDavid Chisnall} // __mut_.unlock(), __lock.lock() 2067a984708SDavid Chisnall 2077a984708SDavid Chisnalltemplate <class _Lock, class _Predicate> 2089729cf09SDimitry Andricinline 2097a984708SDavid Chisnallvoid 2107a984708SDavid Chisnallcondition_variable_any::wait(_Lock& __lock, _Predicate __pred) 2117a984708SDavid Chisnall{ 2127a984708SDavid Chisnall while (!__pred()) 2137a984708SDavid Chisnall wait(__lock); 2147a984708SDavid Chisnall} 2157a984708SDavid Chisnall 2167a984708SDavid Chisnalltemplate <class _Lock, class _Clock, class _Duration> 2177a984708SDavid Chisnallcv_status 2187a984708SDavid Chisnallcondition_variable_any::wait_until(_Lock& __lock, 2197a984708SDavid Chisnall const chrono::time_point<_Clock, _Duration>& __t) 2207a984708SDavid Chisnall{ 2217a984708SDavid Chisnall shared_ptr<mutex> __mut = __mut_; 2227a984708SDavid Chisnall unique_lock<mutex> __lk(*__mut); 2237a984708SDavid Chisnall __lock.unlock(); 2241e0896acSDavid Chisnall unique_ptr<_Lock, __lock_external> __lxx(&__lock); 2251e0896acSDavid Chisnall lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock); 2267a984708SDavid Chisnall return __cv_.wait_until(__lk, __t); 2277a984708SDavid Chisnall} // __mut_.unlock(), __lock.lock() 2287a984708SDavid Chisnall 2297a984708SDavid Chisnalltemplate <class _Lock, class _Clock, class _Duration, class _Predicate> 2309729cf09SDimitry Andricinline 2317a984708SDavid Chisnallbool 2327a984708SDavid Chisnallcondition_variable_any::wait_until(_Lock& __lock, 2337a984708SDavid Chisnall const chrono::time_point<_Clock, _Duration>& __t, 2347a984708SDavid Chisnall _Predicate __pred) 2357a984708SDavid Chisnall{ 2367a984708SDavid Chisnall while (!__pred()) 2377a984708SDavid Chisnall if (wait_until(__lock, __t) == cv_status::timeout) 2387a984708SDavid Chisnall return __pred(); 2397a984708SDavid Chisnall return true; 2407a984708SDavid Chisnall} 2417a984708SDavid Chisnall 2427a984708SDavid Chisnalltemplate <class _Lock, class _Rep, class _Period> 2439729cf09SDimitry Andricinline 2447a984708SDavid Chisnallcv_status 2457a984708SDavid Chisnallcondition_variable_any::wait_for(_Lock& __lock, 2467a984708SDavid Chisnall const chrono::duration<_Rep, _Period>& __d) 2477a984708SDavid Chisnall{ 2487a984708SDavid Chisnall return wait_until(__lock, chrono::steady_clock::now() + __d); 2497a984708SDavid Chisnall} 2507a984708SDavid Chisnall 2517a984708SDavid Chisnalltemplate <class _Lock, class _Rep, class _Period, class _Predicate> 2529729cf09SDimitry Andricinline 2537a984708SDavid Chisnallbool 2547a984708SDavid Chisnallcondition_variable_any::wait_for(_Lock& __lock, 2557a984708SDavid Chisnall const chrono::duration<_Rep, _Period>& __d, 2567a984708SDavid Chisnall _Predicate __pred) 2577a984708SDavid Chisnall{ 2587a984708SDavid Chisnall return wait_until(__lock, chrono::steady_clock::now() + __d, 2597a984708SDavid Chisnall _VSTD::move(__pred)); 2607a984708SDavid Chisnall} 2617a984708SDavid Chisnall 2621bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS 2637a984708SDavid Chisnallvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); 2647a984708SDavid Chisnall 2657a984708SDavid Chisnall_LIBCPP_END_NAMESPACE_STD 2667a984708SDavid Chisnall 267d72607e9SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS 268d72607e9SDimitry Andric 2697a984708SDavid Chisnall#endif // _LIBCPP_CONDITION_VARIABLE 270