blob: d5ece7c1454c8c7533c075e03339c87d28d09da5 [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>
17#include <pthread.h>
18
Howard Hinnant08e17472011-10-17 20:05:1019#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:1620#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:1021#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1622
23_LIBCPP_BEGIN_NAMESPACE_STD
24
Jonathan Roelofs8d86b2e2014-09-05 19:45:0525#ifndef _LIBCPP_HAS_NO_THREADS
26
Howard Hinnant83eade62013-03-06 23:30:1927class _LIBCPP_TYPE_VIS mutex
Howard Hinnantbc8d3f92010-05-11 19:42:1628{
29 pthread_mutex_t __m_;
30
31public:
Howard Hinnant333f50d2010-09-21 20:16:3732 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant384608e2012-07-07 20:01:5233#ifndef _LIBCPP_HAS_NO_CONSTEXPR
Howard Hinnant5c90cba2012-09-11 16:10:2034 constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
Howard Hinnant384608e2012-07-07 20:01:5235#else
Howard Hinnant499c61f2012-07-21 16:13:0936 mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
Howard Hinnant384608e2012-07-07 20:01:5237#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1638 ~mutex();
39
40private:
41 mutex(const mutex&);// = delete;
42 mutex& operator=(const mutex&);// = delete;
43
44public:
45 void lock();
Howard Hinnant499c61f2012-07-21 16:13:0946 bool try_lock() _NOEXCEPT;
47 void unlock() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:1648
49 typedef pthread_mutex_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:3750 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:1651};
52
Howard Hinnant83eade62013-03-06 23:30:1953struct _LIBCPP_TYPE_VIS defer_lock_t {};
54struct _LIBCPP_TYPE_VIS try_to_lock_t {};
55struct _LIBCPP_TYPE_VIS adopt_lock_t {};
Howard Hinnantbc8d3f92010-05-11 19:42:1656
Howard Hinnant499c61f2012-07-21 16:13:0957#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
Howard Hinnantbc8d3f92010-05-11 19:42:1658
Howard Hinnant499c61f2012-07-21 16:13:0959extern const defer_lock_t defer_lock;
60extern const try_to_lock_t try_to_lock;
61extern const adopt_lock_t adopt_lock;
Howard Hinnantbc8d3f92010-05-11 19:42:1662
Howard Hinnant499c61f2012-07-21 16:13:0963#else
64
65constexpr defer_lock_t defer_lock = defer_lock_t();
66constexpr try_to_lock_t try_to_lock = try_to_lock_t();
67constexpr adopt_lock_t adopt_lock = adopt_lock_t();
68
69#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1670
71template <class _Mutex>
Howard Hinnant0f678bd2013-08-12 18:38:3472class _LIBCPP_TYPE_VIS_ONLY lock_guard
Howard Hinnantbc8d3f92010-05-11 19:42:1673{
74public:
75 typedef _Mutex mutex_type;
76
77private:
78 mutex_type& __m_;
79public:
80
Howard Hinnant333f50d2010-09-21 20:16:3781 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1682 explicit lock_guard(mutex_type& __m)
83 : __m_(__m) {__m_.lock();}
Howard Hinnant333f50d2010-09-21 20:16:3784 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1685 lock_guard(mutex_type& __m, adopt_lock_t)
86 : __m_(__m) {}
Howard Hinnant333f50d2010-09-21 20:16:3787 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1688 ~lock_guard() {__m_.unlock();}
89
90private:
91 lock_guard(lock_guard const&);// = delete;
92 lock_guard& operator=(lock_guard const&);// = delete;
93};
94
95template <class _Mutex>
Howard Hinnant0f678bd2013-08-12 18:38:3496class _LIBCPP_TYPE_VIS_ONLY unique_lock
Howard Hinnantbc8d3f92010-05-11 19:42:1697{
98public:
99 typedef _Mutex mutex_type;
100
101private:
102 mutex_type* __m_;
103 bool __owns_;
104
105public:
Howard Hinnant333f50d2010-09-21 20:16:37106 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09107 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37108 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16109 explicit unique_lock(mutex_type& __m)
110 : __m_(&__m), __owns_(true) {__m_->lock();}
Howard Hinnant333f50d2010-09-21 20:16:37111 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09112 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16113 : __m_(&__m), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37114 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16115 unique_lock(mutex_type& __m, try_to_lock_t)
116 : __m_(&__m), __owns_(__m.try_lock()) {}
Howard Hinnant333f50d2010-09-21 20:16:37117 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16118 unique_lock(mutex_type& __m, adopt_lock_t)
119 : __m_(&__m), __owns_(true) {}
120 template <class _Clock, class _Duration>
Howard Hinnant333f50d2010-09-21 20:16:37121 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16122 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
123 : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
124 template <class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37125 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16126 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
127 : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
Howard Hinnant333f50d2010-09-21 20:16:37128 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16129 ~unique_lock()
130 {
131 if (__owns_)
132 __m_->unlock();
133 }
134
135private:
136 unique_lock(unique_lock const&); // = delete;
137 unique_lock& operator=(unique_lock const&); // = delete;
138
139public:
Howard Hinnant73d21a42010-09-04 23:28:19140#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant333f50d2010-09-21 20:16:37141 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09142 unique_lock(unique_lock&& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16143 : __m_(__u.__m_), __owns_(__u.__owns_)
144 {__u.__m_ = nullptr; __u.__owns_ = false;}
Howard Hinnant333f50d2010-09-21 20:16:37145 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09146 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16147 {
148 if (__owns_)
149 __m_->unlock();
150 __m_ = __u.__m_;
151 __owns_ = __u.__owns_;
152 __u.__m_ = nullptr;
153 __u.__owns_ = false;
154 return *this;
155 }
Howard Hinnantac417fa2010-11-28 19:41:07156
Howard Hinnant73d21a42010-09-04 23:28:19157#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16158
159 void lock();
160 bool try_lock();
161
162 template <class _Rep, class _Period>
163 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
164 template <class _Clock, class _Duration>
165 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
166
167 void unlock();
168
Howard Hinnant333f50d2010-09-21 20:16:37169 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09170 void swap(unique_lock& __u) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16171 {
Howard Hinnant0949eed2011-06-30 21:18:19172 _VSTD::swap(__m_, __u.__m_);
173 _VSTD::swap(__owns_, __u.__owns_);
Howard Hinnantbc8d3f92010-05-11 19:42:16174 }
Howard Hinnant333f50d2010-09-21 20:16:37175 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09176 mutex_type* release() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16177 {
178 mutex_type* __m = __m_;
179 __m_ = nullptr;
180 __owns_ = false;
181 return __m;
182 }
183
Howard Hinnant333f50d2010-09-21 20:16:37184 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09185 bool owns_lock() const _NOEXCEPT {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37186 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant77861882012-02-21 21:46:43187 _LIBCPP_EXPLICIT
Howard Hinnant499c61f2012-07-21 16:13:09188 operator bool () const _NOEXCEPT {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37189 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant499c61f2012-07-21 16:13:09190 mutex_type* mutex() const _NOEXCEPT {return __m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16191};
192
193template <class _Mutex>
194void
195unique_lock<_Mutex>::lock()
196{
197 if (__m_ == nullptr)
198 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
199 if (__owns_)
200 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
201 __m_->lock();
202 __owns_ = true;
203}
204
205template <class _Mutex>
206bool
207unique_lock<_Mutex>::try_lock()
208{
209 if (__m_ == nullptr)
210 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
211 if (__owns_)
212 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
213 __owns_ = __m_->try_lock();
214 return __owns_;
215}
216
217template <class _Mutex>
218template <class _Rep, class _Period>
219bool
220unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
221{
222 if (__m_ == nullptr)
223 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
224 if (__owns_)
225 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
226 __owns_ = __m_->try_lock_for(__d);
227 return __owns_;
228}
229
230template <class _Mutex>
231template <class _Clock, class _Duration>
232bool
233unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
234{
235 if (__m_ == nullptr)
236 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
237 if (__owns_)
238 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
239 __owns_ = __m_->try_lock_until(__t);
240 return __owns_;
241}
242
243template <class _Mutex>
244void
245unique_lock<_Mutex>::unlock()
246{
247 if (!__owns_)
248 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
249 __m_->unlock();
250 __owns_ = false;
251}
252
253template <class _Mutex>
Howard Hinnant333f50d2010-09-21 20:16:37254inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16255void
Howard Hinnant499c61f2012-07-21 16:13:09256swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
257 {__x.swap(__y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16258
Marshall Clow239bc422013-12-23 22:14:27259//enum class cv_status
260_LIBCPP_DECLARE_STRONG_ENUM(cv_status)
Howard Hinnantbc8d3f92010-05-11 19:42:16261{
Marshall Clow239bc422013-12-23 22:14:27262 no_timeout,
263 timeout
Howard Hinnantbc8d3f92010-05-11 19:42:16264};
Marshall Clow239bc422013-12-23 22:14:27265_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
Howard Hinnantbc8d3f92010-05-11 19:42:16266
Howard Hinnant83eade62013-03-06 23:30:19267class _LIBCPP_TYPE_VIS condition_variable
Howard Hinnantbc8d3f92010-05-11 19:42:16268{
269 pthread_cond_t __cv_;
270public:
Howard Hinnant333f50d2010-09-21 20:16:37271 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant384608e2012-07-07 20:01:52272#ifndef _LIBCPP_HAS_NO_CONSTEXPR
Howard Hinnant5c90cba2012-09-11 16:10:20273 constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
Howard Hinnant384608e2012-07-07 20:01:52274#else
Howard Hinnantbc8d3f92010-05-11 19:42:16275 condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
Howard Hinnant384608e2012-07-07 20:01:52276#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16277 ~condition_variable();
278
279private:
280 condition_variable(const condition_variable&); // = delete;
281 condition_variable& operator=(const condition_variable&); // = delete;
282
283public:
Howard Hinnantc8f74132012-07-21 16:32:53284 void notify_one() _NOEXCEPT;
285 void notify_all() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16286
Marshall Clowb0767852014-03-26 02:45:04287 void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16288 template <class _Predicate>
289 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
290
Howard Hinnantbc8d3f92010-05-11 19:42:16291 template <class _Clock, class _Duration>
292 cv_status
293 wait_until(unique_lock<mutex>& __lk,
294 const chrono::time_point<_Clock, _Duration>& __t);
295
296 template <class _Clock, class _Duration, class _Predicate>
297 bool
298 wait_until(unique_lock<mutex>& __lk,
299 const chrono::time_point<_Clock, _Duration>& __t,
300 _Predicate __pred);
301
302 template <class _Rep, class _Period>
303 cv_status
304 wait_for(unique_lock<mutex>& __lk,
305 const chrono::duration<_Rep, _Period>& __d);
306
307 template <class _Rep, class _Period, class _Predicate>
308 bool
309 wait_for(unique_lock<mutex>& __lk,
310 const chrono::duration<_Rep, _Period>& __d,
311 _Predicate __pred);
312
313 typedef pthread_cond_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:37314 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16315
316private:
317 void __do_timed_wait(unique_lock<mutex>& __lk,
Marshall Clowb0767852014-03-26 02:45:04318 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16319};
Jonathan Roelofs8d86b2e2014-09-05 19:45:05320#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnantbc8d3f92010-05-11 19:42:16321
322template <class _To, class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37323inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16324typename enable_if
325<
326 chrono::__is_duration<_To>::value,
327 _To
328>::type
329__ceil(chrono::duration<_Rep, _Period> __d)
330{
331 using namespace chrono;
332 _To __r = duration_cast<_To>(__d);
333 if (__r < __d)
334 ++__r;
335 return __r;
336}
337
Jonathan Roelofs8d86b2e2014-09-05 19:45:05338#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnantbc8d3f92010-05-11 19:42:16339template <class _Predicate>
340void
341condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
342{
343 while (!__pred())
344 wait(__lk);
345}
346
Howard Hinnantbc8d3f92010-05-11 19:42:16347template <class _Clock, class _Duration>
348cv_status
349condition_variable::wait_until(unique_lock<mutex>& __lk,
350 const chrono::time_point<_Clock, _Duration>& __t)
351{
352 using namespace chrono;
Howard Hinnantcf115d22012-08-30 19:14:33353 wait_for(__lk, __t - _Clock::now());
Howard Hinnantbc8d3f92010-05-11 19:42:16354 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
355}
356
357template <class _Clock, class _Duration, class _Predicate>
358bool
359condition_variable::wait_until(unique_lock<mutex>& __lk,
360 const chrono::time_point<_Clock, _Duration>& __t,
361 _Predicate __pred)
362{
363 while (!__pred())
364 {
365 if (wait_until(__lk, __t) == cv_status::timeout)
366 return __pred();
367 }
368 return true;
369}
370
371template <class _Rep, class _Period>
372cv_status
373condition_variable::wait_for(unique_lock<mutex>& __lk,
374 const chrono::duration<_Rep, _Period>& __d)
375{
376 using namespace chrono;
Howard Hinnantcf115d22012-08-30 19:14:33377 if (__d <= __d.zero())
378 return cv_status::timeout;
379 typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
380 typedef time_point<system_clock, nanoseconds> __sys_tpi;
381 __sys_tpf _Max = __sys_tpi::max();
Howard Hinnantf8f85212010-11-20 19:16:30382 system_clock::time_point __s_now = system_clock::now();
383 steady_clock::time_point __c_now = steady_clock::now();
Howard Hinnantcf115d22012-08-30 19:14:33384 if (_Max - __d > __s_now)
385 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
386 else
387 __do_timed_wait(__lk, __sys_tpi::max());
Howard Hinnantf8f85212010-11-20 19:16:30388 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
389 cv_status::timeout;
Howard Hinnantbc8d3f92010-05-11 19:42:16390}
391
392template <class _Rep, class _Period, class _Predicate>
Howard Hinnant333f50d2010-09-21 20:16:37393inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16394bool
395condition_variable::wait_for(unique_lock<mutex>& __lk,
396 const chrono::duration<_Rep, _Period>& __d,
397 _Predicate __pred)
398{
Howard Hinnantf8f85212010-11-20 19:16:30399 return wait_until(__lk, chrono::steady_clock::now() + __d,
Howard Hinnant0949eed2011-06-30 21:18:19400 _VSTD::move(__pred));
Howard Hinnantbc8d3f92010-05-11 19:42:16401}
402
Jonathan Roelofs8d86b2e2014-09-05 19:45:05403#endif // !_LIBCPP_HAS_NO_THREADS
404
Howard Hinnantbc8d3f92010-05-11 19:42:16405_LIBCPP_END_NAMESPACE_STD
406
407#endif // _LIBCPP___MUTEX_BASE