1*0b57cec5SDimitry Andric// -*- C++ -*- 2*0b57cec5SDimitry Andric//===---------------------- condition_variable ----------------------------===// 3*0b57cec5SDimitry Andric// 4*0b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*0b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 6*0b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*0b57cec5SDimitry Andric// 8*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 9*0b57cec5SDimitry Andric 10*0b57cec5SDimitry Andric#ifndef _LIBCPP_CONDITION_VARIABLE 11*0b57cec5SDimitry Andric#define _LIBCPP_CONDITION_VARIABLE 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric/* 14*0b57cec5SDimitry Andric condition_variable synopsis 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andricnamespace std 17*0b57cec5SDimitry Andric{ 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andricenum class cv_status { no_timeout, timeout }; 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andricclass condition_variable 22*0b57cec5SDimitry Andric{ 23*0b57cec5SDimitry Andricpublic: 24*0b57cec5SDimitry Andric condition_variable(); 25*0b57cec5SDimitry Andric ~condition_variable(); 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric condition_variable(const condition_variable&) = delete; 28*0b57cec5SDimitry Andric condition_variable& operator=(const condition_variable&) = delete; 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric void notify_one() noexcept; 31*0b57cec5SDimitry Andric void notify_all() noexcept; 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric void wait(unique_lock<mutex>& lock); 34*0b57cec5SDimitry Andric template <class Predicate> 35*0b57cec5SDimitry Andric void wait(unique_lock<mutex>& lock, Predicate pred); 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric template <class Clock, class Duration> 38*0b57cec5SDimitry Andric cv_status 39*0b57cec5SDimitry Andric wait_until(unique_lock<mutex>& lock, 40*0b57cec5SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time); 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric template <class Clock, class Duration, class Predicate> 43*0b57cec5SDimitry Andric bool 44*0b57cec5SDimitry Andric wait_until(unique_lock<mutex>& lock, 45*0b57cec5SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time, 46*0b57cec5SDimitry Andric Predicate pred); 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric template <class Rep, class Period> 49*0b57cec5SDimitry Andric cv_status 50*0b57cec5SDimitry Andric wait_for(unique_lock<mutex>& lock, 51*0b57cec5SDimitry Andric const chrono::duration<Rep, Period>& rel_time); 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric template <class Rep, class Period, class Predicate> 54*0b57cec5SDimitry Andric bool 55*0b57cec5SDimitry Andric wait_for(unique_lock<mutex>& lock, 56*0b57cec5SDimitry Andric const chrono::duration<Rep, Period>& rel_time, 57*0b57cec5SDimitry Andric Predicate pred); 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric typedef pthread_cond_t* native_handle_type; 60*0b57cec5SDimitry Andric native_handle_type native_handle(); 61*0b57cec5SDimitry Andric}; 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andricvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andricclass condition_variable_any 66*0b57cec5SDimitry Andric{ 67*0b57cec5SDimitry Andricpublic: 68*0b57cec5SDimitry Andric condition_variable_any(); 69*0b57cec5SDimitry Andric ~condition_variable_any(); 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric condition_variable_any(const condition_variable_any&) = delete; 72*0b57cec5SDimitry Andric condition_variable_any& operator=(const condition_variable_any&) = delete; 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric void notify_one() noexcept; 75*0b57cec5SDimitry Andric void notify_all() noexcept; 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric template <class Lock> 78*0b57cec5SDimitry Andric void wait(Lock& lock); 79*0b57cec5SDimitry Andric template <class Lock, class Predicate> 80*0b57cec5SDimitry Andric void wait(Lock& lock, Predicate pred); 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric template <class Lock, class Clock, class Duration> 83*0b57cec5SDimitry Andric cv_status 84*0b57cec5SDimitry Andric wait_until(Lock& lock, 85*0b57cec5SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time); 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric template <class Lock, class Clock, class Duration, class Predicate> 88*0b57cec5SDimitry Andric bool 89*0b57cec5SDimitry Andric wait_until(Lock& lock, 90*0b57cec5SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time, 91*0b57cec5SDimitry Andric Predicate pred); 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric template <class Lock, class Rep, class Period> 94*0b57cec5SDimitry Andric cv_status 95*0b57cec5SDimitry Andric wait_for(Lock& lock, 96*0b57cec5SDimitry Andric const chrono::duration<Rep, Period>& rel_time); 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric template <class Lock, class Rep, class Period, class Predicate> 99*0b57cec5SDimitry Andric bool 100*0b57cec5SDimitry Andric wait_for(Lock& lock, 101*0b57cec5SDimitry Andric const chrono::duration<Rep, Period>& rel_time, 102*0b57cec5SDimitry Andric Predicate pred); 103*0b57cec5SDimitry Andric}; 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric} // std 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric*/ 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric#include <__config> 110*0b57cec5SDimitry Andric#include <__mutex_base> 111*0b57cec5SDimitry Andric#include <memory> 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 114*0b57cec5SDimitry Andric#pragma GCC system_header 115*0b57cec5SDimitry Andric#endif 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS condition_variable_any 122*0b57cec5SDimitry Andric{ 123*0b57cec5SDimitry Andric condition_variable __cv_; 124*0b57cec5SDimitry Andric shared_ptr<mutex> __mut_; 125*0b57cec5SDimitry Andricpublic: 126*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 127*0b57cec5SDimitry Andric condition_variable_any(); 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 130*0b57cec5SDimitry Andric void notify_one() _NOEXCEPT; 131*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 132*0b57cec5SDimitry Andric void notify_all() _NOEXCEPT; 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric template <class _Lock> 135*0b57cec5SDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 136*0b57cec5SDimitry Andric void wait(_Lock& __lock); 137*0b57cec5SDimitry Andric template <class _Lock, class _Predicate> 138*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 139*0b57cec5SDimitry Andric void wait(_Lock& __lock, _Predicate __pred); 140*0b57cec5SDimitry Andric 141*0b57cec5SDimitry Andric template <class _Lock, class _Clock, class _Duration> 142*0b57cec5SDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 143*0b57cec5SDimitry Andric cv_status 144*0b57cec5SDimitry Andric wait_until(_Lock& __lock, 145*0b57cec5SDimitry Andric const chrono::time_point<_Clock, _Duration>& __t); 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric template <class _Lock, class _Clock, class _Duration, class _Predicate> 148*0b57cec5SDimitry Andric bool 149*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 150*0b57cec5SDimitry Andric wait_until(_Lock& __lock, 151*0b57cec5SDimitry Andric const chrono::time_point<_Clock, _Duration>& __t, 152*0b57cec5SDimitry Andric _Predicate __pred); 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric template <class _Lock, class _Rep, class _Period> 155*0b57cec5SDimitry Andric cv_status 156*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 157*0b57cec5SDimitry Andric wait_for(_Lock& __lock, 158*0b57cec5SDimitry Andric const chrono::duration<_Rep, _Period>& __d); 159*0b57cec5SDimitry Andric 160*0b57cec5SDimitry Andric template <class _Lock, class _Rep, class _Period, class _Predicate> 161*0b57cec5SDimitry Andric bool 162*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 163*0b57cec5SDimitry Andric wait_for(_Lock& __lock, 164*0b57cec5SDimitry Andric const chrono::duration<_Rep, _Period>& __d, 165*0b57cec5SDimitry Andric _Predicate __pred); 166*0b57cec5SDimitry Andric}; 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andricinline 169*0b57cec5SDimitry Andriccondition_variable_any::condition_variable_any() 170*0b57cec5SDimitry Andric : __mut_(make_shared<mutex>()) {} 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andricinline 173*0b57cec5SDimitry Andricvoid 174*0b57cec5SDimitry Andriccondition_variable_any::notify_one() _NOEXCEPT 175*0b57cec5SDimitry Andric{ 176*0b57cec5SDimitry Andric {lock_guard<mutex> __lx(*__mut_);} 177*0b57cec5SDimitry Andric __cv_.notify_one(); 178*0b57cec5SDimitry Andric} 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andricinline 181*0b57cec5SDimitry Andricvoid 182*0b57cec5SDimitry Andriccondition_variable_any::notify_all() _NOEXCEPT 183*0b57cec5SDimitry Andric{ 184*0b57cec5SDimitry Andric {lock_guard<mutex> __lx(*__mut_);} 185*0b57cec5SDimitry Andric __cv_.notify_all(); 186*0b57cec5SDimitry Andric} 187*0b57cec5SDimitry Andric 188*0b57cec5SDimitry Andricstruct __lock_external 189*0b57cec5SDimitry Andric{ 190*0b57cec5SDimitry Andric template <class _Lock> 191*0b57cec5SDimitry Andric void operator()(_Lock* __m) {__m->lock();} 192*0b57cec5SDimitry Andric}; 193*0b57cec5SDimitry Andric 194*0b57cec5SDimitry Andrictemplate <class _Lock> 195*0b57cec5SDimitry Andricvoid 196*0b57cec5SDimitry Andriccondition_variable_any::wait(_Lock& __lock) 197*0b57cec5SDimitry Andric{ 198*0b57cec5SDimitry Andric shared_ptr<mutex> __mut = __mut_; 199*0b57cec5SDimitry Andric unique_lock<mutex> __lk(*__mut); 200*0b57cec5SDimitry Andric __lock.unlock(); 201*0b57cec5SDimitry Andric unique_ptr<_Lock, __lock_external> __lxx(&__lock); 202*0b57cec5SDimitry Andric lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock); 203*0b57cec5SDimitry Andric __cv_.wait(__lk); 204*0b57cec5SDimitry Andric} // __mut_.unlock(), __lock.lock() 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andrictemplate <class _Lock, class _Predicate> 207*0b57cec5SDimitry Andricinline 208*0b57cec5SDimitry Andricvoid 209*0b57cec5SDimitry Andriccondition_variable_any::wait(_Lock& __lock, _Predicate __pred) 210*0b57cec5SDimitry Andric{ 211*0b57cec5SDimitry Andric while (!__pred()) 212*0b57cec5SDimitry Andric wait(__lock); 213*0b57cec5SDimitry Andric} 214*0b57cec5SDimitry Andric 215*0b57cec5SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration> 216*0b57cec5SDimitry Andriccv_status 217*0b57cec5SDimitry Andriccondition_variable_any::wait_until(_Lock& __lock, 218*0b57cec5SDimitry Andric const chrono::time_point<_Clock, _Duration>& __t) 219*0b57cec5SDimitry Andric{ 220*0b57cec5SDimitry Andric shared_ptr<mutex> __mut = __mut_; 221*0b57cec5SDimitry Andric unique_lock<mutex> __lk(*__mut); 222*0b57cec5SDimitry Andric __lock.unlock(); 223*0b57cec5SDimitry Andric unique_ptr<_Lock, __lock_external> __lxx(&__lock); 224*0b57cec5SDimitry Andric lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock); 225*0b57cec5SDimitry Andric return __cv_.wait_until(__lk, __t); 226*0b57cec5SDimitry Andric} // __mut_.unlock(), __lock.lock() 227*0b57cec5SDimitry Andric 228*0b57cec5SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration, class _Predicate> 229*0b57cec5SDimitry Andricinline 230*0b57cec5SDimitry Andricbool 231*0b57cec5SDimitry Andriccondition_variable_any::wait_until(_Lock& __lock, 232*0b57cec5SDimitry Andric const chrono::time_point<_Clock, _Duration>& __t, 233*0b57cec5SDimitry Andric _Predicate __pred) 234*0b57cec5SDimitry Andric{ 235*0b57cec5SDimitry Andric while (!__pred()) 236*0b57cec5SDimitry Andric if (wait_until(__lock, __t) == cv_status::timeout) 237*0b57cec5SDimitry Andric return __pred(); 238*0b57cec5SDimitry Andric return true; 239*0b57cec5SDimitry Andric} 240*0b57cec5SDimitry Andric 241*0b57cec5SDimitry Andrictemplate <class _Lock, class _Rep, class _Period> 242*0b57cec5SDimitry Andricinline 243*0b57cec5SDimitry Andriccv_status 244*0b57cec5SDimitry Andriccondition_variable_any::wait_for(_Lock& __lock, 245*0b57cec5SDimitry Andric const chrono::duration<_Rep, _Period>& __d) 246*0b57cec5SDimitry Andric{ 247*0b57cec5SDimitry Andric return wait_until(__lock, chrono::steady_clock::now() + __d); 248*0b57cec5SDimitry Andric} 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andrictemplate <class _Lock, class _Rep, class _Period, class _Predicate> 251*0b57cec5SDimitry Andricinline 252*0b57cec5SDimitry Andricbool 253*0b57cec5SDimitry Andriccondition_variable_any::wait_for(_Lock& __lock, 254*0b57cec5SDimitry Andric const chrono::duration<_Rep, _Period>& __d, 255*0b57cec5SDimitry Andric _Predicate __pred) 256*0b57cec5SDimitry Andric{ 257*0b57cec5SDimitry Andric return wait_until(__lock, chrono::steady_clock::now() + __d, 258*0b57cec5SDimitry Andric _VSTD::move(__pred)); 259*0b57cec5SDimitry Andric} 260*0b57cec5SDimitry Andric 261*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS 262*0b57cec5SDimitry Andricvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); 263*0b57cec5SDimitry Andric 264*0b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS 267*0b57cec5SDimitry Andric 268*0b57cec5SDimitry Andric#endif // _LIBCPP_CONDITION_VARIABLE 269