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>
20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21 #pragma GCC system_header
25 #include <__undef_macros>
28 _LIBCPP_BEGIN_NAMESPACE_STD
30 #ifndef _LIBCPP_HAS_NO_THREADS
32 #ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
33 # ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
34 # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
36 # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
38 #endif // _LIBCPP_THREAD_SAFETY_ANNOTATION
40 class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
42 #ifndef _LIBCPP_CXX03_LANG
43 __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
45 __libcpp_mutex_t __m_;
49 _LIBCPP_INLINE_VISIBILITY
50 #ifndef _LIBCPP_CXX03_LANG
51 constexpr mutex() = default;
53 mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;}
58 mutex(const mutex&);// = delete;
59 mutex& operator=(const mutex&);// = delete;
62 void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
63 bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
64 void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
66 typedef __libcpp_mutex_t* native_handle_type;
67 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
70 static_assert(is_nothrow_default_constructible<mutex>::value,
71 "the default constructor for std::mutex must be nothrow");
73 struct _LIBCPP_TYPE_VIS defer_lock_t {};
74 struct _LIBCPP_TYPE_VIS try_to_lock_t {};
75 struct _LIBCPP_TYPE_VIS adopt_lock_t {};
77 #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
79 extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock;
80 extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
81 extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock;
85 /* _LIBCPP_INLINE_VAR */ constexpr defer_lock_t defer_lock = defer_lock_t();
86 /* _LIBCPP_INLINE_VAR */ constexpr try_to_lock_t try_to_lock = try_to_lock_t();
87 /* _LIBCPP_INLINE_VAR */ constexpr adopt_lock_t adopt_lock = adopt_lock_t();
91 template <class _Mutex>
92 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
96 typedef _Mutex mutex_type;
102 _LIBCPP_INLINE_VISIBILITY
103 explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
104 : __m_(__m) {__m_.lock();}
105 _LIBCPP_INLINE_VISIBILITY
106 lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
108 _LIBCPP_INLINE_VISIBILITY
109 ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
112 lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
113 lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
116 template <class _Mutex>
117 class _LIBCPP_TEMPLATE_VIS unique_lock
120 typedef _Mutex mutex_type;
127 _LIBCPP_INLINE_VISIBILITY
128 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
129 _LIBCPP_INLINE_VISIBILITY
130 explicit unique_lock(mutex_type& __m)
131 : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
132 _LIBCPP_INLINE_VISIBILITY
133 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
134 : __m_(_VSTD::addressof(__m)), __owns_(false) {}
135 _LIBCPP_INLINE_VISIBILITY
136 unique_lock(mutex_type& __m, try_to_lock_t)
137 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
138 _LIBCPP_INLINE_VISIBILITY
139 unique_lock(mutex_type& __m, adopt_lock_t)
140 : __m_(_VSTD::addressof(__m)), __owns_(true) {}
141 template <class _Clock, class _Duration>
142 _LIBCPP_INLINE_VISIBILITY
143 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
144 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
145 template <class _Rep, class _Period>
146 _LIBCPP_INLINE_VISIBILITY
147 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
148 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
149 _LIBCPP_INLINE_VISIBILITY
157 unique_lock(unique_lock const&); // = delete;
158 unique_lock& operator=(unique_lock const&); // = delete;
161 #ifndef _LIBCPP_CXX03_LANG
162 _LIBCPP_INLINE_VISIBILITY
163 unique_lock(unique_lock&& __u) _NOEXCEPT
164 : __m_(__u.__m_), __owns_(__u.__owns_)
165 {__u.__m_ = nullptr; __u.__owns_ = false;}
166 _LIBCPP_INLINE_VISIBILITY
167 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
172 __owns_ = __u.__owns_;
178 #endif // _LIBCPP_CXX03_LANG
183 template <class _Rep, class _Period>
184 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
185 template <class _Clock, class _Duration>
186 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
190 _LIBCPP_INLINE_VISIBILITY
191 void swap(unique_lock& __u) _NOEXCEPT
193 _VSTD::swap(__m_, __u.__m_);
194 _VSTD::swap(__owns_, __u.__owns_);
196 _LIBCPP_INLINE_VISIBILITY
197 mutex_type* release() _NOEXCEPT
199 mutex_type* __m = __m_;
205 _LIBCPP_INLINE_VISIBILITY
206 bool owns_lock() const _NOEXCEPT {return __owns_;}
207 _LIBCPP_INLINE_VISIBILITY
209 operator bool () const _NOEXCEPT {return __owns_;}
210 _LIBCPP_INLINE_VISIBILITY
211 mutex_type* mutex() const _NOEXCEPT {return __m_;}
214 template <class _Mutex>
216 unique_lock<_Mutex>::lock()
219 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
221 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
226 template <class _Mutex>
228 unique_lock<_Mutex>::try_lock()
231 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
233 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
234 __owns_ = __m_->try_lock();
238 template <class _Mutex>
239 template <class _Rep, class _Period>
241 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
244 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
246 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
247 __owns_ = __m_->try_lock_for(__d);
251 template <class _Mutex>
252 template <class _Clock, class _Duration>
254 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
257 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
259 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
260 __owns_ = __m_->try_lock_until(__t);
264 template <class _Mutex>
266 unique_lock<_Mutex>::unlock()
269 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
274 template <class _Mutex>
275 inline _LIBCPP_INLINE_VISIBILITY
277 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
280 //enum class cv_status
281 _LIBCPP_DECLARE_STRONG_ENUM(cv_status)
286 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
288 class _LIBCPP_TYPE_VIS condition_variable
290 #ifndef _LIBCPP_CXX03_LANG
291 __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
293 __libcpp_condvar_t __cv_;
297 _LIBCPP_INLINE_VISIBILITY
298 #ifndef _LIBCPP_CXX03_LANG
299 constexpr condition_variable() _NOEXCEPT = default;
301 condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;}
303 ~condition_variable();
306 condition_variable(const condition_variable&); // = delete;
307 condition_variable& operator=(const condition_variable&); // = delete;
310 void notify_one() _NOEXCEPT;
311 void notify_all() _NOEXCEPT;
313 void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
314 template <class _Predicate>
315 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
316 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
318 template <class _Clock, class _Duration>
319 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
321 wait_until(unique_lock<mutex>& __lk,
322 const chrono::time_point<_Clock, _Duration>& __t);
324 template <class _Clock, class _Duration, class _Predicate>
325 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
327 wait_until(unique_lock<mutex>& __lk,
328 const chrono::time_point<_Clock, _Duration>& __t,
331 template <class _Rep, class _Period>
332 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
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
440 #endif // _LIBCPP___MUTEX_BASE