blob: b019b4760d186a6055864202b204e6dbf7f009b0 [file] [log] [blame]
Howard Hinnant3e519522010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnant5b08a8a2010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnant3e519522010-05-11 19:42:16 +00005//
Howard Hinnant412dbeb2010-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 Hinnant3e519522010-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>
Jonathan Roelofs643e0ab2015-08-27 17:47:34 +000017#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant3e519522010-05-11 19:42:16 +000018#include <pthread.h>
Jonathan Roelofs643e0ab2015-08-27 17:47:34 +000019#endif
Howard Hinnant3e519522010-05-11 19:42:16 +000020
Howard Hinnant073458b2011-10-17 20:05:10 +000021#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnant3e519522010-05-11 19:42:16 +000022#pragma GCC system_header
Howard Hinnant073458b2011-10-17 20:05:10 +000023#endif
Howard Hinnant3e519522010-05-11 19:42:16 +000024
25_LIBCPP_BEGIN_NAMESPACE_STD
26
Jonathan Roelofsb3fcc672014-09-05 19:45:05 +000027#ifndef _LIBCPP_HAS_NO_THREADS
28
Howard Hinnant6e412562013-03-06 23:30:19 +000029class _LIBCPP_TYPE_VIS mutex
Howard Hinnant3e519522010-05-11 19:42:16 +000030{
31 pthread_mutex_t __m_;
32
33public:
Howard Hinnantf5ab7032010-09-21 20:16:37 +000034 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbfa79902012-07-07 20:01:52 +000035#ifndef _LIBCPP_HAS_NO_CONSTEXPR
Howard Hinnantab303f72012-09-11 16:10:20 +000036 constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
Howard Hinnantbfa79902012-07-07 20:01:52 +000037#else
Howard Hinnant02e610e2012-07-21 16:13:09 +000038 mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
Howard Hinnantbfa79902012-07-07 20:01:52 +000039#endif
Howard Hinnant3e519522010-05-11 19:42:16 +000040 ~mutex();
41
42private:
43 mutex(const mutex&);// = delete;
44 mutex& operator=(const mutex&);// = delete;
45
46public:
47 void lock();
Howard Hinnant02e610e2012-07-21 16:13:09 +000048 bool try_lock() _NOEXCEPT;
49 void unlock() _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +000050
51 typedef pthread_mutex_t* native_handle_type;
Howard Hinnantf5ab7032010-09-21 20:16:37 +000052 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
Howard Hinnant3e519522010-05-11 19:42:16 +000053};
54
Howard Hinnant6e412562013-03-06 23:30:19 +000055struct _LIBCPP_TYPE_VIS defer_lock_t {};
56struct _LIBCPP_TYPE_VIS try_to_lock_t {};
57struct _LIBCPP_TYPE_VIS adopt_lock_t {};
Howard Hinnant3e519522010-05-11 19:42:16 +000058
Howard Hinnant02e610e2012-07-21 16:13:09 +000059#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
Howard Hinnant3e519522010-05-11 19:42:16 +000060
Howard Hinnant02e610e2012-07-21 16:13:09 +000061extern const defer_lock_t defer_lock;
62extern const try_to_lock_t try_to_lock;
63extern const adopt_lock_t adopt_lock;
Howard Hinnant3e519522010-05-11 19:42:16 +000064
Howard Hinnant02e610e2012-07-21 16:13:09 +000065#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 Hinnant3e519522010-05-11 19:42:16 +000072
73template <class _Mutex>
Howard Hinnantf0544c22013-08-12 18:38:34 +000074class _LIBCPP_TYPE_VIS_ONLY lock_guard
Howard Hinnant3e519522010-05-11 19:42:16 +000075{
76public:
77 typedef _Mutex mutex_type;
78
79private:
80 mutex_type& __m_;
81public:
82
Howard Hinnantf5ab7032010-09-21 20:16:37 +000083 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +000084 explicit lock_guard(mutex_type& __m)
85 : __m_(__m) {__m_.lock();}
Howard Hinnantf5ab7032010-09-21 20:16:37 +000086 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +000087 lock_guard(mutex_type& __m, adopt_lock_t)
88 : __m_(__m) {}
Howard Hinnantf5ab7032010-09-21 20:16:37 +000089 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +000090 ~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 Hinnantf0544c22013-08-12 18:38:34 +000098class _LIBCPP_TYPE_VIS_ONLY unique_lock
Howard Hinnant3e519522010-05-11 19:42:16 +000099{
100public:
101 typedef _Mutex mutex_type;
102
103private:
104 mutex_type* __m_;
105 bool __owns_;
106
107public:
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000108 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant02e610e2012-07-21 16:13:09 +0000109 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000110 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000111 explicit unique_lock(mutex_type& __m)
112 : __m_(&__m), __owns_(true) {__m_->lock();}
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000113 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant02e610e2012-07-21 16:13:09 +0000114 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000115 : __m_(&__m), __owns_(false) {}
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000116 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000117 unique_lock(mutex_type& __m, try_to_lock_t)
118 : __m_(&__m), __owns_(__m.try_lock()) {}
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000119 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000120 unique_lock(mutex_type& __m, adopt_lock_t)
121 : __m_(&__m), __owns_(true) {}
122 template <class _Clock, class _Duration>
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000123 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000124 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 Hinnantf5ab7032010-09-21 20:16:37 +0000127 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000128 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
129 : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000130 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000131 ~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 Hinnant7609c9b2010-09-04 23:28:19 +0000142#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000143 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant02e610e2012-07-21 16:13:09 +0000144 unique_lock(unique_lock&& __u) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000145 : __m_(__u.__m_), __owns_(__u.__owns_)
146 {__u.__m_ = nullptr; __u.__owns_ = false;}
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000147 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant02e610e2012-07-21 16:13:09 +0000148 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000149 {
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 Hinnant6fd5c652010-11-28 19:41:07 +0000158
Howard Hinnant7609c9b2010-09-04 23:28:19 +0000159#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant3e519522010-05-11 19:42:16 +0000160
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 Hinnantf5ab7032010-09-21 20:16:37 +0000171 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant02e610e2012-07-21 16:13:09 +0000172 void swap(unique_lock& __u) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000173 {
Howard Hinnantce48a112011-06-30 21:18:19 +0000174 _VSTD::swap(__m_, __u.__m_);
175 _VSTD::swap(__owns_, __u.__owns_);
Howard Hinnant3e519522010-05-11 19:42:16 +0000176 }
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000177 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant02e610e2012-07-21 16:13:09 +0000178 mutex_type* release() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000179 {
180 mutex_type* __m = __m_;
181 __m_ = nullptr;
182 __owns_ = false;
183 return __m;
184 }
185
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000186 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant02e610e2012-07-21 16:13:09 +0000187 bool owns_lock() const _NOEXCEPT {return __owns_;}
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000188 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantf2f2d8b2012-02-21 21:46:43 +0000189 _LIBCPP_EXPLICIT
Howard Hinnant02e610e2012-07-21 16:13:09 +0000190 operator bool () const _NOEXCEPT {return __owns_;}
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000191 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant02e610e2012-07-21 16:13:09 +0000192 mutex_type* mutex() const _NOEXCEPT {return __m_;}
Howard Hinnant3e519522010-05-11 19:42:16 +0000193};
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 Hinnantf5ab7032010-09-21 20:16:37 +0000256inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000257void
Howard Hinnant02e610e2012-07-21 16:13:09 +0000258swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
259 {__x.swap(__y);}
Howard Hinnant3e519522010-05-11 19:42:16 +0000260
Marshall Clowce81aed42013-12-23 22:14:27 +0000261//enum class cv_status
262_LIBCPP_DECLARE_STRONG_ENUM(cv_status)
Howard Hinnant3e519522010-05-11 19:42:16 +0000263{
Marshall Clowce81aed42013-12-23 22:14:27 +0000264 no_timeout,
265 timeout
Howard Hinnant3e519522010-05-11 19:42:16 +0000266};
Marshall Clowce81aed42013-12-23 22:14:27 +0000267_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
Howard Hinnant3e519522010-05-11 19:42:16 +0000268
Howard Hinnant6e412562013-03-06 23:30:19 +0000269class _LIBCPP_TYPE_VIS condition_variable
Howard Hinnant3e519522010-05-11 19:42:16 +0000270{
271 pthread_cond_t __cv_;
272public:
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000273 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbfa79902012-07-07 20:01:52 +0000274#ifndef _LIBCPP_HAS_NO_CONSTEXPR
Howard Hinnantab303f72012-09-11 16:10:20 +0000275 constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
Howard Hinnantbfa79902012-07-07 20:01:52 +0000276#else
Howard Hinnant3e519522010-05-11 19:42:16 +0000277 condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
Howard Hinnantbfa79902012-07-07 20:01:52 +0000278#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000279 ~condition_variable();
280
281private:
282 condition_variable(const condition_variable&); // = delete;
283 condition_variable& operator=(const condition_variable&); // = delete;
284
285public:
Howard Hinnant45c663d2012-07-21 16:32:53 +0000286 void notify_one() _NOEXCEPT;
287 void notify_all() _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000288
Marshall Clow1641a7c2014-03-26 02:45:04 +0000289 void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000290 template <class _Predicate>
291 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
292
Howard Hinnant3e519522010-05-11 19:42:16 +0000293 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
Evgeniy Stepanov906c8722015-11-07 01:22:13 +0000311 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000312 wait_for(unique_lock<mutex>& __lk,
313 const chrono::duration<_Rep, _Period>& __d,
314 _Predicate __pred);
315
316 typedef pthread_cond_t* native_handle_type;
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000317 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
Howard Hinnant3e519522010-05-11 19:42:16 +0000318
319private:
320 void __do_timed_wait(unique_lock<mutex>& __lk,
Marshall Clow1641a7c2014-03-26 02:45:04 +0000321 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000322};
Jonathan Roelofsb3fcc672014-09-05 19:45:05 +0000323#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant3e519522010-05-11 19:42:16 +0000324
325template <class _To, class _Rep, class _Period>
Howard Hinnantf5ab7032010-09-21 20:16:37 +0000326inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000327typename enable_if
328<
329 chrono::__is_duration<_To>::value,
330 _To
331>::type
332__ceil(chrono::duration<_Rep, _Period> __d)
333{
334 using namespace chrono;
335 _To __r = duration_cast<_To>(__d);
336 if (__r < __d)
337 ++__r;
338 return __r;
339}
340
Jonathan Roelofsb3fcc672014-09-05 19:45:05 +0000341#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant3e519522010-05-11 19:42:16 +0000342template <class _Predicate>
343void
344condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
345{
346 while (!__pred())
347 wait(__lk);
348}
349
Howard Hinnant3e519522010-05-11 19:42:16 +0000350template <class _Clock, class _Duration>
351cv_status
352condition_variable::wait_until(unique_lock<mutex>& __lk,
353 const chrono::time_point<_Clock, _Duration>& __t)
354{
355 using namespace chrono;
Howard Hinnantaad745a2012-08-30 19:14:33 +0000356 wait_for(__lk, __t - _Clock::now());
Howard Hinnant3e519522010-05-11 19:42:16 +0000357 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
358}
359
360template <class _Clock, class _Duration, class _Predicate>
361bool
362condition_variable::wait_until(unique_lock<mutex>& __lk,
363 const chrono::time_point<_Clock, _Duration>& __t,
364 _Predicate __pred)
365{
366 while (!__pred())
367 {
368 if (wait_until(__lk, __t) == cv_status::timeout)
369 return __pred();
370 }
371 return true;
372}
373
374template <class _Rep, class _Period>
375cv_status
376condition_variable::wait_for(unique_lock<mutex>& __lk,
377 const chrono::duration<_Rep, _Period>& __d)
378{
379 using namespace chrono;
Howard Hinnantaad745a2012-08-30 19:14:33 +0000380 if (__d <= __d.zero())
381 return cv_status::timeout;
382 typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
383 typedef time_point<system_clock, nanoseconds> __sys_tpi;
384 __sys_tpf _Max = __sys_tpi::max();
Howard Hinnant3dc64552010-11-20 19:16:30 +0000385 system_clock::time_point __s_now = system_clock::now();
386 steady_clock::time_point __c_now = steady_clock::now();
Howard Hinnantaad745a2012-08-30 19:14:33 +0000387 if (_Max - __d > __s_now)
388 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
389 else
390 __do_timed_wait(__lk, __sys_tpi::max());
Howard Hinnant3dc64552010-11-20 19:16:30 +0000391 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
392 cv_status::timeout;
Howard Hinnant3e519522010-05-11 19:42:16 +0000393}
394
395template <class _Rep, class _Period, class _Predicate>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +0000396inline
Howard Hinnant3e519522010-05-11 19:42:16 +0000397bool
398condition_variable::wait_for(unique_lock<mutex>& __lk,
399 const chrono::duration<_Rep, _Period>& __d,
400 _Predicate __pred)
401{
Howard Hinnant3dc64552010-11-20 19:16:30 +0000402 return wait_until(__lk, chrono::steady_clock::now() + __d,
Howard Hinnantce48a112011-06-30 21:18:19 +0000403 _VSTD::move(__pred));
Howard Hinnant3e519522010-05-11 19:42:16 +0000404}
405
Jonathan Roelofsb3fcc672014-09-05 19:45:05 +0000406#endif // !_LIBCPP_HAS_NO_THREADS
407
Howard Hinnant3e519522010-05-11 19:42:16 +0000408_LIBCPP_END_NAMESPACE_STD
409
410#endif // _LIBCPP___MUTEX_BASE