1// -*- C++ -*- 2//===---------------------- condition_variable ----------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is distributed under the University of Illinois Open Source 7// License. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10 11#ifndef _LIBCPP_CONDITION_VARIABLE 12#define _LIBCPP_CONDITION_VARIABLE 13 14/* 15 condition_variable synopsis 16 17namespace std 18{ 19 20enum class cv_status { no_timeout, timeout }; 21 22class condition_variable 23{ 24public: 25 condition_variable(); 26 ~condition_variable(); 27 28 condition_variable(const condition_variable&) = delete; 29 condition_variable& operator=(const condition_variable&) = delete; 30 31 void notify_one(); 32 void notify_all(); 33 34 void wait(unique_lock<mutex>& lock); 35 template <class Predicate> 36 void wait(unique_lock<mutex>& lock, Predicate pred); 37 38 template <class Clock, class Duration> 39 cv_status 40 wait_until(unique_lock<mutex>& lock, 41 const chrono::time_point<Clock, Duration>& abs_time); 42 43 template <class Clock, class Duration, class Predicate> 44 bool 45 wait_until(unique_lock<mutex>& lock, 46 const chrono::time_point<Clock, Duration>& abs_time, 47 Predicate pred); 48 49 template <class Rep, class Period> 50 cv_status 51 wait_for(unique_lock<mutex>& lock, 52 const chrono::duration<Rep, Period>& rel_time); 53 54 template <class Rep, class Period, class Predicate> 55 bool 56 wait_for(unique_lock<mutex>& lock, 57 const chrono::duration<Rep, Period>& rel_time, 58 Predicate pred); 59 60 typedef pthread_cond_t* native_handle_type; 61 native_handle_type native_handle(); 62}; 63 64class condition_variable_any 65{ 66public: 67 condition_variable_any(); 68 ~condition_variable_any(); 69 70 condition_variable_any(const condition_variable_any&) = delete; 71 condition_variable_any& operator=(const condition_variable_any&) = delete; 72 73 void notify_one(); 74 void notify_all(); 75 76 template <class Lock> 77 void wait(Lock& lock); 78 template <class Lock, class Predicate> 79 void wait(Lock& lock, Predicate pred); 80 81 template <class Lock, class Clock, class Duration> 82 cv_status 83 wait_until(Lock& lock, 84 const chrono::time_point<Clock, Duration>& abs_time); 85 86 template <class Lock, class Clock, class Duration, class Predicate> 87 bool 88 wait_until(Lock& lock, 89 const chrono::time_point<Clock, Duration>& abs_time, 90 Predicate pred); 91 92 template <class Lock, class Rep, class Period> 93 cv_status 94 wait_for(Lock& lock, 95 const chrono::duration<Rep, Period>& rel_time); 96 97 template <class Lock, class Rep, class Period, class Predicate> 98 bool 99 wait_for(Lock& lock, 100 const chrono::duration<Rep, Period>& rel_time, 101 Predicate pred); 102}; 103 104} // std 105 106*/ 107 108#include <__config> 109#include <__mutex_base> 110#include <memory> 111 112#pragma GCC system_header 113 114_LIBCPP_BEGIN_NAMESPACE_STD 115 116class condition_variable_any 117{ 118 condition_variable __cv_; 119 shared_ptr<mutex> __mut_; 120public: 121 condition_variable_any(); 122 123 void notify_one(); 124 void notify_all(); 125 126 template <class _Lock> 127 void wait(_Lock& __lock); 128 template <class _Lock, class _Predicate> 129 void wait(_Lock& __lock, _Predicate __pred); 130 131 template <class _Lock, class _Clock, class _Duration> 132 cv_status 133 wait_until(_Lock& __lock, 134 const chrono::time_point<_Clock, _Duration>& __t); 135 136 template <class _Lock, class _Clock, class _Duration, class _Predicate> 137 bool 138 wait_until(_Lock& __lock, 139 const chrono::time_point<_Clock, _Duration>& __t, 140 _Predicate __pred); 141 142 template <class _Lock, class _Rep, class _Period> 143 cv_status 144 wait_for(_Lock& __lock, 145 const chrono::duration<_Rep, _Period>& __d); 146 147 template <class _Lock, class _Rep, class _Period, class _Predicate> 148 bool 149 wait_for(_Lock& __lock, 150 const chrono::duration<_Rep, _Period>& __d, 151 _Predicate __pred); 152}; 153 154inline 155condition_variable_any::condition_variable_any() 156 : __mut_(make_shared<mutex>()) {} 157 158inline 159void 160condition_variable_any::notify_one() 161{ 162 {lock_guard<mutex> _(*__mut_);} 163 __cv_.notify_one(); 164} 165 166inline 167void 168condition_variable_any::notify_all() 169{ 170 {lock_guard<mutex> _(*__mut_);} 171 __cv_.notify_all(); 172} 173 174struct __lock_external 175{ 176 template <class _Lock> 177 void operator()(_Lock* __m) {__m->lock();} 178}; 179 180template <class _Lock> 181void 182condition_variable_any::wait(_Lock& __lock) 183{ 184 shared_ptr<mutex> __mut = __mut_; 185 unique_lock<mutex> __lk(*__mut); 186 __lock.unlock(); 187 unique_ptr<_Lock, __lock_external> __(&__lock); 188 lock_guard<unique_lock<mutex> > _(__lk, adopt_lock); 189 __cv_.wait(__lk); 190} // __mut_.unlock(), __lock.lock() 191 192template <class _Lock, class _Predicate> 193inline 194void 195condition_variable_any::wait(_Lock& __lock, _Predicate __pred) 196{ 197 while (!__pred()) 198 wait(__lock); 199} 200 201template <class _Lock, class _Clock, class _Duration> 202cv_status 203condition_variable_any::wait_until(_Lock& __lock, 204 const chrono::time_point<_Clock, _Duration>& __t) 205{ 206 shared_ptr<mutex> __mut = __mut_; 207 unique_lock<mutex> __lk(*__mut); 208 __lock.unlock(); 209 unique_ptr<_Lock, __lock_external> __(&__lock); 210 lock_guard<unique_lock<mutex> > _(__lk, adopt_lock); 211 return __cv_.wait_until(__lk, __t); 212} // __mut_.unlock(), __lock.lock() 213 214template <class _Lock, class _Clock, class _Duration, class _Predicate> 215inline 216bool 217condition_variable_any::wait_until(_Lock& __lock, 218 const chrono::time_point<_Clock, _Duration>& __t, 219 _Predicate __pred) 220{ 221 while (!__pred()) 222 if (wait_until(__lock, __t) == cv_status::timeout) 223 return __pred(); 224 return true; 225} 226 227template <class _Lock, class _Rep, class _Period> 228inline 229cv_status 230condition_variable_any::wait_for(_Lock& __lock, 231 const chrono::duration<_Rep, _Period>& __d) 232{ 233 return wait_until(__lock, chrono::monotonic_clock::now() + __d); 234} 235 236template <class _Lock, class _Rep, class _Period, class _Predicate> 237inline 238bool 239condition_variable_any::wait_for(_Lock& __lock, 240 const chrono::duration<_Rep, _Period>& __d, 241 _Predicate __pred) 242{ 243 return wait_until(__lock, chrono::monotonic_clock::now() + __d, 244 _STD::move(__pred)); 245} 246 247_LIBCPP_END_NAMESPACE_STD 248 249#endif // _LIBCPP_CONDITION_VARIABLE 250