xref: /netbsd-src/external/apache2/llvm/dist/libcxx/include/shared_mutex (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1*4d6fc14bSjoerg// -*- C++ -*-
2*4d6fc14bSjoerg//===------------------------ shared_mutex --------------------------------===//
3*4d6fc14bSjoerg//
4*4d6fc14bSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*4d6fc14bSjoerg// See https://llvm.org/LICENSE.txt for license information.
6*4d6fc14bSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*4d6fc14bSjoerg//
8*4d6fc14bSjoerg//===----------------------------------------------------------------------===//
9*4d6fc14bSjoerg
10*4d6fc14bSjoerg#ifndef _LIBCPP_SHARED_MUTEX
11*4d6fc14bSjoerg#define _LIBCPP_SHARED_MUTEX
12*4d6fc14bSjoerg
13*4d6fc14bSjoerg/*
14*4d6fc14bSjoerg    shared_mutex synopsis
15*4d6fc14bSjoerg
16*4d6fc14bSjoerg// C++1y
17*4d6fc14bSjoerg
18*4d6fc14bSjoergnamespace std
19*4d6fc14bSjoerg{
20*4d6fc14bSjoerg
21*4d6fc14bSjoergclass shared_mutex      // C++17
22*4d6fc14bSjoerg{
23*4d6fc14bSjoergpublic:
24*4d6fc14bSjoerg    shared_mutex();
25*4d6fc14bSjoerg    ~shared_mutex();
26*4d6fc14bSjoerg
27*4d6fc14bSjoerg    shared_mutex(const shared_mutex&) = delete;
28*4d6fc14bSjoerg    shared_mutex& operator=(const shared_mutex&) = delete;
29*4d6fc14bSjoerg
30*4d6fc14bSjoerg    // Exclusive ownership
31*4d6fc14bSjoerg    void lock(); // blocking
32*4d6fc14bSjoerg    bool try_lock();
33*4d6fc14bSjoerg    void unlock();
34*4d6fc14bSjoerg
35*4d6fc14bSjoerg    // Shared ownership
36*4d6fc14bSjoerg    void lock_shared(); // blocking
37*4d6fc14bSjoerg    bool try_lock_shared();
38*4d6fc14bSjoerg    void unlock_shared();
39*4d6fc14bSjoerg
40*4d6fc14bSjoerg    typedef implementation-defined native_handle_type; // See 30.2.3
41*4d6fc14bSjoerg    native_handle_type native_handle(); // See 30.2.3
42*4d6fc14bSjoerg};
43*4d6fc14bSjoerg
44*4d6fc14bSjoergclass shared_timed_mutex
45*4d6fc14bSjoerg{
46*4d6fc14bSjoergpublic:
47*4d6fc14bSjoerg    shared_timed_mutex();
48*4d6fc14bSjoerg    ~shared_timed_mutex();
49*4d6fc14bSjoerg
50*4d6fc14bSjoerg    shared_timed_mutex(const shared_timed_mutex&) = delete;
51*4d6fc14bSjoerg    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
52*4d6fc14bSjoerg
53*4d6fc14bSjoerg    // Exclusive ownership
54*4d6fc14bSjoerg    void lock(); // blocking
55*4d6fc14bSjoerg    bool try_lock();
56*4d6fc14bSjoerg    template <class Rep, class Period>
57*4d6fc14bSjoerg        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
58*4d6fc14bSjoerg    template <class Clock, class Duration>
59*4d6fc14bSjoerg        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
60*4d6fc14bSjoerg    void unlock();
61*4d6fc14bSjoerg
62*4d6fc14bSjoerg    // Shared ownership
63*4d6fc14bSjoerg    void lock_shared(); // blocking
64*4d6fc14bSjoerg    bool try_lock_shared();
65*4d6fc14bSjoerg    template <class Rep, class Period>
66*4d6fc14bSjoerg        bool
67*4d6fc14bSjoerg        try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
68*4d6fc14bSjoerg    template <class Clock, class Duration>
69*4d6fc14bSjoerg        bool
70*4d6fc14bSjoerg        try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
71*4d6fc14bSjoerg    void unlock_shared();
72*4d6fc14bSjoerg};
73*4d6fc14bSjoerg
74*4d6fc14bSjoergtemplate <class Mutex>
75*4d6fc14bSjoergclass shared_lock
76*4d6fc14bSjoerg{
77*4d6fc14bSjoergpublic:
78*4d6fc14bSjoerg    typedef Mutex mutex_type;
79*4d6fc14bSjoerg
80*4d6fc14bSjoerg    // Shared locking
81*4d6fc14bSjoerg    shared_lock() noexcept;
82*4d6fc14bSjoerg    explicit shared_lock(mutex_type& m); // blocking
83*4d6fc14bSjoerg    shared_lock(mutex_type& m, defer_lock_t) noexcept;
84*4d6fc14bSjoerg    shared_lock(mutex_type& m, try_to_lock_t);
85*4d6fc14bSjoerg    shared_lock(mutex_type& m, adopt_lock_t);
86*4d6fc14bSjoerg    template <class Clock, class Duration>
87*4d6fc14bSjoerg        shared_lock(mutex_type& m,
88*4d6fc14bSjoerg                    const chrono::time_point<Clock, Duration>& abs_time);
89*4d6fc14bSjoerg    template <class Rep, class Period>
90*4d6fc14bSjoerg        shared_lock(mutex_type& m,
91*4d6fc14bSjoerg                    const chrono::duration<Rep, Period>& rel_time);
92*4d6fc14bSjoerg    ~shared_lock();
93*4d6fc14bSjoerg
94*4d6fc14bSjoerg    shared_lock(shared_lock const&) = delete;
95*4d6fc14bSjoerg    shared_lock& operator=(shared_lock const&) = delete;
96*4d6fc14bSjoerg
97*4d6fc14bSjoerg    shared_lock(shared_lock&& u) noexcept;
98*4d6fc14bSjoerg    shared_lock& operator=(shared_lock&& u) noexcept;
99*4d6fc14bSjoerg
100*4d6fc14bSjoerg    void lock(); // blocking
101*4d6fc14bSjoerg    bool try_lock();
102*4d6fc14bSjoerg    template <class Rep, class Period>
103*4d6fc14bSjoerg        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
104*4d6fc14bSjoerg    template <class Clock, class Duration>
105*4d6fc14bSjoerg        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
106*4d6fc14bSjoerg    void unlock();
107*4d6fc14bSjoerg
108*4d6fc14bSjoerg    // Setters
109*4d6fc14bSjoerg    void swap(shared_lock& u) noexcept;
110*4d6fc14bSjoerg    mutex_type* release() noexcept;
111*4d6fc14bSjoerg
112*4d6fc14bSjoerg    // Getters
113*4d6fc14bSjoerg    bool owns_lock() const noexcept;
114*4d6fc14bSjoerg    explicit operator bool () const noexcept;
115*4d6fc14bSjoerg    mutex_type* mutex() const noexcept;
116*4d6fc14bSjoerg};
117*4d6fc14bSjoerg
118*4d6fc14bSjoergtemplate <class Mutex>
119*4d6fc14bSjoerg    void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
120*4d6fc14bSjoerg
121*4d6fc14bSjoerg}  // std
122*4d6fc14bSjoerg
123*4d6fc14bSjoerg*/
124*4d6fc14bSjoerg
125*4d6fc14bSjoerg#include <__config>
126*4d6fc14bSjoerg#include <__availability>
127*4d6fc14bSjoerg#include <version>
128*4d6fc14bSjoerg
129*4d6fc14bSjoerg_LIBCPP_PUSH_MACROS
130*4d6fc14bSjoerg#include <__undef_macros>
131*4d6fc14bSjoerg
132*4d6fc14bSjoerg
133*4d6fc14bSjoerg#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_LIBRARY)
134*4d6fc14bSjoerg
135*4d6fc14bSjoerg#include <__mutex_base>
136*4d6fc14bSjoerg
137*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
138*4d6fc14bSjoerg#pragma GCC system_header
139*4d6fc14bSjoerg#endif
140*4d6fc14bSjoerg
141*4d6fc14bSjoerg#ifdef _LIBCPP_HAS_NO_THREADS
142*4d6fc14bSjoerg#error <shared_mutex> is not supported on this single threaded system
143*4d6fc14bSjoerg#else // !_LIBCPP_HAS_NO_THREADS
144*4d6fc14bSjoerg
145*4d6fc14bSjoerg_LIBCPP_BEGIN_NAMESPACE_STD
146*4d6fc14bSjoerg
147*4d6fc14bSjoergstruct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("shared_mutex"))
148*4d6fc14bSjoerg__shared_mutex_base
149*4d6fc14bSjoerg{
150*4d6fc14bSjoerg    mutex               __mut_;
151*4d6fc14bSjoerg    condition_variable  __gate1_;
152*4d6fc14bSjoerg    condition_variable  __gate2_;
153*4d6fc14bSjoerg    unsigned            __state_;
154*4d6fc14bSjoerg
155*4d6fc14bSjoerg    static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
156*4d6fc14bSjoerg    static const unsigned __n_readers_ = ~__write_entered_;
157*4d6fc14bSjoerg
158*4d6fc14bSjoerg    __shared_mutex_base();
159*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default;
160*4d6fc14bSjoerg
161*4d6fc14bSjoerg    __shared_mutex_base(const __shared_mutex_base&) = delete;
162*4d6fc14bSjoerg    __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
163*4d6fc14bSjoerg
164*4d6fc14bSjoerg    // Exclusive ownership
165*4d6fc14bSjoerg    void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); // blocking
166*4d6fc14bSjoerg    bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
167*4d6fc14bSjoerg    void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
168*4d6fc14bSjoerg
169*4d6fc14bSjoerg    // Shared ownership
170*4d6fc14bSjoerg    void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_shared_capability()); // blocking
171*4d6fc14bSjoerg    bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_shared_capability(true));
172*4d6fc14bSjoerg    void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_shared_capability());
173*4d6fc14bSjoerg
174*4d6fc14bSjoerg//     typedef implementation-defined native_handle_type; // See 30.2.3
175*4d6fc14bSjoerg//     native_handle_type native_handle(); // See 30.2.3
176*4d6fc14bSjoerg};
177*4d6fc14bSjoerg
178*4d6fc14bSjoerg
179*4d6fc14bSjoerg#if _LIBCPP_STD_VER > 14
180*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex
181*4d6fc14bSjoerg{
182*4d6fc14bSjoerg    __shared_mutex_base __base;
183*4d6fc14bSjoergpublic:
184*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY shared_mutex() : __base() {}
185*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
186*4d6fc14bSjoerg
187*4d6fc14bSjoerg    shared_mutex(const shared_mutex&) = delete;
188*4d6fc14bSjoerg    shared_mutex& operator=(const shared_mutex&) = delete;
189*4d6fc14bSjoerg
190*4d6fc14bSjoerg    // Exclusive ownership
191*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY void lock()     { return __base.lock(); }
192*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
193*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY void unlock()   { return __base.unlock(); }
194*4d6fc14bSjoerg
195*4d6fc14bSjoerg    // Shared ownership
196*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY void lock_shared()     { return __base.lock_shared(); }
197*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
198*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY void unlock_shared()   { return __base.unlock_shared(); }
199*4d6fc14bSjoerg
200*4d6fc14bSjoerg//     typedef __shared_mutex_base::native_handle_type native_handle_type;
201*4d6fc14bSjoerg//     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }
202*4d6fc14bSjoerg};
203*4d6fc14bSjoerg#endif
204*4d6fc14bSjoerg
205*4d6fc14bSjoerg
206*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex
207*4d6fc14bSjoerg{
208*4d6fc14bSjoerg    __shared_mutex_base __base;
209*4d6fc14bSjoergpublic:
210*4d6fc14bSjoerg    shared_timed_mutex();
211*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
212*4d6fc14bSjoerg
213*4d6fc14bSjoerg    shared_timed_mutex(const shared_timed_mutex&) = delete;
214*4d6fc14bSjoerg    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
215*4d6fc14bSjoerg
216*4d6fc14bSjoerg    // Exclusive ownership
217*4d6fc14bSjoerg    void lock();
218*4d6fc14bSjoerg    bool try_lock();
219*4d6fc14bSjoerg    template <class _Rep, class _Period>
220*4d6fc14bSjoerg        _LIBCPP_INLINE_VISIBILITY
221*4d6fc14bSjoerg        bool
222*4d6fc14bSjoerg        try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
223*4d6fc14bSjoerg        {
224*4d6fc14bSjoerg            return try_lock_until(chrono::steady_clock::now() + __rel_time);
225*4d6fc14bSjoerg        }
226*4d6fc14bSjoerg    template <class _Clock, class _Duration>
227*4d6fc14bSjoerg        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
228*4d6fc14bSjoerg        bool
229*4d6fc14bSjoerg        try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
230*4d6fc14bSjoerg    void unlock();
231*4d6fc14bSjoerg
232*4d6fc14bSjoerg    // Shared ownership
233*4d6fc14bSjoerg    void lock_shared();
234*4d6fc14bSjoerg    bool try_lock_shared();
235*4d6fc14bSjoerg    template <class _Rep, class _Period>
236*4d6fc14bSjoerg        _LIBCPP_INLINE_VISIBILITY
237*4d6fc14bSjoerg        bool
238*4d6fc14bSjoerg        try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
239*4d6fc14bSjoerg        {
240*4d6fc14bSjoerg            return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
241*4d6fc14bSjoerg        }
242*4d6fc14bSjoerg    template <class _Clock, class _Duration>
243*4d6fc14bSjoerg        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
244*4d6fc14bSjoerg        bool
245*4d6fc14bSjoerg        try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
246*4d6fc14bSjoerg    void unlock_shared();
247*4d6fc14bSjoerg};
248*4d6fc14bSjoerg
249*4d6fc14bSjoergtemplate <class _Clock, class _Duration>
250*4d6fc14bSjoergbool
251*4d6fc14bSjoergshared_timed_mutex::try_lock_until(
252*4d6fc14bSjoerg                        const chrono::time_point<_Clock, _Duration>& __abs_time)
253*4d6fc14bSjoerg{
254*4d6fc14bSjoerg    unique_lock<mutex> __lk(__base.__mut_);
255*4d6fc14bSjoerg    if (__base.__state_ & __base.__write_entered_)
256*4d6fc14bSjoerg    {
257*4d6fc14bSjoerg        while (true)
258*4d6fc14bSjoerg        {
259*4d6fc14bSjoerg            cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);
260*4d6fc14bSjoerg            if ((__base.__state_ & __base.__write_entered_) == 0)
261*4d6fc14bSjoerg                break;
262*4d6fc14bSjoerg            if (__status == cv_status::timeout)
263*4d6fc14bSjoerg                return false;
264*4d6fc14bSjoerg        }
265*4d6fc14bSjoerg    }
266*4d6fc14bSjoerg    __base.__state_ |= __base.__write_entered_;
267*4d6fc14bSjoerg    if (__base.__state_ & __base.__n_readers_)
268*4d6fc14bSjoerg    {
269*4d6fc14bSjoerg        while (true)
270*4d6fc14bSjoerg        {
271*4d6fc14bSjoerg            cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);
272*4d6fc14bSjoerg            if ((__base.__state_ & __base.__n_readers_) == 0)
273*4d6fc14bSjoerg                break;
274*4d6fc14bSjoerg            if (__status == cv_status::timeout)
275*4d6fc14bSjoerg            {
276*4d6fc14bSjoerg                __base.__state_ &= ~__base.__write_entered_;
277*4d6fc14bSjoerg                __base.__gate1_.notify_all();
278*4d6fc14bSjoerg                return false;
279*4d6fc14bSjoerg            }
280*4d6fc14bSjoerg        }
281*4d6fc14bSjoerg    }
282*4d6fc14bSjoerg    return true;
283*4d6fc14bSjoerg}
284*4d6fc14bSjoerg
285*4d6fc14bSjoergtemplate <class _Clock, class _Duration>
286*4d6fc14bSjoergbool
287*4d6fc14bSjoergshared_timed_mutex::try_lock_shared_until(
288*4d6fc14bSjoerg                        const chrono::time_point<_Clock, _Duration>& __abs_time)
289*4d6fc14bSjoerg{
290*4d6fc14bSjoerg    unique_lock<mutex> __lk(__base.__mut_);
291*4d6fc14bSjoerg    if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)
292*4d6fc14bSjoerg    {
293*4d6fc14bSjoerg        while (true)
294*4d6fc14bSjoerg        {
295*4d6fc14bSjoerg            cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);
296*4d6fc14bSjoerg            if ((__base.__state_ & __base.__write_entered_) == 0 &&
297*4d6fc14bSjoerg                                       (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)
298*4d6fc14bSjoerg                break;
299*4d6fc14bSjoerg            if (status == cv_status::timeout)
300*4d6fc14bSjoerg                return false;
301*4d6fc14bSjoerg        }
302*4d6fc14bSjoerg    }
303*4d6fc14bSjoerg    unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;
304*4d6fc14bSjoerg    __base.__state_ &= ~__base.__n_readers_;
305*4d6fc14bSjoerg    __base.__state_ |= __num_readers;
306*4d6fc14bSjoerg    return true;
307*4d6fc14bSjoerg}
308*4d6fc14bSjoerg
309*4d6fc14bSjoergtemplate <class _Mutex>
310*4d6fc14bSjoergclass shared_lock
311*4d6fc14bSjoerg{
312*4d6fc14bSjoergpublic:
313*4d6fc14bSjoerg    typedef _Mutex mutex_type;
314*4d6fc14bSjoerg
315*4d6fc14bSjoergprivate:
316*4d6fc14bSjoerg    mutex_type* __m_;
317*4d6fc14bSjoerg    bool __owns_;
318*4d6fc14bSjoerg
319*4d6fc14bSjoergpublic:
320*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
321*4d6fc14bSjoerg    shared_lock() _NOEXCEPT
322*4d6fc14bSjoerg        : __m_(nullptr),
323*4d6fc14bSjoerg          __owns_(false)
324*4d6fc14bSjoerg        {}
325*4d6fc14bSjoerg
326*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
327*4d6fc14bSjoerg    explicit shared_lock(mutex_type& __m)
328*4d6fc14bSjoerg        : __m_(_VSTD::addressof(__m)),
329*4d6fc14bSjoerg          __owns_(true)
330*4d6fc14bSjoerg        {__m_->lock_shared();}
331*4d6fc14bSjoerg
332*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
333*4d6fc14bSjoerg    shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
334*4d6fc14bSjoerg        : __m_(_VSTD::addressof(__m)),
335*4d6fc14bSjoerg          __owns_(false)
336*4d6fc14bSjoerg        {}
337*4d6fc14bSjoerg
338*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
339*4d6fc14bSjoerg    shared_lock(mutex_type& __m, try_to_lock_t)
340*4d6fc14bSjoerg        : __m_(_VSTD::addressof(__m)),
341*4d6fc14bSjoerg          __owns_(__m.try_lock_shared())
342*4d6fc14bSjoerg        {}
343*4d6fc14bSjoerg
344*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
345*4d6fc14bSjoerg    shared_lock(mutex_type& __m, adopt_lock_t)
346*4d6fc14bSjoerg        : __m_(_VSTD::addressof(__m)),
347*4d6fc14bSjoerg          __owns_(true)
348*4d6fc14bSjoerg        {}
349*4d6fc14bSjoerg
350*4d6fc14bSjoerg    template <class _Clock, class _Duration>
351*4d6fc14bSjoerg        _LIBCPP_INLINE_VISIBILITY
352*4d6fc14bSjoerg        shared_lock(mutex_type& __m,
353*4d6fc14bSjoerg                    const chrono::time_point<_Clock, _Duration>& __abs_time)
354*4d6fc14bSjoerg            : __m_(_VSTD::addressof(__m)),
355*4d6fc14bSjoerg              __owns_(__m.try_lock_shared_until(__abs_time))
356*4d6fc14bSjoerg            {}
357*4d6fc14bSjoerg
358*4d6fc14bSjoerg    template <class _Rep, class _Period>
359*4d6fc14bSjoerg        _LIBCPP_INLINE_VISIBILITY
360*4d6fc14bSjoerg        shared_lock(mutex_type& __m,
361*4d6fc14bSjoerg                    const chrono::duration<_Rep, _Period>& __rel_time)
362*4d6fc14bSjoerg            : __m_(_VSTD::addressof(__m)),
363*4d6fc14bSjoerg              __owns_(__m.try_lock_shared_for(__rel_time))
364*4d6fc14bSjoerg            {}
365*4d6fc14bSjoerg
366*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
367*4d6fc14bSjoerg    ~shared_lock()
368*4d6fc14bSjoerg    {
369*4d6fc14bSjoerg        if (__owns_)
370*4d6fc14bSjoerg            __m_->unlock_shared();
371*4d6fc14bSjoerg    }
372*4d6fc14bSjoerg
373*4d6fc14bSjoerg    shared_lock(shared_lock const&) = delete;
374*4d6fc14bSjoerg    shared_lock& operator=(shared_lock const&) = delete;
375*4d6fc14bSjoerg
376*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
377*4d6fc14bSjoerg    shared_lock(shared_lock&& __u) _NOEXCEPT
378*4d6fc14bSjoerg        : __m_(__u.__m_),
379*4d6fc14bSjoerg          __owns_(__u.__owns_)
380*4d6fc14bSjoerg        {
381*4d6fc14bSjoerg            __u.__m_ = nullptr;
382*4d6fc14bSjoerg            __u.__owns_ = false;
383*4d6fc14bSjoerg        }
384*4d6fc14bSjoerg
385*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
386*4d6fc14bSjoerg    shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
387*4d6fc14bSjoerg    {
388*4d6fc14bSjoerg        if (__owns_)
389*4d6fc14bSjoerg            __m_->unlock_shared();
390*4d6fc14bSjoerg        __m_ = nullptr;
391*4d6fc14bSjoerg        __owns_ = false;
392*4d6fc14bSjoerg        __m_ = __u.__m_;
393*4d6fc14bSjoerg        __owns_ = __u.__owns_;
394*4d6fc14bSjoerg        __u.__m_ = nullptr;
395*4d6fc14bSjoerg        __u.__owns_ = false;
396*4d6fc14bSjoerg        return *this;
397*4d6fc14bSjoerg    }
398*4d6fc14bSjoerg
399*4d6fc14bSjoerg    void lock();
400*4d6fc14bSjoerg    bool try_lock();
401*4d6fc14bSjoerg    template <class Rep, class Period>
402*4d6fc14bSjoerg        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
403*4d6fc14bSjoerg    template <class Clock, class Duration>
404*4d6fc14bSjoerg        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
405*4d6fc14bSjoerg    void unlock();
406*4d6fc14bSjoerg
407*4d6fc14bSjoerg    // Setters
408*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
409*4d6fc14bSjoerg    void swap(shared_lock& __u) _NOEXCEPT
410*4d6fc14bSjoerg    {
411*4d6fc14bSjoerg        _VSTD::swap(__m_, __u.__m_);
412*4d6fc14bSjoerg        _VSTD::swap(__owns_, __u.__owns_);
413*4d6fc14bSjoerg    }
414*4d6fc14bSjoerg
415*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
416*4d6fc14bSjoerg    mutex_type* release() _NOEXCEPT
417*4d6fc14bSjoerg    {
418*4d6fc14bSjoerg        mutex_type* __m = __m_;
419*4d6fc14bSjoerg        __m_ = nullptr;
420*4d6fc14bSjoerg        __owns_ = false;
421*4d6fc14bSjoerg        return __m;
422*4d6fc14bSjoerg    }
423*4d6fc14bSjoerg
424*4d6fc14bSjoerg    // Getters
425*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
426*4d6fc14bSjoerg    bool owns_lock() const _NOEXCEPT {return __owns_;}
427*4d6fc14bSjoerg
428*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
429*4d6fc14bSjoerg    explicit operator bool () const _NOEXCEPT {return __owns_;}
430*4d6fc14bSjoerg
431*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
432*4d6fc14bSjoerg    mutex_type* mutex() const _NOEXCEPT {return __m_;}
433*4d6fc14bSjoerg};
434*4d6fc14bSjoerg
435*4d6fc14bSjoergtemplate <class _Mutex>
436*4d6fc14bSjoergvoid
437*4d6fc14bSjoergshared_lock<_Mutex>::lock()
438*4d6fc14bSjoerg{
439*4d6fc14bSjoerg    if (__m_ == nullptr)
440*4d6fc14bSjoerg        __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
441*4d6fc14bSjoerg    if (__owns_)
442*4d6fc14bSjoerg        __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
443*4d6fc14bSjoerg    __m_->lock_shared();
444*4d6fc14bSjoerg    __owns_ = true;
445*4d6fc14bSjoerg}
446*4d6fc14bSjoerg
447*4d6fc14bSjoergtemplate <class _Mutex>
448*4d6fc14bSjoergbool
449*4d6fc14bSjoergshared_lock<_Mutex>::try_lock()
450*4d6fc14bSjoerg{
451*4d6fc14bSjoerg    if (__m_ == nullptr)
452*4d6fc14bSjoerg        __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
453*4d6fc14bSjoerg    if (__owns_)
454*4d6fc14bSjoerg        __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
455*4d6fc14bSjoerg    __owns_ = __m_->try_lock_shared();
456*4d6fc14bSjoerg    return __owns_;
457*4d6fc14bSjoerg}
458*4d6fc14bSjoerg
459*4d6fc14bSjoergtemplate <class _Mutex>
460*4d6fc14bSjoergtemplate <class _Rep, class _Period>
461*4d6fc14bSjoergbool
462*4d6fc14bSjoergshared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
463*4d6fc14bSjoerg{
464*4d6fc14bSjoerg    if (__m_ == nullptr)
465*4d6fc14bSjoerg        __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
466*4d6fc14bSjoerg    if (__owns_)
467*4d6fc14bSjoerg        __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
468*4d6fc14bSjoerg    __owns_ = __m_->try_lock_shared_for(__d);
469*4d6fc14bSjoerg    return __owns_;
470*4d6fc14bSjoerg}
471*4d6fc14bSjoerg
472*4d6fc14bSjoergtemplate <class _Mutex>
473*4d6fc14bSjoergtemplate <class _Clock, class _Duration>
474*4d6fc14bSjoergbool
475*4d6fc14bSjoergshared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
476*4d6fc14bSjoerg{
477*4d6fc14bSjoerg    if (__m_ == nullptr)
478*4d6fc14bSjoerg        __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
479*4d6fc14bSjoerg    if (__owns_)
480*4d6fc14bSjoerg        __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
481*4d6fc14bSjoerg    __owns_ = __m_->try_lock_shared_until(__t);
482*4d6fc14bSjoerg    return __owns_;
483*4d6fc14bSjoerg}
484*4d6fc14bSjoerg
485*4d6fc14bSjoergtemplate <class _Mutex>
486*4d6fc14bSjoergvoid
487*4d6fc14bSjoergshared_lock<_Mutex>::unlock()
488*4d6fc14bSjoerg{
489*4d6fc14bSjoerg    if (!__owns_)
490*4d6fc14bSjoerg        __throw_system_error(EPERM, "shared_lock::unlock: not locked");
491*4d6fc14bSjoerg    __m_->unlock_shared();
492*4d6fc14bSjoerg    __owns_ = false;
493*4d6fc14bSjoerg}
494*4d6fc14bSjoerg
495*4d6fc14bSjoergtemplate <class _Mutex>
496*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY
497*4d6fc14bSjoergvoid
498*4d6fc14bSjoergswap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
499*4d6fc14bSjoerg    {__x.swap(__y);}
500*4d6fc14bSjoerg
501*4d6fc14bSjoerg_LIBCPP_END_NAMESPACE_STD
502*4d6fc14bSjoerg
503*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_NO_THREADS
504*4d6fc14bSjoerg
505*4d6fc14bSjoerg#endif // _LIBCPP_STD_VER > 11
506*4d6fc14bSjoerg
507*4d6fc14bSjoerg_LIBCPP_POP_MACROS
508*4d6fc14bSjoerg
509*4d6fc14bSjoerg#endif // _LIBCPP_SHARED_MUTEX
510