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>
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #pragma GCC system_header
23 #ifdef _LIBCPP_SHARED_LOCK
26 template <class _Mutex> class shared_lock;
27 template <class _Mutex> class upgrade_lock;
30 #endif // _LIBCPP_SHARED_LOCK
33 _LIBCPP_BEGIN_NAMESPACE_STD
35 class _LIBCPP_TYPE_VIS mutex
40 _LIBCPP_INLINE_VISIBILITY
41 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
42 constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
44 mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
49 mutex(const mutex&);// = delete;
50 mutex& operator=(const mutex&);// = delete;
54 bool try_lock() _NOEXCEPT;
55 void unlock() _NOEXCEPT;
57 typedef pthread_mutex_t* native_handle_type;
58 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
61 struct _LIBCPP_TYPE_VIS defer_lock_t {};
62 struct _LIBCPP_TYPE_VIS try_to_lock_t {};
63 struct _LIBCPP_TYPE_VIS adopt_lock_t {};
65 #if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
67 extern const defer_lock_t defer_lock;
68 extern const try_to_lock_t try_to_lock;
69 extern const adopt_lock_t adopt_lock;
73 constexpr defer_lock_t defer_lock = defer_lock_t();
74 constexpr try_to_lock_t try_to_lock = try_to_lock_t();
75 constexpr adopt_lock_t adopt_lock = adopt_lock_t();
79 template <class _Mutex>
80 class _LIBCPP_TYPE_VIS lock_guard
83 typedef _Mutex mutex_type;
89 _LIBCPP_INLINE_VISIBILITY
90 explicit lock_guard(mutex_type& __m)
91 : __m_(__m) {__m_.lock();}
92 _LIBCPP_INLINE_VISIBILITY
93 lock_guard(mutex_type& __m, adopt_lock_t)
95 _LIBCPP_INLINE_VISIBILITY
96 ~lock_guard() {__m_.unlock();}
99 lock_guard(lock_guard const&);// = delete;
100 lock_guard& operator=(lock_guard const&);// = delete;
103 template <class _Mutex>
104 class _LIBCPP_TYPE_VIS unique_lock
107 typedef _Mutex mutex_type;
114 _LIBCPP_INLINE_VISIBILITY
115 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
116 _LIBCPP_INLINE_VISIBILITY
117 explicit unique_lock(mutex_type& __m)
118 : __m_(&__m), __owns_(true) {__m_->lock();}
119 _LIBCPP_INLINE_VISIBILITY
120 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
121 : __m_(&__m), __owns_(false) {}
122 _LIBCPP_INLINE_VISIBILITY
123 unique_lock(mutex_type& __m, try_to_lock_t)
124 : __m_(&__m), __owns_(__m.try_lock()) {}
125 _LIBCPP_INLINE_VISIBILITY
126 unique_lock(mutex_type& __m, adopt_lock_t)
127 : __m_(&__m), __owns_(true) {}
128 template <class _Clock, class _Duration>
129 _LIBCPP_INLINE_VISIBILITY
130 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
131 : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
132 template <class _Rep, class _Period>
133 _LIBCPP_INLINE_VISIBILITY
134 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
135 : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
136 _LIBCPP_INLINE_VISIBILITY
144 unique_lock(unique_lock const&); // = delete;
145 unique_lock& operator=(unique_lock const&); // = delete;
148 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
149 _LIBCPP_INLINE_VISIBILITY
150 unique_lock(unique_lock&& __u) _NOEXCEPT
151 : __m_(__u.__m_), __owns_(__u.__owns_)
152 {__u.__m_ = nullptr; __u.__owns_ = false;}
153 _LIBCPP_INLINE_VISIBILITY
154 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
159 __owns_ = __u.__owns_;
165 #ifdef _LIBCPP_SHARED_LOCK
167 unique_lock(ting::shared_lock<mutex_type>&&, try_to_lock_t);
168 template <class _Clock, class _Duration>
169 unique_lock(ting::shared_lock<mutex_type>&&,
170 const chrono::time_point<_Clock, _Duration>&);
171 template <class _Rep, class _Period>
172 unique_lock(ting::shared_lock<mutex_type>&&,
173 const chrono::duration<_Rep, _Period>&);
175 explicit unique_lock(ting::upgrade_lock<mutex_type>&&);
176 unique_lock(ting::upgrade_lock<mutex_type>&&, try_to_lock_t);
177 template <class _Clock, class _Duration>
178 unique_lock(ting::upgrade_lock<mutex_type>&&,
179 const chrono::time_point<_Clock, _Duration>&);
180 template <class _Rep, class _Period>
181 unique_lock(ting::upgrade_lock<mutex_type>&&,
182 const chrono::duration<_Rep, _Period>&);
184 #endif // _LIBCPP_SHARED_LOCK
186 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
191 template <class _Rep, class _Period>
192 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
193 template <class _Clock, class _Duration>
194 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
198 _LIBCPP_INLINE_VISIBILITY
199 void swap(unique_lock& __u) _NOEXCEPT
201 _VSTD::swap(__m_, __u.__m_);
202 _VSTD::swap(__owns_, __u.__owns_);
204 _LIBCPP_INLINE_VISIBILITY
205 mutex_type* release() _NOEXCEPT
207 mutex_type* __m = __m_;
213 _LIBCPP_INLINE_VISIBILITY
214 bool owns_lock() const _NOEXCEPT {return __owns_;}
215 _LIBCPP_INLINE_VISIBILITY
217 operator bool () const _NOEXCEPT {return __owns_;}
218 _LIBCPP_INLINE_VISIBILITY
219 mutex_type* mutex() const _NOEXCEPT {return __m_;}
222 template <class _Mutex>
224 unique_lock<_Mutex>::lock()
227 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
229 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
234 template <class _Mutex>
236 unique_lock<_Mutex>::try_lock()
239 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
241 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
242 __owns_ = __m_->try_lock();
246 template <class _Mutex>
247 template <class _Rep, class _Period>
249 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
252 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
254 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
255 __owns_ = __m_->try_lock_for(__d);
259 template <class _Mutex>
260 template <class _Clock, class _Duration>
262 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
265 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
267 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
268 __owns_ = __m_->try_lock_until(__t);
272 template <class _Mutex>
274 unique_lock<_Mutex>::unlock()
277 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
282 template <class _Mutex>
283 inline _LIBCPP_INLINE_VISIBILITY
285 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
288 struct _LIBCPP_TYPE_VIS cv_status
297 _LIBCPP_INLINE_VISIBILITY cv_status(__lx __v) : __v_(__v) {}
298 _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;}
302 class _LIBCPP_TYPE_VIS condition_variable
304 pthread_cond_t __cv_;
306 _LIBCPP_INLINE_VISIBILITY
307 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
308 constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
310 condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
312 ~condition_variable();
315 condition_variable(const condition_variable&); // = delete;
316 condition_variable& operator=(const condition_variable&); // = delete;
319 void notify_one() _NOEXCEPT;
320 void notify_all() _NOEXCEPT;
322 void wait(unique_lock<mutex>& __lk);
323 template <class _Predicate>
324 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
326 template <class _Clock, class _Duration>
328 wait_until(unique_lock<mutex>& __lk,
329 const chrono::time_point<_Clock, _Duration>& __t);
331 template <class _Clock, class _Duration, class _Predicate>
333 wait_until(unique_lock<mutex>& __lk,
334 const chrono::time_point<_Clock, _Duration>& __t,
337 template <class _Rep, class _Period>
339 wait_for(unique_lock<mutex>& __lk,
340 const chrono::duration<_Rep, _Period>& __d);
342 template <class _Rep, class _Period, class _Predicate>
344 wait_for(unique_lock<mutex>& __lk,
345 const chrono::duration<_Rep, _Period>& __d,
348 typedef pthread_cond_t* native_handle_type;
349 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
352 void __do_timed_wait(unique_lock<mutex>& __lk,
353 chrono::time_point<chrono::system_clock, chrono::nanoseconds>);
356 template <class _To, class _Rep, class _Period>
357 inline _LIBCPP_INLINE_VISIBILITY
360 chrono::__is_duration<_To>::value,
363 __ceil(chrono::duration<_Rep, _Period> __d)
365 using namespace chrono;
366 _To __r = duration_cast<_To>(__d);
372 template <class _Predicate>
374 condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
380 template <class _Clock, class _Duration>
382 condition_variable::wait_until(unique_lock<mutex>& __lk,
383 const chrono::time_point<_Clock, _Duration>& __t)
385 using namespace chrono;
386 wait_for(__lk, __t - _Clock::now());
387 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
390 template <class _Clock, class _Duration, class _Predicate>
392 condition_variable::wait_until(unique_lock<mutex>& __lk,
393 const chrono::time_point<_Clock, _Duration>& __t,
398 if (wait_until(__lk, __t) == cv_status::timeout)
404 template <class _Rep, class _Period>
406 condition_variable::wait_for(unique_lock<mutex>& __lk,
407 const chrono::duration<_Rep, _Period>& __d)
409 using namespace chrono;
410 if (__d <= __d.zero())
411 return cv_status::timeout;
412 typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
413 typedef time_point<system_clock, nanoseconds> __sys_tpi;
414 __sys_tpf _Max = __sys_tpi::max();
415 system_clock::time_point __s_now = system_clock::now();
416 steady_clock::time_point __c_now = steady_clock::now();
417 if (_Max - __d > __s_now)
418 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
420 __do_timed_wait(__lk, __sys_tpi::max());
421 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
425 template <class _Rep, class _Period, class _Predicate>
426 inline _LIBCPP_INLINE_VISIBILITY
428 condition_variable::wait_for(unique_lock<mutex>& __lk,
429 const chrono::duration<_Rep, _Period>& __d,
432 return wait_until(__lk, chrono::steady_clock::now() + __d,
433 _VSTD::move(__pred));
436 _LIBCPP_END_NAMESPACE_STD
438 #endif // _LIBCPP___MUTEX_BASE