Remove building with NOCRYPTO option
[minix.git] / external / bsd / libc++ / dist / libcxx / include / shared_mutex
blobdcb93949e30d389177366f580fc6f40326894f79
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 //===----------------------------------------------------------------------===//
11 #ifndef _LIBCPP_SHARED_MUTEX
12 #define _LIBCPP_SHARED_MUTEX
15     shared_mutex synopsis
17 // C++1y
19 namespace std
22 class shared_mutex      // C++17
24 public:
25     shared_mutex();
26     ~shared_mutex();
28     shared_mutex(const shared_mutex&) = delete;
29     shared_mutex& operator=(const shared_mutex&) = delete;
31     // Exclusive ownership
32     void lock(); // blocking
33     bool try_lock();
34     void unlock();
36     // Shared ownership
37     void lock_shared(); // blocking
38     bool try_lock_shared();
39     void unlock_shared();
41     typedef implementation-defined native_handle_type; // See 30.2.3
42     native_handle_type native_handle(); // See 30.2.3
45 class shared_timed_mutex
47 public:
48     shared_timed_mutex();
49     ~shared_timed_mutex();
51     shared_timed_mutex(const shared_timed_mutex&) = delete;
52     shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
54     // Exclusive ownership
55     void lock(); // blocking
56     bool try_lock();
57     template <class Rep, class Period>
58         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
59     template <class Clock, class Duration>
60         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
61     void unlock();
63     // Shared ownership
64     void lock_shared(); // blocking
65     bool try_lock_shared();
66     template <class Rep, class Period>
67         bool
68         try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
69     template <class Clock, class Duration>
70         bool
71         try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
72     void unlock_shared();
75 template <class Mutex>
76 class shared_lock
78 public:
79     typedef Mutex mutex_type;
81     // Shared locking
82     shared_lock() noexcept;
83     explicit shared_lock(mutex_type& m); // blocking
84     shared_lock(mutex_type& m, defer_lock_t) noexcept;
85     shared_lock(mutex_type& m, try_to_lock_t);
86     shared_lock(mutex_type& m, adopt_lock_t);
87     template <class Clock, class Duration>
88         shared_lock(mutex_type& m,
89                     const chrono::time_point<Clock, Duration>& abs_time);
90     template <class Rep, class Period>
91         shared_lock(mutex_type& m,
92                     const chrono::duration<Rep, Period>& rel_time);
93     ~shared_lock();
95     shared_lock(shared_lock const&) = delete;
96     shared_lock& operator=(shared_lock const&) = delete;
98     shared_lock(shared_lock&& u) noexcept;
99     shared_lock& operator=(shared_lock&& u) noexcept;
101     void lock(); // blocking
102     bool try_lock();
103     template <class Rep, class Period>
104         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
105     template <class Clock, class Duration>
106         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
107     void unlock();
109     // Setters
110     void swap(shared_lock& u) noexcept;
111     mutex_type* release() noexcept;
113     // Getters
114     bool owns_lock() const noexcept;
115     explicit operator bool () const noexcept;
116     mutex_type* mutex() const noexcept;
119 template <class Mutex>
120     void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
122 }  // std
126 #include <__config>
128 #if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_SHARED_MUTEX)
130 #include <__mutex_base>
132 #include <__undef_min_max>
134 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
135 #pragma GCC system_header
136 #endif
138 #ifdef _LIBCPP_HAS_NO_THREADS
139 #error <shared_mutex> is not supported on this single threaded system
140 #else // !_LIBCPP_HAS_NO_THREADS
142 _LIBCPP_BEGIN_NAMESPACE_STD
144 struct _LIBCPP_TYPE_VIS __shared_mutex_base
146     mutex               __mut_;
147     condition_variable  __gate1_;
148     condition_variable  __gate2_;
149     unsigned            __state_;
151     static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
152     static const unsigned __n_readers_ = ~__write_entered_;
154     __shared_mutex_base();
155     _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default;
157     __shared_mutex_base(const __shared_mutex_base&) = delete;
158     __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
160     // Exclusive ownership
161     void lock(); // blocking
162     bool try_lock();
163     void unlock();
165     // Shared ownership
166     void lock_shared(); // blocking
167     bool try_lock_shared();
168     void unlock_shared();
170 //     typedef implementation-defined native_handle_type; // See 30.2.3
171 //     native_handle_type native_handle(); // See 30.2.3
175 #if _LIBCPP_STD_VER > 14
176 class _LIBCPP_TYPE_VIS shared_mutex
178         __shared_mutex_base __base;
179 public:
180     shared_mutex() : __base() {}
181     _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
183     shared_mutex(const shared_mutex&) = delete;
184     shared_mutex& operator=(const shared_mutex&) = delete;
186     // Exclusive ownership
187     _LIBCPP_INLINE_VISIBILITY void lock()     { return __base.lock(); }
188     _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
189     _LIBCPP_INLINE_VISIBILITY void unlock()   { return __base.unlock(); }
191     // Shared ownership
192     _LIBCPP_INLINE_VISIBILITY void lock_shared()     { return __base.lock_shared(); }
193     _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
194     _LIBCPP_INLINE_VISIBILITY void unlock_shared()   { return __base.unlock_shared(); }
196 //     typedef __shared_mutex_base::native_handle_type native_handle_type;
197 //     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }
199 #endif
202 class _LIBCPP_TYPE_VIS shared_timed_mutex
204         __shared_mutex_base __base;
205 public:
206     shared_timed_mutex();
207     _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
209     shared_timed_mutex(const shared_timed_mutex&) = delete;
210     shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
212     // Exclusive ownership
213     void lock();
214     bool try_lock();
215     template <class _Rep, class _Period>
216         _LIBCPP_INLINE_VISIBILITY
217         bool
218         try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
219         {
220             return try_lock_until(chrono::steady_clock::now() + __rel_time);
221         }
222     template <class _Clock, class _Duration>
223         bool
224         try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
225     void unlock();
227     // Shared ownership
228     void lock_shared();
229     bool try_lock_shared();
230     template <class _Rep, class _Period>
231         _LIBCPP_INLINE_VISIBILITY
232         bool
233         try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
234         {
235             return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
236         }
237     template <class _Clock, class _Duration>
238         bool
239         try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
240     void unlock_shared();
243 template <class _Clock, class _Duration>
244 bool
245 shared_timed_mutex::try_lock_until(
246                         const chrono::time_point<_Clock, _Duration>& __abs_time)
248     unique_lock<mutex> __lk(__base.__mut_);
249     if (__base.__state_ & __base.__write_entered_)
250     {
251         while (true)
252         {
253             cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);
254             if ((__base.__state_ & __base.__write_entered_) == 0)
255                 break;
256             if (__status == cv_status::timeout)
257                 return false;
258         }
259     }
260     __base.__state_ |= __base.__write_entered_;
261     if (__base.__state_ & __base.__n_readers_)
262     {
263         while (true)
264         {
265             cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);
266             if ((__base.__state_ & __base.__n_readers_) == 0)
267                 break;
268             if (__status == cv_status::timeout)
269             {
270                 __base.__state_ &= ~__base.__write_entered_;
271                 __base.__gate1_.notify_all();
272                 return false;
273             }
274         }
275     }
276     return true;
279 template <class _Clock, class _Duration>
280 bool
281 shared_timed_mutex::try_lock_shared_until(
282                         const chrono::time_point<_Clock, _Duration>& __abs_time)
284     unique_lock<mutex> __lk(__base.__mut_);
285     if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)
286     {
287         while (true)
288         {
289             cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);
290             if ((__base.__state_ & __base.__write_entered_) == 0 &&
291                                        (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)
292                 break;
293             if (status == cv_status::timeout)
294                 return false;
295         }
296     }
297     unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;
298     __base.__state_ &= ~__base.__n_readers_;
299     __base.__state_ |= __num_readers;
300     return true;
303 template <class _Mutex>
304 class shared_lock
306 public:
307     typedef _Mutex mutex_type;
309 private:
310     mutex_type* __m_;
311     bool __owns_;
313 public:
314     _LIBCPP_INLINE_VISIBILITY
315     shared_lock() _NOEXCEPT
316         : __m_(nullptr),
317           __owns_(false)
318         {}
320     _LIBCPP_INLINE_VISIBILITY
321     explicit shared_lock(mutex_type& __m)
322         : __m_(&__m),
323           __owns_(true)
324         {__m_->lock_shared();}
326     _LIBCPP_INLINE_VISIBILITY
327     shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
328         : __m_(&__m),
329           __owns_(false)
330         {}
332     _LIBCPP_INLINE_VISIBILITY
333     shared_lock(mutex_type& __m, try_to_lock_t)
334         : __m_(&__m),
335           __owns_(__m.try_lock_shared())
336         {}
338     _LIBCPP_INLINE_VISIBILITY
339     shared_lock(mutex_type& __m, adopt_lock_t)
340         : __m_(&__m),
341           __owns_(true)
342         {}
344     template <class _Clock, class _Duration>
345         _LIBCPP_INLINE_VISIBILITY
346         shared_lock(mutex_type& __m,
347                     const chrono::time_point<_Clock, _Duration>& __abs_time)
348             : __m_(&__m),
349               __owns_(__m.try_lock_shared_until(__abs_time))
350             {}
352     template <class _Rep, class _Period>
353         _LIBCPP_INLINE_VISIBILITY
354         shared_lock(mutex_type& __m,
355                     const chrono::duration<_Rep, _Period>& __rel_time)
356             : __m_(&__m),
357               __owns_(__m.try_lock_shared_for(__rel_time))
358             {}
360     _LIBCPP_INLINE_VISIBILITY
361     ~shared_lock()
362     {
363         if (__owns_)
364             __m_->unlock_shared();
365     }
367     shared_lock(shared_lock const&) = delete;
368     shared_lock& operator=(shared_lock const&) = delete;
370     _LIBCPP_INLINE_VISIBILITY
371     shared_lock(shared_lock&& __u) _NOEXCEPT
372         : __m_(__u.__m_),
373           __owns_(__u.__owns_)
374         {
375             __u.__m_ = nullptr;
376             __u.__owns_ = false;
377         }
379     _LIBCPP_INLINE_VISIBILITY
380     shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
381     {
382         if (__owns_)
383             __m_->unlock_shared();
384         __m_ = nullptr;
385         __owns_ = false;
386         __m_ = __u.__m_;
387         __owns_ = __u.__owns_;
388         __u.__m_ = nullptr;
389         __u.__owns_ = false;
390         return *this;
391     }
393     void lock();
394     bool try_lock();
395     template <class Rep, class Period>
396         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
397     template <class Clock, class Duration>
398         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
399     void unlock();
401     // Setters
402     _LIBCPP_INLINE_VISIBILITY
403     void swap(shared_lock& __u) _NOEXCEPT
404     {
405         _VSTD::swap(__m_, __u.__m_);
406         _VSTD::swap(__owns_, __u.__owns_);
407     }
409     _LIBCPP_INLINE_VISIBILITY
410     mutex_type* release() _NOEXCEPT
411     {
412         mutex_type* __m = __m_;
413         __m_ = nullptr;
414         __owns_ = false;
415         return __m;
416     }
418     // Getters
419     _LIBCPP_INLINE_VISIBILITY
420     bool owns_lock() const _NOEXCEPT {return __owns_;}
422     _LIBCPP_INLINE_VISIBILITY
423     explicit operator bool () const _NOEXCEPT {return __owns_;}
425     _LIBCPP_INLINE_VISIBILITY
426     mutex_type* mutex() const _NOEXCEPT {return __m_;}
429 template <class _Mutex>
430 void
431 shared_lock<_Mutex>::lock()
433     if (__m_ == nullptr)
434         __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
435     if (__owns_)
436         __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
437     __m_->lock_shared();
438     __owns_ = true;
441 template <class _Mutex>
442 bool
443 shared_lock<_Mutex>::try_lock()
445     if (__m_ == nullptr)
446         __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
447     if (__owns_)
448         __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
449     __owns_ = __m_->try_lock_shared();
450     return __owns_;
453 template <class _Mutex>
454 template <class _Rep, class _Period>
455 bool
456 shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
458     if (__m_ == nullptr)
459         __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
460     if (__owns_)
461         __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
462     __owns_ = __m_->try_lock_shared_for(__d);
463     return __owns_;
466 template <class _Mutex>
467 template <class _Clock, class _Duration>
468 bool
469 shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
471     if (__m_ == nullptr)
472         __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
473     if (__owns_)
474         __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
475     __owns_ = __m_->try_lock_shared_until(__t);
476     return __owns_;
479 template <class _Mutex>
480 void
481 shared_lock<_Mutex>::unlock()
483     if (!__owns_)
484         __throw_system_error(EPERM, "shared_lock::unlock: not locked");
485     __m_->unlock_shared();
486     __owns_ = false;
489 template <class _Mutex>
490 inline _LIBCPP_INLINE_VISIBILITY
491 void
492 swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
493     {__x.swap(__y);}
495 _LIBCPP_END_NAMESPACE_STD
497 #endif  // !_LIBCPP_HAS_NO_THREADS
499 #endif  // _LIBCPP_STD_VER > 11
501 #endif  // _LIBCPP_SHARED_MUTEX