2 //===----------------------------------------------------------------------===//
4 // The LLVM Compiler Infrastructure
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #ifndef _LIBCPP___MUTEX_BASE
12 #define _LIBCPP___MUTEX_BASE
16 #include <system_error>
17 #include <__threading_support>
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #pragma GCC system_header
23 _LIBCPP_BEGIN_NAMESPACE_STD
25 #ifndef _LIBCPP_HAS_NO_THREADS
27 #ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
28 # ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
29 # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
31 # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
33 #endif // _LIBCPP_THREAD_SAFETY_ANNOTATION
35 class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
37 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
38 __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
40 __libcpp_mutex_t __m_;
44 _LIBCPP_INLINE_VISIBILITY
45 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
46 constexpr mutex() _NOEXCEPT = default;
48 mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;}
53 mutex(const mutex&);// = delete;
54 mutex& operator=(const mutex&);// = delete;
57 void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
58 bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
59 void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
61 typedef __libcpp_mutex_t* native_handle_type;
62 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
65 struct _LIBCPP_TYPE_VIS defer_lock_t {};
66 struct _LIBCPP_TYPE_VIS try_to_lock_t {};
67 struct _LIBCPP_TYPE_VIS adopt_lock_t {};
69 #if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
71 extern const defer_lock_t defer_lock;
72 extern const try_to_lock_t try_to_lock;
73 extern const adopt_lock_t adopt_lock;
77 constexpr defer_lock_t defer_lock = defer_lock_t();
78 constexpr try_to_lock_t try_to_lock = try_to_lock_t();
79 constexpr adopt_lock_t adopt_lock = adopt_lock_t();
84 // Forward declare lock_guard as a variadic template even in C++03 to keep
85 // the mangling consistent between dialects.
86 #if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
87 template <class ..._Mutexes>
88 class _LIBCPP_TEMPLATE_VIS lock_guard;
91 template <class _Mutex>
92 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
93 #if !defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
100 typedef _Mutex mutex_type;
106 _LIBCPP_INLINE_VISIBILITY
107 explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
108 : __m_(__m) {__m_.lock();}
109 _LIBCPP_INLINE_VISIBILITY
110 lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
112 _LIBCPP_INLINE_VISIBILITY
113 ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
116 lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
117 lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
120 template <class _Mutex>
121 class _LIBCPP_TEMPLATE_VIS unique_lock
124 typedef _Mutex mutex_type;
131 _LIBCPP_INLINE_VISIBILITY
132 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
133 _LIBCPP_INLINE_VISIBILITY
134 explicit unique_lock(mutex_type& __m)
135 : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
136 _LIBCPP_INLINE_VISIBILITY
137 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
138 : __m_(_VSTD::addressof(__m)), __owns_(false) {}
139 _LIBCPP_INLINE_VISIBILITY
140 unique_lock(mutex_type& __m, try_to_lock_t)
141 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
142 _LIBCPP_INLINE_VISIBILITY
143 unique_lock(mutex_type& __m, adopt_lock_t)
144 : __m_(_VSTD::addressof(__m)), __owns_(true) {}
145 template <class _Clock, class _Duration>
146 _LIBCPP_INLINE_VISIBILITY
147 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
148 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
149 template <class _Rep, class _Period>
150 _LIBCPP_INLINE_VISIBILITY
151 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
152 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
153 _LIBCPP_INLINE_VISIBILITY
161 unique_lock(unique_lock const&); // = delete;
162 unique_lock& operator=(unique_lock const&); // = delete;
165 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
166 _LIBCPP_INLINE_VISIBILITY
167 unique_lock(unique_lock&& __u) _NOEXCEPT
168 : __m_(__u.__m_), __owns_(__u.__owns_)
169 {__u.__m_ = nullptr; __u.__owns_ = false;}
170 _LIBCPP_INLINE_VISIBILITY
171 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
176 __owns_ = __u.__owns_;
182 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
187 template <class _Rep, class _Period>
188 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
189 template <class _Clock, class _Duration>
190 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
194 _LIBCPP_INLINE_VISIBILITY
195 void swap(unique_lock& __u) _NOEXCEPT
197 _VSTD::swap(__m_, __u.__m_);
198 _VSTD::swap(__owns_, __u.__owns_);
200 _LIBCPP_INLINE_VISIBILITY
201 mutex_type* release() _NOEXCEPT
203 mutex_type* __m = __m_;
209 _LIBCPP_INLINE_VISIBILITY
210 bool owns_lock() const _NOEXCEPT {return __owns_;}
211 _LIBCPP_INLINE_VISIBILITY
213 operator bool () const _NOEXCEPT {return __owns_;}
214 _LIBCPP_INLINE_VISIBILITY
215 mutex_type* mutex() const _NOEXCEPT {return __m_;}
218 template <class _Mutex>
220 unique_lock<_Mutex>::lock()
223 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
225 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
230 template <class _Mutex>
232 unique_lock<_Mutex>::try_lock()
235 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
237 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
238 __owns_ = __m_->try_lock();
242 template <class _Mutex>
243 template <class _Rep, class _Period>
245 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
248 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
250 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
251 __owns_ = __m_->try_lock_for(__d);
255 template <class _Mutex>
256 template <class _Clock, class _Duration>
258 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
261 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
263 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
264 __owns_ = __m_->try_lock_until(__t);
268 template <class _Mutex>
270 unique_lock<_Mutex>::unlock()
273 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
278 template <class _Mutex>
279 inline _LIBCPP_INLINE_VISIBILITY
281 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
284 //enum class cv_status
285 _LIBCPP_DECLARE_STRONG_ENUM(cv_status)
290 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
292 class _LIBCPP_TYPE_VIS condition_variable
294 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
295 __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
297 __libcpp_condvar_t __cv_;
301 _LIBCPP_INLINE_VISIBILITY
302 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
303 constexpr condition_variable() _NOEXCEPT = default;
305 condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;}
307 ~condition_variable();
310 condition_variable(const condition_variable&); // = delete;
311 condition_variable& operator=(const condition_variable&); // = delete;
314 void notify_one() _NOEXCEPT;
315 void notify_all() _NOEXCEPT;
317 void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
318 template <class _Predicate>
319 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
321 template <class _Clock, class _Duration>
323 wait_until(unique_lock<mutex>& __lk,
324 const chrono::time_point<_Clock, _Duration>& __t);
326 template <class _Clock, class _Duration, class _Predicate>
328 wait_until(unique_lock<mutex>& __lk,
329 const chrono::time_point<_Clock, _Duration>& __t,
332 template <class _Rep, class _Period>
334 wait_for(unique_lock<mutex>& __lk,
335 const chrono::duration<_Rep, _Period>& __d);
337 template <class _Rep, class _Period, class _Predicate>
339 _LIBCPP_INLINE_VISIBILITY
340 wait_for(unique_lock<mutex>& __lk,
341 const chrono::duration<_Rep, _Period>& __d,
344 typedef __libcpp_condvar_t* native_handle_type;
345 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
348 void __do_timed_wait(unique_lock<mutex>& __lk,
349 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
351 #endif // !_LIBCPP_HAS_NO_THREADS
353 template <class _To, class _Rep, class _Period>
354 inline _LIBCPP_INLINE_VISIBILITY
357 chrono::__is_duration<_To>::value,
360 __ceil(chrono::duration<_Rep, _Period> __d)
362 using namespace chrono;
363 _To __r = duration_cast<_To>(__d);
369 #ifndef _LIBCPP_HAS_NO_THREADS
370 template <class _Predicate>
372 condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
378 template <class _Clock, class _Duration>
380 condition_variable::wait_until(unique_lock<mutex>& __lk,
381 const chrono::time_point<_Clock, _Duration>& __t)
383 using namespace chrono;
384 wait_for(__lk, __t - _Clock::now());
385 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
388 template <class _Clock, class _Duration, class _Predicate>
390 condition_variable::wait_until(unique_lock<mutex>& __lk,
391 const chrono::time_point<_Clock, _Duration>& __t,
396 if (wait_until(__lk, __t) == cv_status::timeout)
402 template <class _Rep, class _Period>
404 condition_variable::wait_for(unique_lock<mutex>& __lk,
405 const chrono::duration<_Rep, _Period>& __d)
407 using namespace chrono;
408 if (__d <= __d.zero())
409 return cv_status::timeout;
410 typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
411 typedef time_point<system_clock, nanoseconds> __sys_tpi;
412 __sys_tpf _Max = __sys_tpi::max();
413 steady_clock::time_point __c_now = steady_clock::now();
414 system_clock::time_point __s_now = system_clock::now();
415 if (_Max - __d > __s_now)
416 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
418 __do_timed_wait(__lk, __sys_tpi::max());
419 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
423 template <class _Rep, class _Period, class _Predicate>
426 condition_variable::wait_for(unique_lock<mutex>& __lk,
427 const chrono::duration<_Rep, _Period>& __d,
430 return wait_until(__lk, chrono::steady_clock::now() + __d,
431 _VSTD::move(__pred));
434 #endif // !_LIBCPP_HAS_NO_THREADS
436 _LIBCPP_END_NAMESPACE_STD
438 #endif // _LIBCPP___MUTEX_BASE