blob: c78be2472a06756c39da3d76ed4f349f04babd09 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:161// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:014// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:165//
Howard Hinnantb64f8b02010-11-16 22:09:026// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:168//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP___MUTEX_BASE
12#define _LIBCPP___MUTEX_BASE
13
14#include <__config>
15#include <chrono>
16#include <system_error>
Jonathan Roelofs044df632015-08-27 17:47:3417#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantbc8d3f92010-05-11 19:42:1618#include <pthread.h>
Jonathan Roelofs044df632015-08-27 17:47:3419#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1620
Howard Hinnant08e17472011-10-17 20:05:1021#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:1622#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:1023#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1624
25_LIBCPP_BEGIN_NAMESPACE_STD
26
Jonathan Roelofs8d86b2e2014-09-05 19:45:0527#ifndef _LIBCPP_HAS_NO_THREADS
28
Howard Hinnant83eade62013-03-06 23:30:1929class _LIBCPP_TYPE_VIS mutex
Howard Hinnantbc8d3f92010-05-11 19:42:1630{
31 pthread_mutex_t __m_;
32
33public:
Howard Hinnant333f50d2010-09-21 20:16:3734 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant384608e2012-07-07 20:01:5235#ifndef _LIBCPP_HAS_NO_CONSTEXPR
Howard Hinnant5c90cba2012-09-11 16:10:2036 constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
Howard Hinnant384608e2012-07-07 20:01:5237#else
Howard Hinnant499c61f2012-07-21 16:13:0938 mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
Howard Hinnant384608e2012-07-07 20:01:5239#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1640 ~mutex();
41
42private:
43 mutex(const mutex&);// = delete;
44 mutex& operator=(const mutex&);// = delete;
45
46public:
47 void lock();
Howard Hinnant499c61f2012-07-21 16:13:0948 bool try_lock() _NOEXCEPT;
49 void unlock() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:1650
51 typedef pthread_mutex_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:3752 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:1653};
54
Howard Hinnant83eade62013-03-06 23:30:1955struct _LIBCPP_TYPE_VIS defer_lock_t {};
56struct _LIBCPP_TYPE_VIS try_to_lock_t {};
57struct _LIBCPP_TYPE_VIS adopt_lock_t {};
Howard Hinnantbc8d3f92010-05-11 19:42:1658
Howard Hinnant499c61f2012-07-21 16:13:0959#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
Howard Hinnantbc8d3f92010-05-11 19:42:1660
Howard Hinnant499c61f2012-07-21 16:13:0961extern const defer_lock_t defer_lock;
62extern const try_to_lock_t try_to_lock;
63extern const adopt_lock_t adopt_lock;
Howard Hinnantbc8d3f92010-05-11 19:42:1664
Howard Hinnant499c61f2012-07-21 16:13:0965#else
66
67constexpr defer_lock_t defer_lock = defer_lock_t();
68constexpr try_to_lock_t try_to_lock = try_to_lock_t();
69constexpr adopt_lock_t adopt_lock = adopt_lock_t();
70
71#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1672
73template <class _Mutex>
Howard Hinnant0f678bd2013-08-12 18:38:3474class _LIBCPP_TYPE_VIS_ONLY lock_guard
Howard Hinnantbc8d3f92010-05-11 19:42:1675{
76public:
77 typedef _Mutex mutex_type;
78
79private:
80 mutex_type& __m_;
81public:
82
Howard Hinnant333f50d2010-09-21 20:16:3783 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1684 explicit lock_guard(mutex_type& __m)
85 : __m_(__m) {__m_.lock();}
Howard Hinnant333f50d2010-09-21 20:16:3786 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1687 lock_guard(mutex_type& __m, adopt_lock_t)
88 : __m_(__m) {}
Howard Hinnant333f50d2010-09-21 20:16:3789 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1690 ~lock_guard() {__m_.unlock();}
91
92private:
93 lock_guard(lock_guard const&);// = delete;
94 lock_guard& operator=(lock_guard const&);// = delete;
95};
96
97template <class _Mutex>
Howard Hinnant0f678bd2013-08-12 18:38:3498class _LIBCPP_TYPE_VIS_ONLY unique_lock
Howard Hinnantbc8d3f92010-05-11 19:42:1699{
100public:
101 typedef _Mutex mutex_type;
102
103private:
104 mutex_type* __m_;
105 bool __owns_;
106
107public:
Howard Hinnant333f50d2010-09-21 20:16:37108 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09109 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37110 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16111 explicit unique_lock(mutex_type& __m)
112 : __m_(&__m), __owns_(true) {__m_->lock();}
Howard Hinnant333f50d2010-09-21 20:16:37113 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09114 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16115 : __m_(&__m), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37116 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16117 unique_lock(mutex_type& __m, try_to_lock_t)
118 : __m_(&__m), __owns_(__m.try_lock()) {}
Howard Hinnant333f50d2010-09-21 20:16:37119 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16120 unique_lock(mutex_type& __m, adopt_lock_t)
121 : __m_(&__m), __owns_(true) {}
122 template <class _Clock, class _Duration>
Howard Hinnant333f50d2010-09-21 20:16:37123 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16124 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
125 : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
126 template <class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37127 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16128 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
129 : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
Howard Hinnant333f50d2010-09-21 20:16:37130 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16131 ~unique_lock()
132 {
133 if (__owns_)
134 __m_->unlock();
135 }
136
137private:
138 unique_lock(unique_lock const&); // = delete;
139 unique_lock& operator=(unique_lock const&); // = delete;
140
141public:
Howard Hinnant73d21a42010-09-04 23:28:19142#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant333f50d2010-09-21 20:16:37143 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09144 unique_lock(unique_lock&& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16145 : __m_(__u.__m_), __owns_(__u.__owns_)
146 {__u.__m_ = nullptr; __u.__owns_ = false;}
Howard Hinnant333f50d2010-09-21 20:16:37147 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09148 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16149 {
150 if (__owns_)
151 __m_->unlock();
152 __m_ = __u.__m_;
153 __owns_ = __u.__owns_;
154 __u.__m_ = nullptr;
155 __u.__owns_ = false;
156 return *this;
157 }
Howard Hinnantac417fa2010-11-28 19:41:07158
Howard Hinnant73d21a42010-09-04 23:28:19159#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16160
161 void lock();
162 bool try_lock();
163
164 template <class _Rep, class _Period>
165 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
166 template <class _Clock, class _Duration>
167 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
168
169 void unlock();
170
Howard Hinnant333f50d2010-09-21 20:16:37171 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09172 void swap(unique_lock& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16173 {
Howard Hinnant0949eed2011-06-30 21:18:19174 _VSTD::swap(__m_, __u.__m_);
175 _VSTD::swap(__owns_, __u.__owns_);
Howard Hinnantbc8d3f92010-05-11 19:42:16176 }
Howard Hinnant333f50d2010-09-21 20:16:37177 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09178 mutex_type* release() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16179 {
180 mutex_type* __m = __m_;
181 __m_ = nullptr;
182 __owns_ = false;
183 return __m;
184 }
185
Howard Hinnant333f50d2010-09-21 20:16:37186 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09187 bool owns_lock() const _NOEXCEPT {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37188 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant77861882012-02-21 21:46:43189 _LIBCPP_EXPLICIT
Howard Hinnant499c61f2012-07-21 16:13:09190 operator bool () const _NOEXCEPT {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37191 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09192 mutex_type* mutex() const _NOEXCEPT {return __m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16193};
194
195template <class _Mutex>
196void
197unique_lock<_Mutex>::lock()
198{
199 if (__m_ == nullptr)
200 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
201 if (__owns_)
202 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
203 __m_->lock();
204 __owns_ = true;
205}
206
207template <class _Mutex>
208bool
209unique_lock<_Mutex>::try_lock()
210{
211 if (__m_ == nullptr)
212 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
213 if (__owns_)
214 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
215 __owns_ = __m_->try_lock();
216 return __owns_;
217}
218
219template <class _Mutex>
220template <class _Rep, class _Period>
221bool
222unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
223{
224 if (__m_ == nullptr)
225 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
226 if (__owns_)
227 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
228 __owns_ = __m_->try_lock_for(__d);
229 return __owns_;
230}
231
232template <class _Mutex>
233template <class _Clock, class _Duration>
234bool
235unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
236{
237 if (__m_ == nullptr)
238 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
239 if (__owns_)
240 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
241 __owns_ = __m_->try_lock_until(__t);
242 return __owns_;
243}
244
245template <class _Mutex>
246void
247unique_lock<_Mutex>::unlock()
248{
249 if (!__owns_)
250 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
251 __m_->unlock();
252 __owns_ = false;
253}
254
255template <class _Mutex>
Howard Hinnant333f50d2010-09-21 20:16:37256inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16257void
Howard Hinnant499c61f2012-07-21 16:13:09258swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
259 {__x.swap(__y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16260
Marshall Clow239bc422013-12-23 22:14:27261//enum class cv_status
262_LIBCPP_DECLARE_STRONG_ENUM(cv_status)
Howard Hinnantbc8d3f92010-05-11 19:42:16263{
Marshall Clow239bc422013-12-23 22:14:27264 no_timeout,
265 timeout
Howard Hinnantbc8d3f92010-05-11 19:42:16266};
Marshall Clow239bc422013-12-23 22:14:27267_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
Howard Hinnantbc8d3f92010-05-11 19:42:16268
Howard Hinnant83eade62013-03-06 23:30:19269class _LIBCPP_TYPE_VIS condition_variable
Howard Hinnantbc8d3f92010-05-11 19:42:16270{
271 pthread_cond_t __cv_;
272public:
Howard Hinnant333f50d2010-09-21 20:16:37273 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant384608e2012-07-07 20:01:52274#ifndef _LIBCPP_HAS_NO_CONSTEXPR
Howard Hinnant5c90cba2012-09-11 16:10:20275 constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
Howard Hinnant384608e2012-07-07 20:01:52276#else
Howard Hinnantbc8d3f92010-05-11 19:42:16277 condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
Howard Hinnant384608e2012-07-07 20:01:52278#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16279 ~condition_variable();
280
281private:
282 condition_variable(const condition_variable&); // = delete;
283 condition_variable& operator=(const condition_variable&); // = delete;
284
285public:
Howard Hinnantc8f74132012-07-21 16:32:53286 void notify_one() _NOEXCEPT;
287 void notify_all() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16288
Marshall Clowb0767852014-03-26 02:45:04289 void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16290 template <class _Predicate>
291 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
292
Howard Hinnantbc8d3f92010-05-11 19:42:16293 template <class _Clock, class _Duration>
294 cv_status
295 wait_until(unique_lock<mutex>& __lk,
296 const chrono::time_point<_Clock, _Duration>& __t);
297
298 template <class _Clock, class _Duration, class _Predicate>
299 bool
300 wait_until(unique_lock<mutex>& __lk,
301 const chrono::time_point<_Clock, _Duration>& __t,
302 _Predicate __pred);
303
304 template <class _Rep, class _Period>
305 cv_status
306 wait_for(unique_lock<mutex>& __lk,
307 const chrono::duration<_Rep, _Period>& __d);
308
309 template <class _Rep, class _Period, class _Predicate>
310 bool
311 wait_for(unique_lock<mutex>& __lk,
312 const chrono::duration<_Rep, _Period>& __d,
313 _Predicate __pred);
314
315 typedef pthread_cond_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:37316 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16317
318private:
319 void __do_timed_wait(unique_lock<mutex>& __lk,
Marshall Clowb0767852014-03-26 02:45:04320 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16321};
Jonathan Roelofs8d86b2e2014-09-05 19:45:05322#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnantbc8d3f92010-05-11 19:42:16323
324template <class _To, class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37325inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16326typename enable_if
327<
328 chrono::__is_duration<_To>::value,
329 _To
330>::type
331__ceil(chrono::duration<_Rep, _Period> __d)
332{
333 using namespace chrono;
334 _To __r = duration_cast<_To>(__d);
335 if (__r < __d)
336 ++__r;
337 return __r;
338}
339
Jonathan Roelofs8d86b2e2014-09-05 19:45:05340#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantbc8d3f92010-05-11 19:42:16341template <class _Predicate>
342void
343condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
344{
345 while (!__pred())
346 wait(__lk);
347}
348
Howard Hinnantbc8d3f92010-05-11 19:42:16349template <class _Clock, class _Duration>
350cv_status
351condition_variable::wait_until(unique_lock<mutex>& __lk,
352 const chrono::time_point<_Clock, _Duration>& __t)
353{
354 using namespace chrono;
Howard Hinnantcf115d22012-08-30 19:14:33355 wait_for(__lk, __t - _Clock::now());
Howard Hinnantbc8d3f92010-05-11 19:42:16356 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
357}
358
359template <class _Clock, class _Duration, class _Predicate>
360bool
361condition_variable::wait_until(unique_lock<mutex>& __lk,
362 const chrono::time_point<_Clock, _Duration>& __t,
363 _Predicate __pred)
364{
365 while (!__pred())
366 {
367 if (wait_until(__lk, __t) == cv_status::timeout)
368 return __pred();
369 }
370 return true;
371}
372
373template <class _Rep, class _Period>
374cv_status
375condition_variable::wait_for(unique_lock<mutex>& __lk,
376 const chrono::duration<_Rep, _Period>& __d)
377{
378 using namespace chrono;
Howard Hinnantcf115d22012-08-30 19:14:33379 if (__d <= __d.zero())
380 return cv_status::timeout;
381 typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
382 typedef time_point<system_clock, nanoseconds> __sys_tpi;
383 __sys_tpf _Max = __sys_tpi::max();
Howard Hinnantf8f85212010-11-20 19:16:30384 system_clock::time_point __s_now = system_clock::now();
385 steady_clock::time_point __c_now = steady_clock::now();
Howard Hinnantcf115d22012-08-30 19:14:33386 if (_Max - __d > __s_now)
387 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
388 else
389 __do_timed_wait(__lk, __sys_tpi::max());
Howard Hinnantf8f85212010-11-20 19:16:30390 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
391 cv_status::timeout;
Howard Hinnantbc8d3f92010-05-11 19:42:16392}
393
394template <class _Rep, class _Period, class _Predicate>
Howard Hinnant333f50d2010-09-21 20:16:37395inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16396bool
397condition_variable::wait_for(unique_lock<mutex>& __lk,
398 const chrono::duration<_Rep, _Period>& __d,
399 _Predicate __pred)
400{
Howard Hinnantf8f85212010-11-20 19:16:30401 return wait_until(__lk, chrono::steady_clock::now() + __d,
Howard Hinnant0949eed2011-06-30 21:18:19402 _VSTD::move(__pred));
Howard Hinnantbc8d3f92010-05-11 19:42:16403}
404
Jonathan Roelofs8d86b2e2014-09-05 19:45:05405#endif // !_LIBCPP_HAS_NO_THREADS
406
Howard Hinnantbc8d3f92010-05-11 19:42:16407_LIBCPP_END_NAMESPACE_STD
408
409#endif // _LIBCPP___MUTEX_BASE