condition_variable 7.5 KB

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