blob: a4ac36161cbaa3682821c5484c38ae6ce68da83d [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:161// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Chandler Carruth7c3769d2019-01-19 10:56:404// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnantbc8d3f92010-05-11 19:42:167//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___MUTEX_BASE
11#define _LIBCPP___MUTEX_BASE
12
13#include <__config>
14#include <chrono>
15#include <system_error>
Asiri Rathnayake35ff03b2016-05-06 14:06:2916#include <__threading_support>
Eric Fiselier018a3d52017-05-31 22:07:4917
Dan Alberta4ccec72019-09-18 18:13:3218#include <time.h>
Howard Hinnantbc8d3f92010-05-11 19:42:1619
Howard Hinnant08e17472011-10-17 20:05:1020#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:1621#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:1022#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1623
Eric Fiselier018a3d52017-05-31 22:07:4924_LIBCPP_PUSH_MACROS
25#include <__undef_macros>
26
27
Howard Hinnantbc8d3f92010-05-11 19:42:1628_LIBCPP_BEGIN_NAMESPACE_STD
29
Jonathan Roelofs8d86b2e2014-09-05 19:45:0530#ifndef _LIBCPP_HAS_NO_THREADS
31
Eric Fiseliera15e8c32016-03-16 02:30:0632#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
33# ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
34# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
35# else
36# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
37# endif
38#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION
39
Eric Fiselier47e6bb82019-07-07 01:20:5440
Eric Fiseliera15e8c32016-03-16 02:30:0641class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
Howard Hinnantbc8d3f92010-05-11 19:42:1642{
Marshall Clow65eb1e92016-07-18 17:23:0643 __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
Howard Hinnantbc8d3f92010-05-11 19:42:1644
45public:
Howard Hinnant333f50d2010-09-21 20:16:3746 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier47e6bb82019-07-07 01:20:5447 _LIBCPP_CONSTEXPR mutex() = default;
48
49 mutex(const mutex&) = delete;
50 mutex& operator=(const mutex&) = delete;
51
52#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION)
53 ~mutex() = default;
Howard Hinnant384608e2012-07-07 20:01:5254#else
Richard Smith8a590a42019-04-25 20:00:0655 ~mutex() _NOEXCEPT;
Eric Fiselier47e6bb82019-07-07 01:20:5456#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1657
Eric Fiseliera15e8c32016-03-16 02:30:0658 void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
59 bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
60 void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
Howard Hinnantbc8d3f92010-05-11 19:42:1661
Asiri Rathnayake35ff03b2016-05-06 14:06:2962 typedef __libcpp_mutex_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:3763 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:1664};
65
Eric Fiselier276a69c2017-06-07 20:47:4266static_assert(is_nothrow_default_constructible<mutex>::value,
67 "the default constructor for std::mutex must be nothrow");
68
Howard Hinnant83eade62013-03-06 23:30:1969struct _LIBCPP_TYPE_VIS defer_lock_t {};
70struct _LIBCPP_TYPE_VIS try_to_lock_t {};
71struct _LIBCPP_TYPE_VIS adopt_lock_t {};
Howard Hinnantbc8d3f92010-05-11 19:42:1672
Louis Dionne6952d142018-08-01 02:08:5973#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
Howard Hinnantbc8d3f92010-05-11 19:42:1674
Louis Dionne07f95bd2018-10-25 12:13:4375extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock;
76extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
77extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock;
Howard Hinnantbc8d3f92010-05-11 19:42:1678
Howard Hinnant499c61f2012-07-21 16:13:0979#else
80
Marshall Clow97adf8a2018-01-02 19:23:3081/* _LIBCPP_INLINE_VAR */ constexpr defer_lock_t defer_lock = defer_lock_t();
82/* _LIBCPP_INLINE_VAR */ constexpr try_to_lock_t try_to_lock = try_to_lock_t();
83/* _LIBCPP_INLINE_VAR */ constexpr adopt_lock_t adopt_lock = adopt_lock_t();
Howard Hinnant499c61f2012-07-21 16:13:0984
85#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1686
87template <class _Mutex>
Eric Fiselierc3589a82017-01-04 23:56:0088class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
Eric Fiselier10b52a02016-06-14 03:48:0989lock_guard
Howard Hinnantbc8d3f92010-05-11 19:42:1690{
91public:
92 typedef _Mutex mutex_type;
93
94private:
95 mutex_type& __m_;
96public:
97
Louis Dionne22eff1a2019-08-13 11:12:2898 _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY
Eric Fiseliera15e8c32016-03-16 02:30:0699 explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
Howard Hinnantbc8d3f92010-05-11 19:42:16100 : __m_(__m) {__m_.lock();}
Louis Dionne22eff1a2019-08-13 11:12:28101
102 _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY
Eric Fiseliera15e8c32016-03-16 02:30:06103 lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
Howard Hinnantbc8d3f92010-05-11 19:42:16104 : __m_(__m) {}
Howard Hinnant333f50d2010-09-21 20:16:37105 _LIBCPP_INLINE_VISIBILITY
Eric Fiseliera15e8c32016-03-16 02:30:06106 ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
Howard Hinnantbc8d3f92010-05-11 19:42:16107
108private:
Eric Fiselier10b52a02016-06-14 03:48:09109 lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
110 lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
Howard Hinnantbc8d3f92010-05-11 19:42:16111};
112
113template <class _Mutex>
Eric Fiselierc3589a82017-01-04 23:56:00114class _LIBCPP_TEMPLATE_VIS unique_lock
Howard Hinnantbc8d3f92010-05-11 19:42:16115{
116public:
117 typedef _Mutex mutex_type;
118
119private:
120 mutex_type* __m_;
121 bool __owns_;
122
123public:
Howard Hinnant333f50d2010-09-21 20:16:37124 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09125 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37126 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16127 explicit unique_lock(mutex_type& __m)
Marshall Clow81652492016-04-13 17:02:23128 : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
Howard Hinnant333f50d2010-09-21 20:16:37129 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09130 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
Marshall Clow81652492016-04-13 17:02:23131 : __m_(_VSTD::addressof(__m)), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37132 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16133 unique_lock(mutex_type& __m, try_to_lock_t)
Marshall Clow81652492016-04-13 17:02:23134 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
Howard Hinnant333f50d2010-09-21 20:16:37135 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16136 unique_lock(mutex_type& __m, adopt_lock_t)
Marshall Clow81652492016-04-13 17:02:23137 : __m_(_VSTD::addressof(__m)), __owns_(true) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16138 template <class _Clock, class _Duration>
Howard Hinnant333f50d2010-09-21 20:16:37139 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16140 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
Marshall Clow81652492016-04-13 17:02:23141 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16142 template <class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37143 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16144 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
Marshall Clow81652492016-04-13 17:02:23145 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
Howard Hinnant333f50d2010-09-21 20:16:37146 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16147 ~unique_lock()
148 {
149 if (__owns_)
150 __m_->unlock();
151 }
152
153private:
154 unique_lock(unique_lock const&); // = delete;
155 unique_lock& operator=(unique_lock const&); // = delete;
156
157public:
Eric Fiselier690d9992017-04-18 23:05:08158#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant333f50d2010-09-21 20:16:37159 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09160 unique_lock(unique_lock&& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16161 : __m_(__u.__m_), __owns_(__u.__owns_)
162 {__u.__m_ = nullptr; __u.__owns_ = false;}
Howard Hinnant333f50d2010-09-21 20:16:37163 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09164 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16165 {
166 if (__owns_)
167 __m_->unlock();
168 __m_ = __u.__m_;
169 __owns_ = __u.__owns_;
170 __u.__m_ = nullptr;
171 __u.__owns_ = false;
172 return *this;
173 }
Howard Hinnantac417fa2010-11-28 19:41:07174
Eric Fiselier690d9992017-04-18 23:05:08175#endif // _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16176
177 void lock();
178 bool try_lock();
179
180 template <class _Rep, class _Period>
181 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
182 template <class _Clock, class _Duration>
183 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
184
185 void unlock();
186
Howard Hinnant333f50d2010-09-21 20:16:37187 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09188 void swap(unique_lock& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16189 {
Howard Hinnant0949eed2011-06-30 21:18:19190 _VSTD::swap(__m_, __u.__m_);
191 _VSTD::swap(__owns_, __u.__owns_);
Howard Hinnantbc8d3f92010-05-11 19:42:16192 }
Howard Hinnant333f50d2010-09-21 20:16:37193 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09194 mutex_type* release() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16195 {
196 mutex_type* __m = __m_;
197 __m_ = nullptr;
198 __owns_ = false;
199 return __m;
200 }
201
Howard Hinnant333f50d2010-09-21 20:16:37202 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09203 bool owns_lock() const _NOEXCEPT {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37204 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant77861882012-02-21 21:46:43205 _LIBCPP_EXPLICIT
Howard Hinnant499c61f2012-07-21 16:13:09206 operator bool () const _NOEXCEPT {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37207 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09208 mutex_type* mutex() const _NOEXCEPT {return __m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16209};
210
211template <class _Mutex>
212void
213unique_lock<_Mutex>::lock()
214{
215 if (__m_ == nullptr)
216 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
217 if (__owns_)
218 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
219 __m_->lock();
220 __owns_ = true;
221}
222
223template <class _Mutex>
224bool
225unique_lock<_Mutex>::try_lock()
226{
227 if (__m_ == nullptr)
228 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
229 if (__owns_)
230 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
231 __owns_ = __m_->try_lock();
232 return __owns_;
233}
234
235template <class _Mutex>
236template <class _Rep, class _Period>
237bool
238unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
239{
240 if (__m_ == nullptr)
241 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
242 if (__owns_)
243 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
244 __owns_ = __m_->try_lock_for(__d);
245 return __owns_;
246}
247
248template <class _Mutex>
249template <class _Clock, class _Duration>
250bool
251unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
252{
253 if (__m_ == nullptr)
254 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
255 if (__owns_)
256 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
257 __owns_ = __m_->try_lock_until(__t);
258 return __owns_;
259}
260
261template <class _Mutex>
262void
263unique_lock<_Mutex>::unlock()
264{
265 if (!__owns_)
266 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
267 __m_->unlock();
268 __owns_ = false;
269}
270
271template <class _Mutex>
Howard Hinnant333f50d2010-09-21 20:16:37272inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16273void
Howard Hinnant499c61f2012-07-21 16:13:09274swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
275 {__x.swap(__y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16276
Marshall Clow239bc422013-12-23 22:14:27277//enum class cv_status
278_LIBCPP_DECLARE_STRONG_ENUM(cv_status)
Howard Hinnantbc8d3f92010-05-11 19:42:16279{
Marshall Clow239bc422013-12-23 22:14:27280 no_timeout,
281 timeout
Howard Hinnantbc8d3f92010-05-11 19:42:16282};
Marshall Clow239bc422013-12-23 22:14:27283_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
Howard Hinnantbc8d3f92010-05-11 19:42:16284
Howard Hinnant83eade62013-03-06 23:30:19285class _LIBCPP_TYPE_VIS condition_variable
Howard Hinnantbc8d3f92010-05-11 19:42:16286{
Marshall Clow65eb1e92016-07-18 17:23:06287 __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
Howard Hinnantbc8d3f92010-05-11 19:42:16288public:
Howard Hinnant333f50d2010-09-21 20:16:37289 _LIBCPP_INLINE_VISIBILITY
Eric Fiseliera3863692019-07-07 17:24:03290 _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
291
292#ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
293 ~condition_variable() = default;
Howard Hinnant384608e2012-07-07 20:01:52294#else
Howard Hinnantbc8d3f92010-05-11 19:42:16295 ~condition_variable();
Eric Fiseliera3863692019-07-07 17:24:03296#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16297
Eric Fiseliera3863692019-07-07 17:24:03298 condition_variable(const condition_variable&) = delete;
299 condition_variable& operator=(const condition_variable&) = delete;
Howard Hinnantbc8d3f92010-05-11 19:42:16300
Howard Hinnantc8f74132012-07-21 16:32:53301 void notify_one() _NOEXCEPT;
302 void notify_all() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16303
Marshall Clowb0767852014-03-26 02:45:04304 void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16305 template <class _Predicate>
Shoaib Meenai6b734922017-03-02 03:22:18306 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
Howard Hinnantbc8d3f92010-05-11 19:42:16307 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
308
Howard Hinnantbc8d3f92010-05-11 19:42:16309 template <class _Clock, class _Duration>
Shoaib Meenai6b734922017-03-02 03:22:18310 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
Howard Hinnantbc8d3f92010-05-11 19:42:16311 cv_status
312 wait_until(unique_lock<mutex>& __lk,
313 const chrono::time_point<_Clock, _Duration>& __t);
314
315 template <class _Clock, class _Duration, class _Predicate>
Shoaib Meenai6b734922017-03-02 03:22:18316 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
Howard Hinnantbc8d3f92010-05-11 19:42:16317 bool
318 wait_until(unique_lock<mutex>& __lk,
319 const chrono::time_point<_Clock, _Duration>& __t,
320 _Predicate __pred);
321
322 template <class _Rep, class _Period>
Shoaib Meenai6b734922017-03-02 03:22:18323 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
Howard Hinnantbc8d3f92010-05-11 19:42:16324 cv_status
325 wait_for(unique_lock<mutex>& __lk,
326 const chrono::duration<_Rep, _Period>& __d);
327
328 template <class _Rep, class _Period, class _Predicate>
329 bool
Evgeniy Stepanova3b25f82015-11-07 01:22:13330 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16331 wait_for(unique_lock<mutex>& __lk,
332 const chrono::duration<_Rep, _Period>& __d,
333 _Predicate __pred);
334
Asiri Rathnayake35ff03b2016-05-06 14:06:29335 typedef __libcpp_condvar_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:37336 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16337
338private:
339 void __do_timed_wait(unique_lock<mutex>& __lk,
Marshall Clowb0767852014-03-26 02:45:04340 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
Dan Alberta4ccec72019-09-18 18:13:32341#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
342 void __do_timed_wait(unique_lock<mutex>& __lk,
343 chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
344#endif
345 template <class _Clock>
346 void __do_timed_wait(unique_lock<mutex>& __lk,
347 chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16348};
Jonathan Roelofs8d86b2e2014-09-05 19:45:05349#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnantbc8d3f92010-05-11 19:42:16350
Dan Alberta4ccec72019-09-18 18:13:32351template <class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37352inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16353typename enable_if
354<
Dan Alberta4ccec72019-09-18 18:13:32355 is_floating_point<_Rep>::value,
356 chrono::nanoseconds
Howard Hinnantbc8d3f92010-05-11 19:42:16357>::type
Dan Alberta4ccec72019-09-18 18:13:32358__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d)
Howard Hinnantbc8d3f92010-05-11 19:42:16359{
360 using namespace chrono;
Dan Alberta4ccec72019-09-18 18:13:32361 using __ratio = ratio_divide<_Period, nano>;
362 using __ns_rep = nanoseconds::rep;
363 _Rep __result_float = __d.count() * __ratio::num / __ratio::den;
364
365 _Rep __result_max = numeric_limits<__ns_rep>::max();
366 if (__result_float >= __result_max) {
367 return nanoseconds::max();
368 }
369
370 _Rep __result_min = numeric_limits<__ns_rep>::min();
371 if (__result_float <= __result_min) {
372 return nanoseconds::min();
373 }
374
375 return nanoseconds(static_cast<__ns_rep>(__result_float));
376}
377
378template <class _Rep, class _Period>
379inline _LIBCPP_INLINE_VISIBILITY
380typename enable_if
381<
382 !is_floating_point<_Rep>::value,
383 chrono::nanoseconds
384>::type
385__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d)
386{
387 using namespace chrono;
388 if (__d.count() == 0) {
389 return nanoseconds(0);
390 }
391
392 using __ratio = ratio_divide<_Period, nano>;
393 using __ns_rep = nanoseconds::rep;
394 __ns_rep __result_max = std::numeric_limits<__ns_rep>::max();
395 if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) {
396 return nanoseconds::max();
397 }
398
399 __ns_rep __result_min = std::numeric_limits<__ns_rep>::min();
400 if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) {
401 return nanoseconds::min();
402 }
403
404 __ns_rep __result = __d.count() * __ratio::num / __ratio::den;
405 if (__result == 0) {
406 return nanoseconds(1);
407 }
408
409 return nanoseconds(__result);
Howard Hinnantbc8d3f92010-05-11 19:42:16410}
411
Jonathan Roelofs8d86b2e2014-09-05 19:45:05412#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantbc8d3f92010-05-11 19:42:16413template <class _Predicate>
414void
415condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
416{
417 while (!__pred())
418 wait(__lk);
419}
420
Howard Hinnantbc8d3f92010-05-11 19:42:16421template <class _Clock, class _Duration>
422cv_status
423condition_variable::wait_until(unique_lock<mutex>& __lk,
424 const chrono::time_point<_Clock, _Duration>& __t)
425{
426 using namespace chrono;
Dan Alberta4ccec72019-09-18 18:13:32427 using __clock_tp_ns = time_point<_Clock, nanoseconds>;
428
429 typename _Clock::time_point __now = _Clock::now();
430 if (__t <= __now)
431 return cv_status::timeout;
432
433 __clock_tp_ns __t_ns = __clock_tp_ns(__safe_nanosecond_cast(__t.time_since_epoch()));
434
435 __do_timed_wait(__lk, __t_ns);
Howard Hinnantbc8d3f92010-05-11 19:42:16436 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
437}
438
439template <class _Clock, class _Duration, class _Predicate>
440bool
441condition_variable::wait_until(unique_lock<mutex>& __lk,
442 const chrono::time_point<_Clock, _Duration>& __t,
443 _Predicate __pred)
444{
445 while (!__pred())
446 {
447 if (wait_until(__lk, __t) == cv_status::timeout)
448 return __pred();
449 }
450 return true;
451}
452
453template <class _Rep, class _Period>
454cv_status
455condition_variable::wait_for(unique_lock<mutex>& __lk,
456 const chrono::duration<_Rep, _Period>& __d)
457{
458 using namespace chrono;
Howard Hinnantcf115d22012-08-30 19:14:33459 if (__d <= __d.zero())
460 return cv_status::timeout;
Dan Alberta4ccec72019-09-18 18:13:32461 using __ns_rep = nanoseconds::rep;
Howard Hinnantf8f85212010-11-20 19:16:30462 steady_clock::time_point __c_now = steady_clock::now();
Dan Alberta4ccec72019-09-18 18:13:32463
464#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
465 using __clock_tp_ns = time_point<steady_clock, nanoseconds>;
466 __ns_rep __now_count_ns = __safe_nanosecond_cast(__c_now.time_since_epoch()).count();
467#else
468 using __clock_tp_ns = time_point<system_clock, nanoseconds>;
469 __ns_rep __now_count_ns = __safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
470#endif
471
472 __ns_rep __d_ns_count = __safe_nanosecond_cast(__d).count();
473
474 if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
475 __do_timed_wait(__lk, __clock_tp_ns::max());
476 } else {
477 __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
478 }
479
Howard Hinnantf8f85212010-11-20 19:16:30480 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
481 cv_status::timeout;
Howard Hinnantbc8d3f92010-05-11 19:42:16482}
483
484template <class _Rep, class _Period, class _Predicate>
Evgeniy Stepanova3b25f82015-11-07 01:22:13485inline
Howard Hinnantbc8d3f92010-05-11 19:42:16486bool
487condition_variable::wait_for(unique_lock<mutex>& __lk,
488 const chrono::duration<_Rep, _Period>& __d,
489 _Predicate __pred)
490{
Howard Hinnantf8f85212010-11-20 19:16:30491 return wait_until(__lk, chrono::steady_clock::now() + __d,
Howard Hinnant0949eed2011-06-30 21:18:19492 _VSTD::move(__pred));
Howard Hinnantbc8d3f92010-05-11 19:42:16493}
494
Dan Alberta4ccec72019-09-18 18:13:32495#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
496inline
497void
498condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
499 chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT
500{
501 using namespace chrono;
502 if (!__lk.owns_lock())
503 __throw_system_error(EPERM,
504 "condition_variable::timed wait: mutex not locked");
505 nanoseconds __d = __tp.time_since_epoch();
506 timespec __ts;
507 seconds __s = duration_cast<seconds>(__d);
508 using __ts_sec = decltype(__ts.tv_sec);
509 const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
510 if (__s.count() < __ts_sec_max)
511 {
512 __ts.tv_sec = static_cast<__ts_sec>(__s.count());
513 __ts.tv_nsec = (__d - __s).count();
514 }
515 else
516 {
517 __ts.tv_sec = __ts_sec_max;
518 __ts.tv_nsec = giga::num - 1;
519 }
520 int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts);
521 if (__ec != 0 && __ec != ETIMEDOUT)
522 __throw_system_error(__ec, "condition_variable timed_wait failed");
523}
524#endif // _LIBCPP_HAS_COND_CLOCKWAIT
525
526template <class _Clock>
527inline
528void
529condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
530 chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT
531{
532 wait_for(__lk, __tp - _Clock::now());
533}
534
Jonathan Roelofs8d86b2e2014-09-05 19:45:05535#endif // !_LIBCPP_HAS_NO_THREADS
536
Howard Hinnantbc8d3f92010-05-11 19:42:16537_LIBCPP_END_NAMESPACE_STD
538
Eric Fiselier018a3d52017-05-31 22:07:49539_LIBCPP_POP_MACROS
540
Howard Hinnantbc8d3f92010-05-11 19:42:16541#endif // _LIBCPP___MUTEX_BASE