]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/libc++/include/__mutex_base
Merged libcxxrt and libc++. Now available for testing on 9-stable with
[FreeBSD/stable/9.git] / contrib / libc++ / include / __mutex_base
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
8 //
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
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #pragma GCC system_header
21 #endif
22
23 #ifdef _LIBCPP_SHARED_LOCK
24
25 namespace ting {
26 template <class _Mutex> class shared_lock;
27 template <class _Mutex> class upgrade_lock;
28 }
29
30 #endif  // _LIBCPP_SHARED_LOCK
31
32
33 _LIBCPP_BEGIN_NAMESPACE_STD
34
35 class _LIBCPP_VISIBLE mutex
36 {
37     pthread_mutex_t __m_;
38
39 public:
40     _LIBCPP_INLINE_VISIBILITY
41      mutex() {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
42      ~mutex();
43
44 private:
45     mutex(const mutex&);// = delete;
46     mutex& operator=(const mutex&);// = delete;
47
48 public:
49     void lock();
50     bool try_lock();
51     void unlock();
52
53     typedef pthread_mutex_t* native_handle_type;
54     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
55 };
56
57 struct _LIBCPP_VISIBLE defer_lock_t {};
58 struct _LIBCPP_VISIBLE try_to_lock_t {};
59 struct _LIBCPP_VISIBLE adopt_lock_t {};
60
61 //constexpr
62 extern const
63 defer_lock_t  defer_lock;
64
65 //constexpr
66 extern const
67 try_to_lock_t try_to_lock;
68
69 //constexpr
70 extern const
71 adopt_lock_t  adopt_lock;
72
73 template <class _Mutex>
74 class _LIBCPP_VISIBLE lock_guard
75 {
76 public:
77     typedef _Mutex mutex_type;
78
79 private:
80     mutex_type& __m_;
81 public:
82
83     _LIBCPP_INLINE_VISIBILITY
84     explicit lock_guard(mutex_type& __m)
85         : __m_(__m) {__m_.lock();}
86     _LIBCPP_INLINE_VISIBILITY
87     lock_guard(mutex_type& __m, adopt_lock_t)
88         : __m_(__m) {}
89     _LIBCPP_INLINE_VISIBILITY
90     ~lock_guard() {__m_.unlock();}
91
92 private:
93     lock_guard(lock_guard const&);// = delete;
94     lock_guard& operator=(lock_guard const&);// = delete;
95 };
96
97 template <class _Mutex>
98 class _LIBCPP_VISIBLE unique_lock
99 {
100 public:
101     typedef _Mutex mutex_type;
102
103 private:
104     mutex_type* __m_;
105     bool __owns_;
106
107 public:
108     _LIBCPP_INLINE_VISIBILITY
109     unique_lock() : __m_(nullptr), __owns_(false) {}
110     _LIBCPP_INLINE_VISIBILITY
111     explicit unique_lock(mutex_type& __m)
112         : __m_(&__m), __owns_(true) {__m_->lock();}
113     _LIBCPP_INLINE_VISIBILITY
114     unique_lock(mutex_type& __m, defer_lock_t)
115         : __m_(&__m), __owns_(false) {}
116     _LIBCPP_INLINE_VISIBILITY
117     unique_lock(mutex_type& __m, try_to_lock_t)
118         : __m_(&__m), __owns_(__m.try_lock()) {}
119     _LIBCPP_INLINE_VISIBILITY
120     unique_lock(mutex_type& __m, adopt_lock_t)
121         : __m_(&__m), __owns_(true) {}
122     template <class _Clock, class _Duration>
123     _LIBCPP_INLINE_VISIBILITY
124         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>
127     _LIBCPP_INLINE_VISIBILITY
128         unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
129             : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
130     _LIBCPP_INLINE_VISIBILITY
131     ~unique_lock()
132     {
133         if (__owns_)
134             __m_->unlock();
135     }
136
137 private:
138     unique_lock(unique_lock const&); // = delete;
139     unique_lock& operator=(unique_lock const&); // = delete;
140
141 public:
142 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
143     _LIBCPP_INLINE_VISIBILITY
144     unique_lock(unique_lock&& __u)
145         : __m_(__u.__m_), __owns_(__u.__owns_)
146         {__u.__m_ = nullptr; __u.__owns_ = false;}
147     _LIBCPP_INLINE_VISIBILITY
148     unique_lock& operator=(unique_lock&& __u)
149         {
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         }
158
159 #ifdef _LIBCPP_SHARED_LOCK
160
161     unique_lock(ting::shared_lock<mutex_type>&&, try_to_lock_t);
162     template <class _Clock, class _Duration>
163         unique_lock(ting::shared_lock<mutex_type>&&,
164                     const chrono::time_point<_Clock, _Duration>&);
165     template <class _Rep, class _Period>
166         unique_lock(ting::shared_lock<mutex_type>&&,
167                     const chrono::duration<_Rep, _Period>&);
168
169     explicit unique_lock(ting::upgrade_lock<mutex_type>&&);
170     unique_lock(ting::upgrade_lock<mutex_type>&&, try_to_lock_t);
171     template <class _Clock, class _Duration>
172         unique_lock(ting::upgrade_lock<mutex_type>&&,
173                     const chrono::time_point<_Clock, _Duration>&);
174     template <class _Rep, class _Period>
175         unique_lock(ting::upgrade_lock<mutex_type>&&,
176                     const chrono::duration<_Rep, _Period>&);
177
178 #endif  // _LIBCPP_SHARED_LOCK
179
180 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
181
182     void lock();
183     bool try_lock();
184
185     template <class _Rep, class _Period>
186         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
187     template <class _Clock, class _Duration>
188         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
189
190     void unlock();
191
192     _LIBCPP_INLINE_VISIBILITY
193     void swap(unique_lock& __u)
194     {
195         _VSTD::swap(__m_, __u.__m_);
196         _VSTD::swap(__owns_, __u.__owns_);
197     }
198     _LIBCPP_INLINE_VISIBILITY
199     mutex_type* release()
200     {
201         mutex_type* __m = __m_;
202         __m_ = nullptr;
203         __owns_ = false;
204         return __m;
205     }
206
207     _LIBCPP_INLINE_VISIBILITY
208     bool owns_lock() const {return __owns_;}
209     _LIBCPP_INLINE_VISIBILITY
210     _LIBCPP_EXPLICIT
211         operator bool () const {return __owns_;}
212     _LIBCPP_INLINE_VISIBILITY
213     mutex_type* mutex() const {return __m_;}
214 };
215
216 template <class _Mutex>
217 void
218 unique_lock<_Mutex>::lock()
219 {
220     if (__m_ == nullptr)
221         __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
222     if (__owns_)
223         __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
224     __m_->lock();
225     __owns_ = true;
226 }
227
228 template <class _Mutex>
229 bool
230 unique_lock<_Mutex>::try_lock()
231 {
232     if (__m_ == nullptr)
233         __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
234     if (__owns_)
235         __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
236     __owns_ = __m_->try_lock();
237     return __owns_;
238 }
239
240 template <class _Mutex>
241 template <class _Rep, class _Period>
242 bool
243 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
244 {
245     if (__m_ == nullptr)
246         __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
247     if (__owns_)
248         __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
249     __owns_ = __m_->try_lock_for(__d);
250     return __owns_;
251 }
252
253 template <class _Mutex>
254 template <class _Clock, class _Duration>
255 bool
256 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
257 {
258     if (__m_ == nullptr)
259         __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
260     if (__owns_)
261         __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
262     __owns_ = __m_->try_lock_until(__t);
263     return __owns_;
264 }
265
266 template <class _Mutex>
267 void
268 unique_lock<_Mutex>::unlock()
269 {
270     if (!__owns_)
271         __throw_system_error(EPERM, "unique_lock::unlock: not locked");
272     __m_->unlock();
273     __owns_ = false;
274 }
275
276 template <class _Mutex>
277 inline _LIBCPP_INLINE_VISIBILITY
278 void
279 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) {__x.swap(__y);}
280
281 struct _LIBCPP_VISIBLE cv_status
282 {
283     enum _ {
284         no_timeout,
285         timeout
286     };
287
288     _ __v_;
289
290     _LIBCPP_INLINE_VISIBILITY cv_status(_ __v) : __v_(__v) {}
291     _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;}
292
293 };
294
295 class _LIBCPP_VISIBLE condition_variable
296 {
297     pthread_cond_t __cv_;
298 public:
299     _LIBCPP_INLINE_VISIBILITY
300     condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
301     ~condition_variable();
302
303 private:
304     condition_variable(const condition_variable&); // = delete;
305     condition_variable& operator=(const condition_variable&); // = delete;
306
307 public:
308     void notify_one();
309     void notify_all();
310
311     void wait(unique_lock<mutex>& __lk);
312     template <class _Predicate>
313         void wait(unique_lock<mutex>& __lk, _Predicate __pred);
314
315     template <class _Duration>
316         cv_status
317         wait_until(unique_lock<mutex>& __lk,
318                    const chrono::time_point<chrono::system_clock, _Duration>& __t);
319
320     template <class _Clock, class _Duration>
321         cv_status
322         wait_until(unique_lock<mutex>& __lk,
323                    const chrono::time_point<_Clock, _Duration>& __t);
324
325     template <class _Clock, class _Duration, class _Predicate>
326         bool
327         wait_until(unique_lock<mutex>& __lk,
328                    const chrono::time_point<_Clock, _Duration>& __t,
329                    _Predicate __pred);
330
331     template <class _Rep, class _Period>
332         cv_status
333         wait_for(unique_lock<mutex>& __lk,
334                  const chrono::duration<_Rep, _Period>& __d);
335
336     template <class _Rep, class _Period, class _Predicate>
337         bool
338         wait_for(unique_lock<mutex>& __lk,
339                  const chrono::duration<_Rep, _Period>& __d,
340                  _Predicate __pred);
341
342     typedef pthread_cond_t* native_handle_type;
343     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
344
345 private:
346     void __do_timed_wait(unique_lock<mutex>& __lk,
347                  chrono::time_point<chrono::system_clock, chrono::nanoseconds>);
348 };
349
350 template <class _To, class _Rep, class _Period>
351 inline _LIBCPP_INLINE_VISIBILITY
352 typename enable_if
353 <
354     chrono::__is_duration<_To>::value,
355     _To
356 >::type
357 __ceil(chrono::duration<_Rep, _Period> __d)
358 {
359     using namespace chrono;
360     _To __r = duration_cast<_To>(__d);
361     if (__r < __d)
362         ++__r;
363     return __r;
364 }
365
366 template <class _Predicate>
367 void
368 condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
369 {
370     while (!__pred())
371         wait(__lk);
372 }
373
374 template <class _Duration>
375 cv_status
376 condition_variable::wait_until(unique_lock<mutex>& __lk,
377                  const chrono::time_point<chrono::system_clock, _Duration>& __t)
378 {
379     using namespace chrono;
380     typedef time_point<system_clock, nanoseconds> __nano_sys_tmpt;
381     __do_timed_wait(__lk,
382                   __nano_sys_tmpt(__ceil<nanoseconds>(__t.time_since_epoch())));
383     return system_clock::now() < __t ? cv_status::no_timeout :
384                                        cv_status::timeout;
385 }
386
387 template <class _Clock, class _Duration>
388 cv_status
389 condition_variable::wait_until(unique_lock<mutex>& __lk,
390                                const chrono::time_point<_Clock, _Duration>& __t)
391 {
392     using namespace chrono;
393     system_clock::time_point     __s_now = system_clock::now();
394     typename _Clock::time_point  __c_now = _Clock::now();
395     __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__t - __c_now));
396     return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
397 }
398
399 template <class _Clock, class _Duration, class _Predicate>
400 bool
401 condition_variable::wait_until(unique_lock<mutex>& __lk,
402                    const chrono::time_point<_Clock, _Duration>& __t,
403                    _Predicate __pred)
404 {
405     while (!__pred())
406     {
407         if (wait_until(__lk, __t) == cv_status::timeout)
408             return __pred();
409     }
410     return true;
411 }
412
413 template <class _Rep, class _Period>
414 cv_status
415 condition_variable::wait_for(unique_lock<mutex>& __lk,
416                              const chrono::duration<_Rep, _Period>& __d)
417 {
418     using namespace chrono;
419     system_clock::time_point __s_now = system_clock::now();
420     steady_clock::time_point __c_now = steady_clock::now();
421     __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
422     return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
423                                                  cv_status::timeout;
424 }
425
426 template <class _Rep, class _Period, class _Predicate>
427 inline _LIBCPP_INLINE_VISIBILITY
428 bool
429 condition_variable::wait_for(unique_lock<mutex>& __lk,
430                              const chrono::duration<_Rep, _Period>& __d,
431                              _Predicate __pred)
432 {
433     return wait_until(__lk, chrono::steady_clock::now() + __d,
434                       _VSTD::move(__pred));
435 }
436
437 _LIBCPP_END_NAMESPACE_STD
438
439 #endif  // _LIBCPP___MUTEX_BASE