5b1f53aafe81e0a431679f20cf97f5578fab98b1
[platform/framework/web/crosswalk.git] / src / third_party / libc++ / trunk / include / shared_mutex
1 // -*- C++ -*-
2 //===------------------------ shared_mutex --------------------------------===//
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_SHARED_MUTEX
12 #define _LIBCPP_SHARED_MUTEX
13
14 /*
15     shared_mutex synopsis
16
17 // C++1y
18
19 namespace std
20 {
21
22 class shared_mutex
23 {
24 public:
25     shared_mutex();
26     ~shared_mutex();
27
28     shared_mutex(const shared_mutex&) = delete;
29     shared_mutex& operator=(const shared_mutex&) = delete;
30
31     // Exclusive ownership
32     void lock(); // blocking
33     bool try_lock();
34     template <class Rep, class Period>
35         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
36     template <class Clock, class Duration>
37         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
38     void unlock();
39
40     // Shared ownership
41     void lock_shared(); // blocking
42     bool try_lock_shared();
43     template <class Rep, class Period>
44         bool
45         try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
46     template <class Clock, class Duration>
47         bool
48         try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
49     void unlock_shared();
50 };
51
52 template <class Mutex>
53 class shared_lock
54 {
55 public:
56     typedef Mutex mutex_type;
57
58     // Shared locking
59     shared_lock() noexcept;
60     explicit shared_lock(mutex_type& m); // blocking
61     shared_lock(mutex_type& m, defer_lock_t) noexcept;
62     shared_lock(mutex_type& m, try_to_lock_t);
63     shared_lock(mutex_type& m, adopt_lock_t);
64     template <class Clock, class Duration>
65         shared_lock(mutex_type& m,
66                     const chrono::time_point<Clock, Duration>& abs_time);
67     template <class Rep, class Period>
68         shared_lock(mutex_type& m,
69                     const chrono::duration<Rep, Period>& rel_time);
70     ~shared_lock();
71
72     shared_lock(shared_lock const&) = delete;
73     shared_lock& operator=(shared_lock const&) = delete;
74
75     shared_lock(shared_lock&& u) noexcept;
76     shared_lock& operator=(shared_lock&& u) noexcept;
77
78     void lock(); // blocking
79     bool try_lock();
80     template <class Rep, class Period>
81         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
82     template <class Clock, class Duration>
83         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
84     void unlock();
85
86     // Setters
87     void swap(shared_lock& u) noexcept;
88     mutex_type* release() noexcept;
89
90     // Getters
91     bool owns_lock() const noexcept;
92     explicit operator bool () const noexcept;
93     mutex_type* mutex() const noexcept;
94 };
95
96 template <class Mutex>
97     void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
98
99 }  // std
100
101 */
102
103 #include <__config>
104
105 #if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_SHARED_MUTEX)
106
107 #include <__mutex_base>
108
109 #include <__undef_min_max>
110
111 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
112 #pragma GCC system_header
113 #endif
114
115 _LIBCPP_BEGIN_NAMESPACE_STD
116
117 class _LIBCPP_TYPE_VIS shared_mutex
118 {
119     mutex               __mut_;
120     condition_variable  __gate1_;
121     condition_variable  __gate2_;
122     unsigned            __state_;
123
124     static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
125     static const unsigned __n_readers_ = ~__write_entered_;
126 public:
127     shared_mutex();
128     _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
129
130     shared_mutex(const shared_mutex&) = delete;
131     shared_mutex& operator=(const shared_mutex&) = delete;
132
133     // Exclusive ownership
134     void lock();
135     bool try_lock();
136     template <class _Rep, class _Period>
137         _LIBCPP_INLINE_VISIBILITY
138         bool
139         try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
140         {
141             return try_lock_until(chrono::steady_clock::now() + __rel_time);
142         }
143     template <class _Clock, class _Duration>
144         bool
145         try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
146     void unlock();
147
148     // Shared ownership
149     void lock_shared();
150     bool try_lock_shared();
151     template <class _Rep, class _Period>
152         _LIBCPP_INLINE_VISIBILITY
153         bool
154         try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
155         {
156             return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
157         }
158     template <class _Clock, class _Duration>
159         bool
160         try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
161     void unlock_shared();
162 };
163
164 template <class _Clock, class _Duration>
165 bool
166 shared_mutex::try_lock_until(
167                         const chrono::time_point<_Clock, _Duration>& __abs_time)
168 {
169     unique_lock<mutex> __lk(__mut_);
170     if (__state_ & __write_entered_)
171     {
172         while (true)
173         {
174             cv_status __status = __gate1_.wait_until(__lk, __abs_time);
175             if ((__state_ & __write_entered_) == 0)
176                 break;
177             if (__status == cv_status::timeout)
178                 return false;
179         }
180     }
181     __state_ |= __write_entered_;
182     if (__state_ & __n_readers_)
183     {
184         while (true)
185         {
186             cv_status __status = __gate2_.wait_until(__lk, __abs_time);
187             if ((__state_ & __n_readers_) == 0)
188                 break;
189             if (__status == cv_status::timeout)
190             {
191                 __state_ &= ~__write_entered_;
192                 return false;
193             }
194         }
195     }
196     return true;
197 }
198
199 template <class _Clock, class _Duration>
200 bool
201 shared_mutex::try_lock_shared_until(
202                         const chrono::time_point<_Clock, _Duration>& __abs_time)
203 {
204     unique_lock<mutex> __lk(__mut_);
205     if ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
206     {
207         while (true)
208         {
209             cv_status status = __gate1_.wait_until(__lk, __abs_time);
210             if ((__state_ & __write_entered_) == 0 &&
211                                        (__state_ & __n_readers_) < __n_readers_)
212                 break;
213             if (status == cv_status::timeout)
214                 return false;
215         }
216     }
217     unsigned __num_readers = (__state_ & __n_readers_) + 1;
218     __state_ &= ~__n_readers_;
219     __state_ |= __num_readers;
220     return true;
221 }
222
223 template <class _Mutex>
224 class shared_lock
225 {
226 public:
227     typedef _Mutex mutex_type;
228
229 private:
230     mutex_type* __m_;
231     bool __owns_;
232
233 public:
234     _LIBCPP_INLINE_VISIBILITY
235     shared_lock() noexcept
236         : __m_(nullptr),
237           __owns_(false)
238         {}
239
240     _LIBCPP_INLINE_VISIBILITY
241     explicit shared_lock(mutex_type& __m)
242         : __m_(&__m),
243           __owns_(true)
244         {__m_->lock_shared();}
245
246     _LIBCPP_INLINE_VISIBILITY
247     shared_lock(mutex_type& __m, defer_lock_t) noexcept
248         : __m_(&__m),
249           __owns_(false)
250         {}
251
252     _LIBCPP_INLINE_VISIBILITY
253     shared_lock(mutex_type& __m, try_to_lock_t)
254         : __m_(&__m),
255           __owns_(__m.try_lock_shared())
256         {}
257
258     _LIBCPP_INLINE_VISIBILITY
259     shared_lock(mutex_type& __m, adopt_lock_t)
260         : __m_(&__m),
261           __owns_(true)
262         {}
263
264     template <class _Clock, class _Duration>
265         _LIBCPP_INLINE_VISIBILITY
266         shared_lock(mutex_type& __m,
267                     const chrono::time_point<_Clock, _Duration>& __abs_time)
268             : __m_(&__m),
269               __owns_(__m.try_lock_shared_until(__abs_time))
270             {}
271
272     template <class _Rep, class _Period>
273         _LIBCPP_INLINE_VISIBILITY
274         shared_lock(mutex_type& __m,
275                     const chrono::duration<_Rep, _Period>& __rel_time)
276             : __m_(&__m),
277               __owns_(__m.try_lock_shared_for(__rel_time))
278             {}
279
280     _LIBCPP_INLINE_VISIBILITY
281     ~shared_lock()
282     {
283         if (__owns_)
284             __m_->unlock_shared();
285     }
286
287     shared_lock(shared_lock const&) = delete;
288     shared_lock& operator=(shared_lock const&) = delete;
289
290     _LIBCPP_INLINE_VISIBILITY
291     shared_lock(shared_lock&& __u) noexcept
292         : __m_(__u.__m_),
293           __owns_(__u.__owns_)
294         {
295             __u.__m_ = nullptr;
296             __u.__owns_ = false;
297         }
298
299     _LIBCPP_INLINE_VISIBILITY
300     shared_lock& operator=(shared_lock&& __u) noexcept
301     {
302         if (__owns_)
303             __m_->unlock_shared();
304         __m_ = nullptr;
305         __owns_ = false;
306         __m_ = __u.__m_;
307         __owns_ = __u.__owns_;
308         __u.__m_ = nullptr;
309         __u.__owns_ = false;
310         return *this;
311     }
312
313     void lock();
314     bool try_lock();
315     template <class Rep, class Period>
316         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
317     template <class Clock, class Duration>
318         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
319     void unlock();
320
321     // Setters
322     _LIBCPP_INLINE_VISIBILITY
323     void swap(shared_lock& __u) noexcept
324     {
325         _VSTD::swap(__m_, __u.__m_);
326         _VSTD::swap(__owns_, __u.__owns_);
327     }
328
329     _LIBCPP_INLINE_VISIBILITY
330     mutex_type* release() noexcept
331     {
332         mutex_type* __m = __m_;
333         __m_ = nullptr;
334         __owns_ = false;
335         return __m;
336     }
337
338     // Getters
339     _LIBCPP_INLINE_VISIBILITY
340     bool owns_lock() const noexcept {return __owns_;}
341
342     _LIBCPP_INLINE_VISIBILITY
343     explicit operator bool () const noexcept {return __owns_;}
344
345     _LIBCPP_INLINE_VISIBILITY
346     mutex_type* mutex() const noexcept {return __m_;}
347 };
348
349 template <class _Mutex>
350 void
351 shared_lock<_Mutex>::lock()
352 {
353     if (__m_ == nullptr)
354         __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
355     if (__owns_)
356         __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
357     __m_->lock_shared();
358     __owns_ = true;
359 }
360
361 template <class _Mutex>
362 bool
363 shared_lock<_Mutex>::try_lock()
364 {
365     if (__m_ == nullptr)
366         __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
367     if (__owns_)
368         __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
369     __owns_ = __m_->try_lock_shared();
370     return __owns_;
371 }
372
373 template <class _Mutex>
374 template <class _Rep, class _Period>
375 bool
376 shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
377 {
378     if (__m_ == nullptr)
379         __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
380     if (__owns_)
381         __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
382     __owns_ = __m_->try_lock_shared_for(__d);
383     return __owns_;
384 }
385
386 template <class _Mutex>
387 template <class _Clock, class _Duration>
388 bool
389 shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
390 {
391     if (__m_ == nullptr)
392         __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
393     if (__owns_)
394         __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
395     __owns_ = __m_->try_lock_shared_until(__t);
396     return __owns_;
397 }
398
399 template <class _Mutex>
400 void
401 shared_lock<_Mutex>::unlock()
402 {
403     if (!__owns_)
404         __throw_system_error(EPERM, "shared_lock::unlock: not locked");
405     __m_->unlock_shared();
406     __owns_ = false;
407 }
408
409 template <class _Mutex>
410 inline _LIBCPP_INLINE_VISIBILITY
411 void
412 swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) noexcept
413     {__x.swap(__y);}
414
415 _LIBCPP_END_NAMESPACE_STD
416
417 #endif  // _LIBCPP_STD_VER > 11
418
419 #endif  // _LIBCPP_SHARED_MUTEX