blob: 854f02c436f911e71aecae5a459bc9a0d4cdc8f3 [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
Howard Hinnantac417fa2010-11-28 19:41:0723#ifdef _LIBCPP_SHARED_LOCK
24
25namespace ting {
Howard Hinnant2b1b2d42011-06-14 19:58:1726template <class _Mutex> class shared_lock;
27template <class _Mutex> class upgrade_lock;
Howard Hinnantac417fa2010-11-28 19:41:0728}
29
30#endif // _LIBCPP_SHARED_LOCK
31
32
Howard Hinnantbc8d3f92010-05-11 19:42:1633_LIBCPP_BEGIN_NAMESPACE_STD
34
Howard Hinnant333f50d2010-09-21 20:16:3735class _LIBCPP_VISIBLE mutex
Howard Hinnantbc8d3f92010-05-11 19:42:1636{
37 pthread_mutex_t __m_;
38
39public:
Howard Hinnant333f50d2010-09-21 20:16:3740 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant384608e2012-07-07 20:01:5241#ifndef _LIBCPP_HAS_NO_CONSTEXPR
42 constexpr mutex() : __m_ PTHREAD_MUTEX_INITIALIZER {}
43#else
Howard Hinnantbc8d3f92010-05-11 19:42:1644 mutex() {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
Howard Hinnant384608e2012-07-07 20:01:5245#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1646 ~mutex();
47
48private:
49 mutex(const mutex&);// = delete;
50 mutex& operator=(const mutex&);// = delete;
51
52public:
53 void lock();
54 bool try_lock();
55 void unlock();
56
57 typedef pthread_mutex_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:3758 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
Howard Hinnantbc8d3f92010-05-11 19:42:1659};
60
Howard Hinnant333f50d2010-09-21 20:16:3761struct _LIBCPP_VISIBLE defer_lock_t {};
62struct _LIBCPP_VISIBLE try_to_lock_t {};
63struct _LIBCPP_VISIBLE adopt_lock_t {};
Howard Hinnantbc8d3f92010-05-11 19:42:1664
65//constexpr
66extern const
67defer_lock_t defer_lock;
68
69//constexpr
70extern const
71try_to_lock_t try_to_lock;
72
73//constexpr
74extern const
75adopt_lock_t adopt_lock;
76
77template <class _Mutex>
Howard Hinnant333f50d2010-09-21 20:16:3778class _LIBCPP_VISIBLE lock_guard
Howard Hinnantbc8d3f92010-05-11 19:42:1679{
80public:
81 typedef _Mutex mutex_type;
82
83private:
84 mutex_type& __m_;
85public:
86
Howard Hinnant333f50d2010-09-21 20:16:3787 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1688 explicit lock_guard(mutex_type& __m)
89 : __m_(__m) {__m_.lock();}
Howard Hinnant333f50d2010-09-21 20:16:3790 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1691 lock_guard(mutex_type& __m, adopt_lock_t)
92 : __m_(__m) {}
Howard Hinnant333f50d2010-09-21 20:16:3793 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:1694 ~lock_guard() {__m_.unlock();}
95
96private:
97 lock_guard(lock_guard const&);// = delete;
98 lock_guard& operator=(lock_guard const&);// = delete;
99};
100
101template <class _Mutex>
Howard Hinnant333f50d2010-09-21 20:16:37102class _LIBCPP_VISIBLE unique_lock
Howard Hinnantbc8d3f92010-05-11 19:42:16103{
104public:
105 typedef _Mutex mutex_type;
106
107private:
108 mutex_type* __m_;
109 bool __owns_;
110
111public:
Howard Hinnant333f50d2010-09-21 20:16:37112 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16113 unique_lock() : __m_(nullptr), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37114 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16115 explicit unique_lock(mutex_type& __m)
116 : __m_(&__m), __owns_(true) {__m_->lock();}
Howard Hinnant333f50d2010-09-21 20:16:37117 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16118 unique_lock(mutex_type& __m, defer_lock_t)
119 : __m_(&__m), __owns_(false) {}
Howard Hinnant333f50d2010-09-21 20:16:37120 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16121 unique_lock(mutex_type& __m, try_to_lock_t)
122 : __m_(&__m), __owns_(__m.try_lock()) {}
Howard Hinnant333f50d2010-09-21 20:16:37123 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16124 unique_lock(mutex_type& __m, adopt_lock_t)
125 : __m_(&__m), __owns_(true) {}
126 template <class _Clock, class _Duration>
Howard Hinnant333f50d2010-09-21 20:16:37127 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16128 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
129 : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
130 template <class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37131 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16132 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
133 : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
Howard Hinnant333f50d2010-09-21 20:16:37134 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16135 ~unique_lock()
136 {
137 if (__owns_)
138 __m_->unlock();
139 }
140
141private:
142 unique_lock(unique_lock const&); // = delete;
143 unique_lock& operator=(unique_lock const&); // = delete;
144
145public:
Howard Hinnant73d21a42010-09-04 23:28:19146#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant333f50d2010-09-21 20:16:37147 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16148 unique_lock(unique_lock&& __u)
149 : __m_(__u.__m_), __owns_(__u.__owns_)
150 {__u.__m_ = nullptr; __u.__owns_ = false;}
Howard Hinnant333f50d2010-09-21 20:16:37151 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16152 unique_lock& operator=(unique_lock&& __u)
153 {
154 if (__owns_)
155 __m_->unlock();
156 __m_ = __u.__m_;
157 __owns_ = __u.__owns_;
158 __u.__m_ = nullptr;
159 __u.__owns_ = false;
160 return *this;
161 }
Howard Hinnantac417fa2010-11-28 19:41:07162
163#ifdef _LIBCPP_SHARED_LOCK
164
165 unique_lock(ting::shared_lock<mutex_type>&&, try_to_lock_t);
166 template <class _Clock, class _Duration>
167 unique_lock(ting::shared_lock<mutex_type>&&,
168 const chrono::time_point<_Clock, _Duration>&);
169 template <class _Rep, class _Period>
170 unique_lock(ting::shared_lock<mutex_type>&&,
171 const chrono::duration<_Rep, _Period>&);
172
173 explicit unique_lock(ting::upgrade_lock<mutex_type>&&);
174 unique_lock(ting::upgrade_lock<mutex_type>&&, try_to_lock_t);
175 template <class _Clock, class _Duration>
176 unique_lock(ting::upgrade_lock<mutex_type>&&,
177 const chrono::time_point<_Clock, _Duration>&);
178 template <class _Rep, class _Period>
179 unique_lock(ting::upgrade_lock<mutex_type>&&,
180 const chrono::duration<_Rep, _Period>&);
181
182#endif // _LIBCPP_SHARED_LOCK
183
Howard Hinnant73d21a42010-09-04 23:28:19184#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16185
186 void lock();
187 bool try_lock();
188
189 template <class _Rep, class _Period>
190 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
191 template <class _Clock, class _Duration>
192 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
193
194 void unlock();
195
Howard Hinnant333f50d2010-09-21 20:16:37196 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16197 void swap(unique_lock& __u)
198 {
Howard Hinnant0949eed2011-06-30 21:18:19199 _VSTD::swap(__m_, __u.__m_);
200 _VSTD::swap(__owns_, __u.__owns_);
Howard Hinnantbc8d3f92010-05-11 19:42:16201 }
Howard Hinnant333f50d2010-09-21 20:16:37202 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16203 mutex_type* release()
204 {
205 mutex_type* __m = __m_;
206 __m_ = nullptr;
207 __owns_ = false;
208 return __m;
209 }
210
Howard Hinnant333f50d2010-09-21 20:16:37211 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16212 bool owns_lock() const {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37213 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant77861882012-02-21 21:46:43214 _LIBCPP_EXPLICIT
Howard Hinnantbc8d3f92010-05-11 19:42:16215 operator bool () const {return __owns_;}
Howard Hinnant333f50d2010-09-21 20:16:37216 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16217 mutex_type* mutex() const {return __m_;}
218};
219
220template <class _Mutex>
221void
222unique_lock<_Mutex>::lock()
223{
224 if (__m_ == nullptr)
225 __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
226 if (__owns_)
227 __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
228 __m_->lock();
229 __owns_ = true;
230}
231
232template <class _Mutex>
233bool
234unique_lock<_Mutex>::try_lock()
235{
236 if (__m_ == nullptr)
237 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
238 if (__owns_)
239 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
240 __owns_ = __m_->try_lock();
241 return __owns_;
242}
243
244template <class _Mutex>
245template <class _Rep, class _Period>
246bool
247unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
248{
249 if (__m_ == nullptr)
250 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
251 if (__owns_)
252 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
253 __owns_ = __m_->try_lock_for(__d);
254 return __owns_;
255}
256
257template <class _Mutex>
258template <class _Clock, class _Duration>
259bool
260unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
261{
262 if (__m_ == nullptr)
263 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
264 if (__owns_)
265 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
266 __owns_ = __m_->try_lock_until(__t);
267 return __owns_;
268}
269
270template <class _Mutex>
271void
272unique_lock<_Mutex>::unlock()
273{
274 if (!__owns_)
275 __throw_system_error(EPERM, "unique_lock::unlock: not locked");
276 __m_->unlock();
277 __owns_ = false;
278}
279
280template <class _Mutex>
Howard Hinnant333f50d2010-09-21 20:16:37281inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16282void
283swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) {__x.swap(__y);}
284
Howard Hinnant333f50d2010-09-21 20:16:37285struct _LIBCPP_VISIBLE cv_status
Howard Hinnantbc8d3f92010-05-11 19:42:16286{
287 enum _ {
288 no_timeout,
289 timeout
290 };
291
292 _ __v_;
293
Howard Hinnant333f50d2010-09-21 20:16:37294 _LIBCPP_INLINE_VISIBILITY cv_status(_ __v) : __v_(__v) {}
295 _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16296
297};
298
Howard Hinnant333f50d2010-09-21 20:16:37299class _LIBCPP_VISIBLE condition_variable
Howard Hinnantbc8d3f92010-05-11 19:42:16300{
301 pthread_cond_t __cv_;
302public:
Howard Hinnant333f50d2010-09-21 20:16:37303 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant384608e2012-07-07 20:01:52304#ifndef _LIBCPP_HAS_NO_CONSTEXPR
305 constexpr condition_variable() : __cv_ PTHREAD_COND_INITIALIZER {}
306#else
Howard Hinnantbc8d3f92010-05-11 19:42:16307 condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
Howard Hinnant384608e2012-07-07 20:01:52308#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16309 ~condition_variable();
310
311private:
312 condition_variable(const condition_variable&); // = delete;
313 condition_variable& operator=(const condition_variable&); // = delete;
314
315public:
316 void notify_one();
317 void notify_all();
318
319 void wait(unique_lock<mutex>& __lk);
320 template <class _Predicate>
321 void wait(unique_lock<mutex>& __lk, _Predicate __pred);
322
323 template <class _Duration>
324 cv_status
325 wait_until(unique_lock<mutex>& __lk,
326 const chrono::time_point<chrono::system_clock, _Duration>& __t);
327
328 template <class _Clock, class _Duration>
329 cv_status
330 wait_until(unique_lock<mutex>& __lk,
331 const chrono::time_point<_Clock, _Duration>& __t);
332
333 template <class _Clock, class _Duration, class _Predicate>
334 bool
335 wait_until(unique_lock<mutex>& __lk,
336 const chrono::time_point<_Clock, _Duration>& __t,
337 _Predicate __pred);
338
339 template <class _Rep, class _Period>
340 cv_status
341 wait_for(unique_lock<mutex>& __lk,
342 const chrono::duration<_Rep, _Period>& __d);
343
344 template <class _Rep, class _Period, class _Predicate>
345 bool
346 wait_for(unique_lock<mutex>& __lk,
347 const chrono::duration<_Rep, _Period>& __d,
348 _Predicate __pred);
349
350 typedef pthread_cond_t* native_handle_type;
Howard Hinnant333f50d2010-09-21 20:16:37351 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16352
353private:
354 void __do_timed_wait(unique_lock<mutex>& __lk,
355 chrono::time_point<chrono::system_clock, chrono::nanoseconds>);
356};
357
358template <class _To, class _Rep, class _Period>
Howard Hinnant333f50d2010-09-21 20:16:37359inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16360typename enable_if
361<
362 chrono::__is_duration<_To>::value,
363 _To
364>::type
365__ceil(chrono::duration<_Rep, _Period> __d)
366{
367 using namespace chrono;
368 _To __r = duration_cast<_To>(__d);
369 if (__r < __d)
370 ++__r;
371 return __r;
372}
373
374template <class _Predicate>
375void
376condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
377{
378 while (!__pred())
379 wait(__lk);
380}
381
382template <class _Duration>
383cv_status
384condition_variable::wait_until(unique_lock<mutex>& __lk,
385 const chrono::time_point<chrono::system_clock, _Duration>& __t)
386{
387 using namespace chrono;
388 typedef time_point<system_clock, nanoseconds> __nano_sys_tmpt;
389 __do_timed_wait(__lk,
390 __nano_sys_tmpt(__ceil<nanoseconds>(__t.time_since_epoch())));
391 return system_clock::now() < __t ? cv_status::no_timeout :
392 cv_status::timeout;
393}
394
395template <class _Clock, class _Duration>
396cv_status
397condition_variable::wait_until(unique_lock<mutex>& __lk,
398 const chrono::time_point<_Clock, _Duration>& __t)
399{
400 using namespace chrono;
401 system_clock::time_point __s_now = system_clock::now();
402 typename _Clock::time_point __c_now = _Clock::now();
403 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__t - __c_now));
404 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
405}
406
407template <class _Clock, class _Duration, class _Predicate>
408bool
409condition_variable::wait_until(unique_lock<mutex>& __lk,
410 const chrono::time_point<_Clock, _Duration>& __t,
411 _Predicate __pred)
412{
413 while (!__pred())
414 {
415 if (wait_until(__lk, __t) == cv_status::timeout)
416 return __pred();
417 }
418 return true;
419}
420
421template <class _Rep, class _Period>
422cv_status
423condition_variable::wait_for(unique_lock<mutex>& __lk,
424 const chrono::duration<_Rep, _Period>& __d)
425{
426 using namespace chrono;
Howard Hinnantf8f85212010-11-20 19:16:30427 system_clock::time_point __s_now = system_clock::now();
428 steady_clock::time_point __c_now = steady_clock::now();
Howard Hinnantbc8d3f92010-05-11 19:42:16429 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
Howard Hinnantf8f85212010-11-20 19:16:30430 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
431 cv_status::timeout;
Howard Hinnantbc8d3f92010-05-11 19:42:16432}
433
434template <class _Rep, class _Period, class _Predicate>
Howard Hinnant333f50d2010-09-21 20:16:37435inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16436bool
437condition_variable::wait_for(unique_lock<mutex>& __lk,
438 const chrono::duration<_Rep, _Period>& __d,
439 _Predicate __pred)
440{
Howard Hinnantf8f85212010-11-20 19:16:30441 return wait_until(__lk, chrono::steady_clock::now() + __d,
Howard Hinnant0949eed2011-06-30 21:18:19442 _VSTD::move(__pred));
Howard Hinnantbc8d3f92010-05-11 19:42:16443}
444
445_LIBCPP_END_NAMESPACE_STD
446
447#endif // _LIBCPP___MUTEX_BASE