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