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>
18 #include <__undef_min_max>
20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21 #pragma GCC system_header
24 _LIBCPP_BEGIN_NAMESPACE_STD
26 #ifndef _LIBCPP_HAS_NO_THREADS
28 #ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
29 # ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
30 # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
32 # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
34 #endif // _LIBCPP_THREAD_SAFETY_ANNOTATION
36 class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
38 #ifndef _LIBCPP_CXX03_LANG
39 __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
41 __libcpp_mutex_t __m_;
45 _LIBCPP_INLINE_VISIBILITY
46 #ifndef _LIBCPP_CXX03_LANG
47 constexpr mutex() _NOEXCEPT = default;
49 mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;}
54 mutex(const mutex&);// = delete;
55 mutex& operator=(const mutex&);// = delete;
58 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());
62 typedef __libcpp_mutex_t* native_handle_type;
63 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
66 struct _LIBCPP_TYPE_VIS defer_lock_t {};
67 struct _LIBCPP_TYPE_VIS try_to_lock_t {};
68 struct _LIBCPP_TYPE_VIS adopt_lock_t {};
70 #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_MUTEX)
72 extern const defer_lock_t defer_lock;
73 extern const try_to_lock_t try_to_lock;
74 extern const adopt_lock_t adopt_lock;
78 constexpr defer_lock_t defer_lock = defer_lock_t();
79 constexpr try_to_lock_t try_to_lock = try_to_lock_t();
80 constexpr adopt_lock_t adopt_lock = adopt_lock_t();
84 template <class _Mutex>
85 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
89 typedef _Mutex mutex_type;
95 _LIBCPP_INLINE_VISIBILITY
96 explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
97 : __m_(__m) {__m_.lock();}
98 _LIBCPP_INLINE_VISIBILITY
99 lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
101 _LIBCPP_INLINE_VISIBILITY
102 ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
105 lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
106 lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
109 template <class _Mutex>
110 class _LIBCPP_TEMPLATE_VIS unique_lock
113 typedef _Mutex mutex_type;
120 _LIBCPP_INLINE_VISIBILITY
121 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
122 _LIBCPP_INLINE_VISIBILITY
123 explicit unique_lock(mutex_type& __m)
124 : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
125 _LIBCPP_INLINE_VISIBILITY
126 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
127 : __m_(_VSTD::addressof(__m)), __owns_(false) {}
128 _LIBCPP_INLINE_VISIBILITY
129 unique_lock(mutex_type& __m, try_to_lock_t)
130 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
131 _LIBCPP_INLINE_VISIBILITY
132 unique_lock(mutex_type& __m, adopt_lock_t)
133 : __m_(_VSTD::addressof(__m)), __owns_(true) {}
134 template <class _Clock, class _Duration>
135 _LIBCPP_INLINE_VISIBILITY
136 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
137 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
138 template <class _Rep, class _Period>
139 _LIBCPP_INLINE_VISIBILITY
140 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
141 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
142 _LIBCPP_INLINE_VISIBILITY
150 unique_lock(unique_lock const&); // = delete;
151 unique_lock& operator=(unique_lock const&); // = delete;
154 #ifndef _LIBCPP_CXX03_LANG
155 _LIBCPP_INLINE_VISIBILITY
156 unique_lock(unique_lock&& __u) _NOEXCEPT
157 : __m_(__u.__m_), __owns_(__u.__owns_)
158 {__u.__m_ = nullptr; __u.__owns_ = false;}
159 _LIBCPP_INLINE_VISIBILITY
160 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
165 __owns_ = __u.__owns_;
171 #endif // _LIBCPP_CXX03_LANG
176 template <class _Rep, class _Period>
177 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
178 template <class _Clock, class _Duration>
179 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
183 _LIBCPP_INLINE_VISIBILITY
184 void swap(unique_lock& __u) _NOEXCEPT
186 _VSTD::swap(__m_, __u.__m_);
187 _VSTD::swap(__owns_, __u.__owns_);
189 _LIBCPP_INLINE_VISIBILITY
190 mutex_type* release() _NOEXCEPT
192 mutex_type* __m = __m_;
198 _LIBCPP_INLINE_VISIBILITY
199 bool owns_lock() const _NOEXCEPT {return __owns_;}
200 _LIBCPP_INLINE_VISIBILITY
202 operator bool () const _NOEXCEPT {return __owns_;}
203 _LIBCPP_INLINE_VISIBILITY
204 mutex_type* mutex() const _NOEXCEPT {return __m_;}
207 template <class _Mutex>
209 unique_lock<_Mutex>::lock()
212 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
214 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
219 template <class _Mutex>
221 unique_lock<_Mutex>::try_lock()
224 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
226 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
227 __owns_ = __m_->try_lock();
231 template <class _Mutex>
232 template <class _Rep, class _Period>
234 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
237 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
239 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
240 __owns_ = __m_->try_lock_for(__d);
244 template <class _Mutex>
245 template <class _Clock, class _Duration>
247 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
250 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
252 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
253 __owns_ = __m_->try_lock_until(__t);
257 template <class _Mutex>
259 unique_lock<_Mutex>::unlock()
262 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
267 template <class _Mutex>
268 inline _LIBCPP_INLINE_VISIBILITY
270 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
273 //enum class cv_status
274 _LIBCPP_DECLARE_STRONG_ENUM(cv_status)
279 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
281 class _LIBCPP_TYPE_VIS condition_variable
283 #ifndef _LIBCPP_CXX03_LANG
284 __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
286 __libcpp_condvar_t __cv_;
290 _LIBCPP_INLINE_VISIBILITY
291 #ifndef _LIBCPP_CXX03_LANG
292 constexpr condition_variable() _NOEXCEPT = default;
294 condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;}
296 ~condition_variable();
299 condition_variable(const condition_variable&); // = delete;
300 condition_variable& operator=(const condition_variable&); // = delete;
303 void notify_one() _NOEXCEPT;
304 void notify_all() _NOEXCEPT;
306 void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
307 template <class _Predicate>
308 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
309 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
311 template <class _Clock, class _Duration>
312 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
314 wait_until(unique_lock<mutex>& __lk,
315 const chrono::time_point<_Clock, _Duration>& __t);
317 template <class _Clock, class _Duration, class _Predicate>
318 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
320 wait_until(unique_lock<mutex>& __lk,
321 const chrono::time_point<_Clock, _Duration>& __t,
324 template <class _Rep, class _Period>
325 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
327 wait_for(unique_lock<mutex>& __lk,
328 const chrono::duration<_Rep, _Period>& __d);
330 template <class _Rep, class _Period, class _Predicate>
332 _LIBCPP_INLINE_VISIBILITY
333 wait_for(unique_lock<mutex>& __lk,
334 const chrono::duration<_Rep, _Period>& __d,
337 typedef __libcpp_condvar_t* native_handle_type;
338 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
341 void __do_timed_wait(unique_lock<mutex>& __lk,
342 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
344 #endif // !_LIBCPP_HAS_NO_THREADS
346 template <class _To, class _Rep, class _Period>
347 inline _LIBCPP_INLINE_VISIBILITY
350 chrono::__is_duration<_To>::value,
353 __ceil(chrono::duration<_Rep, _Period> __d)
355 using namespace chrono;
356 _To __r = duration_cast<_To>(__d);
362 #ifndef _LIBCPP_HAS_NO_THREADS
363 template <class _Predicate>
365 condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
371 template <class _Clock, class _Duration>
373 condition_variable::wait_until(unique_lock<mutex>& __lk,
374 const chrono::time_point<_Clock, _Duration>& __t)
376 using namespace chrono;
377 wait_for(__lk, __t - _Clock::now());
378 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
381 template <class _Clock, class _Duration, class _Predicate>
383 condition_variable::wait_until(unique_lock<mutex>& __lk,
384 const chrono::time_point<_Clock, _Duration>& __t,
389 if (wait_until(__lk, __t) == cv_status::timeout)
395 template <class _Rep, class _Period>
397 condition_variable::wait_for(unique_lock<mutex>& __lk,
398 const chrono::duration<_Rep, _Period>& __d)
400 using namespace chrono;
401 if (__d <= __d.zero())
402 return cv_status::timeout;
403 typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
404 typedef time_point<system_clock, nanoseconds> __sys_tpi;
405 __sys_tpf _Max = __sys_tpi::max();
406 steady_clock::time_point __c_now = steady_clock::now();
407 system_clock::time_point __s_now = system_clock::now();
408 if (_Max - __d > __s_now)
409 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
411 __do_timed_wait(__lk, __sys_tpi::max());
412 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
416 template <class _Rep, class _Period, class _Predicate>
419 condition_variable::wait_for(unique_lock<mutex>& __lk,
420 const chrono::duration<_Rep, _Period>& __d,
423 return wait_until(__lk, chrono::steady_clock::now() + __d,
424 _VSTD::move(__pred));
427 #endif // !_LIBCPP_HAS_NO_THREADS
429 _LIBCPP_END_NAMESPACE_STD
431 #endif // _LIBCPP___MUTEX_BASE