blob: 293feada648243e5f3860c6cb1227352385ddd3b [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// 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:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP___MUTEX_BASE
12#define _LIBCPP___MUTEX_BASE
13
14#include <__config>
15#include <chrono>
16#include <system_error>
17#include <pthread.h>
18
Howard Hinnant08e17472011-10-17 20:05:10 +000019#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000020#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +000021#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000022
23_LIBCPP_BEGIN_NAMESPACE_STD
24
Howard Hinnant83eade62013-03-06 23:30:19 +000025class _LIBCPP_TYPE_VIS mutex
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000026{
27 pthread_mutex_t __m_;
28
29public:
Howard Hinnant333f50d2010-09-21 20:16:37 +000030 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant384608e2012-07-07 20:01:52 +000031#ifndef _LIBCPP_HAS_NO_CONSTEXPR
Howard Hinnant5c90cba2012-09-11 16:10:20 +000032 constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
Howard Hinnant384608e2012-07-07 20:01:52 +000033#else
Howard Hinnant499c61f2012-07-21 16:13:09 +000034 mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
Howard Hinnant384608e2012-07-07 20:01:52 +000035#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036 ~mutex();
37
38private:
39 mutex(const mutex&);// = delete;
40 mutex& operator=(const mutex&);// = delete;
41
42public:
43 void lock();
Howard Hinnant499c61f2012-07-21 16:13:09 +000044 bool try_lock() _NOEXCEPT;
45 void unlock() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000046
47 typedef pthread_mutex_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:37 +000048 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049};
50
Howard Hinnant83eade62013-03-06 23:30:19 +000051struct _LIBCPP_TYPE_VIS defer_lock_t {};
52struct _LIBCPP_TYPE_VIS try_to_lock_t {};
53struct _LIBCPP_TYPE_VIS adopt_lock_t {};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000054
Howard Hinnant499c61f2012-07-21 16:13:09 +000055#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000056
Howard Hinnant499c61f2012-07-21 16:13:09 +000057extern const defer_lock_t defer_lock;
58extern const try_to_lock_t try_to_lock;
59extern const adopt_lock_t adopt_lock;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000060
Howard Hinnant499c61f2012-07-21 16:13:09 +000061#else
62
63constexpr defer_lock_t defer_lock = defer_lock_t();
64constexpr try_to_lock_t try_to_lock = try_to_lock_t();
65constexpr adopt_lock_t adopt_lock = adopt_lock_t();
66
67#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000068
69template <class _Mutex>
Howard Hinnant0f678bd2013-08-12 18:38:34 +000070class _LIBCPP_TYPE_VIS_ONLY lock_guard
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000071{
72public:
73 typedef _Mutex mutex_type;
74
75private:
76 mutex_type& __m_;
77public:
78
Howard Hinnant333f50d2010-09-21 20:16:37 +000079 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000080 explicit lock_guard(mutex_type& __m)
81 : __m_(__m) {__m_.lock();}
Howard Hinnant333f50d2010-09-21 20:16:37 +000082 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000083 lock_guard(mutex_type& __m, adopt_lock_t)
84 : __m_(__m) {}
Howard Hinnant333f50d2010-09-21 20:16:37 +000085 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000086 ~lock_guard() {__m_.unlock();}
87
88private:
89 lock_guard(lock_guard const&);// = delete;
90 lock_guard& operator=(lock_guard const&);// = delete;
91};
92
93template <class _Mutex>
Howard Hinnant0f678bd2013-08-12 18:38:34 +000094class _LIBCPP_TYPE_VIS_ONLY unique_lock
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000095{
96public:
97 typedef _Mutex mutex_type;
98
99private:
100 mutex_type* __m_;
101 bool __owns_;
102
103public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000104 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000105 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000106 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000107 explicit unique_lock(mutex_type& __m)
108 : __m_(&__m), __owns_(true) {__m_->lock();}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000109 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000110 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000111 : __m_(&__m), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000112 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000113 unique_lock(mutex_type& __m, try_to_lock_t)
114 : __m_(&__m), __owns_(__m.try_lock()) {}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000115 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116 unique_lock(mutex_type& __m, adopt_lock_t)
117 : __m_(&__m), __owns_(true) {}
118 template <class _Clock, class _Duration>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000119 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
121 : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
122 template <class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000123 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000124 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
125 : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000126 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000127 ~unique_lock()
128 {
129 if (__owns_)
130 __m_->unlock();
131 }
132
133private:
134 unique_lock(unique_lock const&); // = delete;
135 unique_lock& operator=(unique_lock const&); // = delete;
136
137public:
Howard Hinnant73d21a42010-09-04 23:28:19 +0000138#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant333f50d2010-09-21 20:16:37 +0000139 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000140 unique_lock(unique_lock&& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000141 : __m_(__u.__m_), __owns_(__u.__owns_)
142 {__u.__m_ = nullptr; __u.__owns_ = false;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000143 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000144 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000145 {
146 if (__owns_)
147 __m_->unlock();
148 __m_ = __u.__m_;
149 __owns_ = __u.__owns_;
150 __u.__m_ = nullptr;
151 __u.__owns_ = false;
152 return *this;
153 }
Howard Hinnantac417fa2010-11-28 19:41:07 +0000154
Howard Hinnant73d21a42010-09-04 23:28:19 +0000155#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000156
157 void lock();
158 bool try_lock();
159
160 template <class _Rep, class _Period>
161 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
162 template <class _Clock, class _Duration>
163 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
164
165 void unlock();
166
Howard Hinnant333f50d2010-09-21 20:16:37 +0000167 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000168 void swap(unique_lock& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000169 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000170 _VSTD::swap(__m_, __u.__m_);
171 _VSTD::swap(__owns_, __u.__owns_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000172 }
Howard Hinnant333f50d2010-09-21 20:16:37 +0000173 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000174 mutex_type* release() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000175 {
176 mutex_type* __m = __m_;
177 __m_ = nullptr;
178 __owns_ = false;
179 return __m;
180 }
181
Howard Hinnant333f50d2010-09-21 20:16:37 +0000182 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000183 bool owns_lock() const _NOEXCEPT {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000184 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant77861882012-02-21 21:46:43 +0000185 _LIBCPP_EXPLICIT
Howard Hinnant499c61f2012-07-21 16:13:09 +0000186 operator bool () const _NOEXCEPT {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37 +0000187 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09 +0000188 mutex_type* mutex() const _NOEXCEPT {return __m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000189};
190
191template <class _Mutex>
192void
193unique_lock<_Mutex>::lock()
194{
195 if (__m_ == nullptr)
196 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
197 if (__owns_)
198 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
199 __m_->lock();
200 __owns_ = true;
201}
202
203template <class _Mutex>
204bool
205unique_lock<_Mutex>::try_lock()
206{
207 if (__m_ == nullptr)
208 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
209 if (__owns_)
210 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
211 __owns_ = __m_->try_lock();
212 return __owns_;
213}
214
215template <class _Mutex>
216template <class _Rep, class _Period>
217bool
218unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
219{
220 if (__m_ == nullptr)
221 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
222 if (__owns_)
223 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
224 __owns_ = __m_->try_lock_for(__d);
225 return __owns_;
226}
227
228template <class _Mutex>
229template <class _Clock, class _Duration>
230bool
231unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
232{
233 if (__m_ == nullptr)
234 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
235 if (__owns_)
236 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
237 __owns_ = __m_->try_lock_until(__t);
238 return __owns_;
239}
240
241template <class _Mutex>
242void
243unique_lock<_Mutex>::unlock()
244{
245 if (!__owns_)
246 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
247 __m_->unlock();
248 __owns_ = false;
249}
250
251template <class _Mutex>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000252inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000253void
Howard Hinnant499c61f2012-07-21 16:13:09 +0000254swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
255 {__x.swap(__y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000256
Marshall Clow239bc422013-12-23 22:14:27 +0000257//enum class cv_status
258_LIBCPP_DECLARE_STRONG_ENUM(cv_status)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000259{
Marshall Clow239bc422013-12-23 22:14:27 +0000260 no_timeout,
261 timeout
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000262};
Marshall Clow239bc422013-12-23 22:14:27 +0000263_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264
Howard Hinnant83eade62013-03-06 23:30:19 +0000265class _LIBCPP_TYPE_VIS condition_variable
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000266{
267 pthread_cond_t __cv_;
268public:
Howard Hinnant333f50d2010-09-21 20:16:37 +0000269 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant384608e2012-07-07 20:01:52 +0000270#ifndef _LIBCPP_HAS_NO_CONSTEXPR
Howard Hinnant5c90cba2012-09-11 16:10:20 +0000271 constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
Howard Hinnant384608e2012-07-07 20:01:52 +0000272#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000273 condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
Howard Hinnant384608e2012-07-07 20:01:52 +0000274#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000275 ~condition_variable();
276
277private:
278 condition_variable(const condition_variable&); // = delete;
279 condition_variable& operator=(const condition_variable&); // = delete;
280
281public:
Howard Hinnantc8f74132012-07-21 16:32:53 +0000282 void notify_one() _NOEXCEPT;
283 void notify_all() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000284
Marshall Clowb0767852014-03-26 02:45:04 +0000285 void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000286 template <class _Predicate>
287 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
288
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000289 template <class _Clock, class _Duration>
290 cv_status
291 wait_until(unique_lock<mutex>& __lk,
292 const chrono::time_point<_Clock, _Duration>& __t);
293
294 template <class _Clock, class _Duration, class _Predicate>
295 bool
296 wait_until(unique_lock<mutex>& __lk,
297 const chrono::time_point<_Clock, _Duration>& __t,
298 _Predicate __pred);
299
300 template <class _Rep, class _Period>
301 cv_status
302 wait_for(unique_lock<mutex>& __lk,
303 const chrono::duration<_Rep, _Period>& __d);
304
305 template <class _Rep, class _Period, class _Predicate>
306 bool
307 wait_for(unique_lock<mutex>& __lk,
308 const chrono::duration<_Rep, _Period>& __d,
309 _Predicate __pred);
310
311 typedef pthread_cond_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:37 +0000312 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000313
314private:
315 void __do_timed_wait(unique_lock<mutex>& __lk,
Marshall Clowb0767852014-03-26 02:45:04 +0000316 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000317};
318
319template <class _To, class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000320inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000321typename enable_if
322<
323 chrono::__is_duration<_To>::value,
324 _To
325>::type
326__ceil(chrono::duration<_Rep, _Period> __d)
327{
328 using namespace chrono;
329 _To __r = duration_cast<_To>(__d);
330 if (__r < __d)
331 ++__r;
332 return __r;
333}
334
335template <class _Predicate>
336void
337condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
338{
339 while (!__pred())
340 wait(__lk);
341}
342
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000343template <class _Clock, class _Duration>
344cv_status
345condition_variable::wait_until(unique_lock<mutex>& __lk,
346 const chrono::time_point<_Clock, _Duration>& __t)
347{
348 using namespace chrono;
Howard Hinnantcf115d22012-08-30 19:14:33 +0000349 wait_for(__lk, __t - _Clock::now());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000350 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
351}
352
353template <class _Clock, class _Duration, class _Predicate>
354bool
355condition_variable::wait_until(unique_lock<mutex>& __lk,
356 const chrono::time_point<_Clock, _Duration>& __t,
357 _Predicate __pred)
358{
359 while (!__pred())
360 {
361 if (wait_until(__lk, __t) == cv_status::timeout)
362 return __pred();
363 }
364 return true;
365}
366
367template <class _Rep, class _Period>
368cv_status
369condition_variable::wait_for(unique_lock<mutex>& __lk,
370 const chrono::duration<_Rep, _Period>& __d)
371{
372 using namespace chrono;
Howard Hinnantcf115d22012-08-30 19:14:33 +0000373 if (__d <= __d.zero())
374 return cv_status::timeout;
375 typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
376 typedef time_point<system_clock, nanoseconds> __sys_tpi;
377 __sys_tpf _Max = __sys_tpi::max();
Howard Hinnantf8f85212010-11-20 19:16:30 +0000378 system_clock::time_point __s_now = system_clock::now();
379 steady_clock::time_point __c_now = steady_clock::now();
Howard Hinnantcf115d22012-08-30 19:14:33 +0000380 if (_Max - __d > __s_now)
381 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
382 else
383 __do_timed_wait(__lk, __sys_tpi::max());
Howard Hinnantf8f85212010-11-20 19:16:30 +0000384 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
385 cv_status::timeout;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000386}
387
388template <class _Rep, class _Period, class _Predicate>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000389inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000390bool
391condition_variable::wait_for(unique_lock<mutex>& __lk,
392 const chrono::duration<_Rep, _Period>& __d,
393 _Predicate __pred)
394{
Howard Hinnantf8f85212010-11-20 19:16:30 +0000395 return wait_until(__lk, chrono::steady_clock::now() + __d,
Howard Hinnant0949eed2011-06-30 21:18:19 +0000396 _VSTD::move(__pred));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000397}
398
399_LIBCPP_END_NAMESPACE_STD
400
401#endif // _LIBCPP___MUTEX_BASE