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