14f7ab58eSDimitry Andric// -*- C++ -*- 24f7ab58eSDimitry Andric//===------------------------ shared_mutex --------------------------------===// 34f7ab58eSDimitry Andric// 44f7ab58eSDimitry Andric// The LLVM Compiler Infrastructure 54f7ab58eSDimitry Andric// 64f7ab58eSDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open 74f7ab58eSDimitry Andric// Source Licenses. See LICENSE.TXT for details. 84f7ab58eSDimitry Andric// 94f7ab58eSDimitry Andric//===----------------------------------------------------------------------===// 104f7ab58eSDimitry Andric 114f7ab58eSDimitry Andric#ifndef _LIBCPP_SHARED_MUTEX 124f7ab58eSDimitry Andric#define _LIBCPP_SHARED_MUTEX 134f7ab58eSDimitry Andric 144f7ab58eSDimitry Andric/* 154f7ab58eSDimitry Andric shared_mutex synopsis 164f7ab58eSDimitry Andric 174f7ab58eSDimitry Andric// C++1y 184f7ab58eSDimitry Andric 194f7ab58eSDimitry Andricnamespace std 204f7ab58eSDimitry Andric{ 214f7ab58eSDimitry Andric 22854fa44bSDimitry Andricclass shared_mutex // C++17 23854fa44bSDimitry Andric{ 24854fa44bSDimitry Andricpublic: 25854fa44bSDimitry Andric shared_mutex(); 26854fa44bSDimitry Andric ~shared_mutex(); 27854fa44bSDimitry Andric 28854fa44bSDimitry Andric shared_mutex(const shared_mutex&) = delete; 29854fa44bSDimitry Andric shared_mutex& operator=(const shared_mutex&) = delete; 30854fa44bSDimitry Andric 31854fa44bSDimitry Andric // Exclusive ownership 32854fa44bSDimitry Andric void lock(); // blocking 33854fa44bSDimitry Andric bool try_lock(); 34854fa44bSDimitry Andric void unlock(); 35854fa44bSDimitry Andric 36854fa44bSDimitry Andric // Shared ownership 37854fa44bSDimitry Andric void lock_shared(); // blocking 38854fa44bSDimitry Andric bool try_lock_shared(); 39854fa44bSDimitry Andric void unlock_shared(); 40854fa44bSDimitry Andric 41854fa44bSDimitry Andric typedef implementation-defined native_handle_type; // See 30.2.3 42854fa44bSDimitry Andric native_handle_type native_handle(); // See 30.2.3 43854fa44bSDimitry Andric}; 44854fa44bSDimitry Andric 45d72607e9SDimitry Andricclass shared_timed_mutex 464f7ab58eSDimitry Andric{ 474f7ab58eSDimitry Andricpublic: 48d72607e9SDimitry Andric shared_timed_mutex(); 49d72607e9SDimitry Andric ~shared_timed_mutex(); 504f7ab58eSDimitry Andric 51d72607e9SDimitry Andric shared_timed_mutex(const shared_timed_mutex&) = delete; 52d72607e9SDimitry Andric shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; 534f7ab58eSDimitry Andric 544f7ab58eSDimitry Andric // Exclusive ownership 554f7ab58eSDimitry Andric void lock(); // blocking 564f7ab58eSDimitry Andric bool try_lock(); 574f7ab58eSDimitry Andric template <class Rep, class Period> 584f7ab58eSDimitry Andric bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 594f7ab58eSDimitry Andric template <class Clock, class Duration> 604f7ab58eSDimitry Andric bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 614f7ab58eSDimitry Andric void unlock(); 624f7ab58eSDimitry Andric 634f7ab58eSDimitry Andric // Shared ownership 644f7ab58eSDimitry Andric void lock_shared(); // blocking 654f7ab58eSDimitry Andric bool try_lock_shared(); 664f7ab58eSDimitry Andric template <class Rep, class Period> 674f7ab58eSDimitry Andric bool 684f7ab58eSDimitry Andric try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time); 694f7ab58eSDimitry Andric template <class Clock, class Duration> 704f7ab58eSDimitry Andric bool 714f7ab58eSDimitry Andric try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time); 724f7ab58eSDimitry Andric void unlock_shared(); 734f7ab58eSDimitry Andric}; 744f7ab58eSDimitry Andric 754f7ab58eSDimitry Andrictemplate <class Mutex> 764f7ab58eSDimitry Andricclass shared_lock 774f7ab58eSDimitry Andric{ 784f7ab58eSDimitry Andricpublic: 794f7ab58eSDimitry Andric typedef Mutex mutex_type; 804f7ab58eSDimitry Andric 814f7ab58eSDimitry Andric // Shared locking 824f7ab58eSDimitry Andric shared_lock() noexcept; 834f7ab58eSDimitry Andric explicit shared_lock(mutex_type& m); // blocking 844f7ab58eSDimitry Andric shared_lock(mutex_type& m, defer_lock_t) noexcept; 854f7ab58eSDimitry Andric shared_lock(mutex_type& m, try_to_lock_t); 864f7ab58eSDimitry Andric shared_lock(mutex_type& m, adopt_lock_t); 874f7ab58eSDimitry Andric template <class Clock, class Duration> 884f7ab58eSDimitry Andric shared_lock(mutex_type& m, 894f7ab58eSDimitry Andric const chrono::time_point<Clock, Duration>& abs_time); 904f7ab58eSDimitry Andric template <class Rep, class Period> 914f7ab58eSDimitry Andric shared_lock(mutex_type& m, 924f7ab58eSDimitry Andric const chrono::duration<Rep, Period>& rel_time); 934f7ab58eSDimitry Andric ~shared_lock(); 944f7ab58eSDimitry Andric 954f7ab58eSDimitry Andric shared_lock(shared_lock const&) = delete; 964f7ab58eSDimitry Andric shared_lock& operator=(shared_lock const&) = delete; 974f7ab58eSDimitry Andric 984f7ab58eSDimitry Andric shared_lock(shared_lock&& u) noexcept; 994f7ab58eSDimitry Andric shared_lock& operator=(shared_lock&& u) noexcept; 1004f7ab58eSDimitry Andric 1014f7ab58eSDimitry Andric void lock(); // blocking 1024f7ab58eSDimitry Andric bool try_lock(); 1034f7ab58eSDimitry Andric template <class Rep, class Period> 1044f7ab58eSDimitry Andric bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 1054f7ab58eSDimitry Andric template <class Clock, class Duration> 1064f7ab58eSDimitry Andric bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 1074f7ab58eSDimitry Andric void unlock(); 1084f7ab58eSDimitry Andric 1094f7ab58eSDimitry Andric // Setters 1104f7ab58eSDimitry Andric void swap(shared_lock& u) noexcept; 1114f7ab58eSDimitry Andric mutex_type* release() noexcept; 1124f7ab58eSDimitry Andric 1134f7ab58eSDimitry Andric // Getters 1144f7ab58eSDimitry Andric bool owns_lock() const noexcept; 1154f7ab58eSDimitry Andric explicit operator bool () const noexcept; 1164f7ab58eSDimitry Andric mutex_type* mutex() const noexcept; 1174f7ab58eSDimitry Andric}; 1184f7ab58eSDimitry Andric 1194f7ab58eSDimitry Andrictemplate <class Mutex> 1204f7ab58eSDimitry Andric void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept; 1214f7ab58eSDimitry Andric 1224f7ab58eSDimitry Andric} // std 1234f7ab58eSDimitry Andric 1244f7ab58eSDimitry Andric*/ 1254f7ab58eSDimitry Andric 1264f7ab58eSDimitry Andric#include <__config> 127*b5893f02SDimitry Andric#include <version> 1284f7ab58eSDimitry Andric 129f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS 130f9448bf3SDimitry Andric#include <__undef_macros> 131f9448bf3SDimitry Andric 132f9448bf3SDimitry Andric 1334ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_LIBRARY) 1344f7ab58eSDimitry Andric 1354f7ab58eSDimitry Andric#include <__mutex_base> 1364f7ab58eSDimitry Andric 1374f7ab58eSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1384f7ab58eSDimitry Andric#pragma GCC system_header 1394f7ab58eSDimitry Andric#endif 1404f7ab58eSDimitry Andric 141d72607e9SDimitry Andric#ifdef _LIBCPP_HAS_NO_THREADS 142d72607e9SDimitry Andric#error <shared_mutex> is not supported on this single threaded system 143d72607e9SDimitry Andric#else // !_LIBCPP_HAS_NO_THREADS 144d72607e9SDimitry Andric 1454f7ab58eSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 1464f7ab58eSDimitry Andric 147*b5893f02SDimitry Andricstruct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("shared_mutex")) 148*b5893f02SDimitry Andric__shared_mutex_base 1494f7ab58eSDimitry Andric{ 1504f7ab58eSDimitry Andric mutex __mut_; 1514f7ab58eSDimitry Andric condition_variable __gate1_; 1524f7ab58eSDimitry Andric condition_variable __gate2_; 1534f7ab58eSDimitry Andric unsigned __state_; 1544f7ab58eSDimitry Andric 1554f7ab58eSDimitry Andric static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1); 1564f7ab58eSDimitry Andric static const unsigned __n_readers_ = ~__write_entered_; 157854fa44bSDimitry Andric 158854fa44bSDimitry Andric __shared_mutex_base(); 159854fa44bSDimitry Andric _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default; 160854fa44bSDimitry Andric 161854fa44bSDimitry Andric __shared_mutex_base(const __shared_mutex_base&) = delete; 162854fa44bSDimitry Andric __shared_mutex_base& operator=(const __shared_mutex_base&) = delete; 163854fa44bSDimitry Andric 164854fa44bSDimitry Andric // Exclusive ownership 165*b5893f02SDimitry Andric void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); // blocking 166*b5893f02SDimitry Andric bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); 167*b5893f02SDimitry Andric void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); 168854fa44bSDimitry Andric 169854fa44bSDimitry Andric // Shared ownership 170*b5893f02SDimitry Andric void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_shared_capability()); // blocking 171*b5893f02SDimitry Andric bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_shared_capability(true)); 172*b5893f02SDimitry Andric void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_shared_capability()); 173854fa44bSDimitry Andric 174854fa44bSDimitry Andric// typedef implementation-defined native_handle_type; // See 30.2.3 175854fa44bSDimitry Andric// native_handle_type native_handle(); // See 30.2.3 176854fa44bSDimitry Andric}; 177854fa44bSDimitry Andric 178854fa44bSDimitry Andric 179854fa44bSDimitry Andric#if _LIBCPP_STD_VER > 14 1800f5676f4SDimitry Andricclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex 181854fa44bSDimitry Andric{ 182854fa44bSDimitry Andric __shared_mutex_base __base; 183854fa44bSDimitry Andricpublic: 1840f5676f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY shared_mutex() : __base() {} 185854fa44bSDimitry Andric _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default; 186854fa44bSDimitry Andric 187854fa44bSDimitry Andric shared_mutex(const shared_mutex&) = delete; 188854fa44bSDimitry Andric shared_mutex& operator=(const shared_mutex&) = delete; 189854fa44bSDimitry Andric 190854fa44bSDimitry Andric // Exclusive ownership 191854fa44bSDimitry Andric _LIBCPP_INLINE_VISIBILITY void lock() { return __base.lock(); } 192854fa44bSDimitry Andric _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); } 193854fa44bSDimitry Andric _LIBCPP_INLINE_VISIBILITY void unlock() { return __base.unlock(); } 194854fa44bSDimitry Andric 195854fa44bSDimitry Andric // Shared ownership 196854fa44bSDimitry Andric _LIBCPP_INLINE_VISIBILITY void lock_shared() { return __base.lock_shared(); } 197854fa44bSDimitry Andric _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); } 198854fa44bSDimitry Andric _LIBCPP_INLINE_VISIBILITY void unlock_shared() { return __base.unlock_shared(); } 199854fa44bSDimitry Andric 200854fa44bSDimitry Andric// typedef __shared_mutex_base::native_handle_type native_handle_type; 201854fa44bSDimitry Andric// _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); } 202854fa44bSDimitry Andric}; 203854fa44bSDimitry Andric#endif 204854fa44bSDimitry Andric 205854fa44bSDimitry Andric 2060f5676f4SDimitry Andricclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex 207854fa44bSDimitry Andric{ 208854fa44bSDimitry Andric __shared_mutex_base __base; 2094f7ab58eSDimitry Andricpublic: 210d72607e9SDimitry Andric shared_timed_mutex(); 211d72607e9SDimitry Andric _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default; 2124f7ab58eSDimitry Andric 213d72607e9SDimitry Andric shared_timed_mutex(const shared_timed_mutex&) = delete; 214d72607e9SDimitry Andric shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; 2154f7ab58eSDimitry Andric 2164f7ab58eSDimitry Andric // Exclusive ownership 2174f7ab58eSDimitry Andric void lock(); 2184f7ab58eSDimitry Andric bool try_lock(); 2194f7ab58eSDimitry Andric template <class _Rep, class _Period> 2204f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2214f7ab58eSDimitry Andric bool 2224f7ab58eSDimitry Andric try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) 2234f7ab58eSDimitry Andric { 2244f7ab58eSDimitry Andric return try_lock_until(chrono::steady_clock::now() + __rel_time); 2254f7ab58eSDimitry Andric } 2264f7ab58eSDimitry Andric template <class _Clock, class _Duration> 227540d2a8bSDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2284f7ab58eSDimitry Andric bool 2294f7ab58eSDimitry Andric try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time); 2304f7ab58eSDimitry Andric void unlock(); 2314f7ab58eSDimitry Andric 2324f7ab58eSDimitry Andric // Shared ownership 2334f7ab58eSDimitry Andric void lock_shared(); 2344f7ab58eSDimitry Andric bool try_lock_shared(); 2354f7ab58eSDimitry Andric template <class _Rep, class _Period> 2364f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2374f7ab58eSDimitry Andric bool 2384f7ab58eSDimitry Andric try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) 2394f7ab58eSDimitry Andric { 2404f7ab58eSDimitry Andric return try_lock_shared_until(chrono::steady_clock::now() + __rel_time); 2414f7ab58eSDimitry Andric } 2424f7ab58eSDimitry Andric template <class _Clock, class _Duration> 243540d2a8bSDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2444f7ab58eSDimitry Andric bool 2454f7ab58eSDimitry Andric try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time); 2464f7ab58eSDimitry Andric void unlock_shared(); 2474f7ab58eSDimitry Andric}; 2484f7ab58eSDimitry Andric 2494f7ab58eSDimitry Andrictemplate <class _Clock, class _Duration> 2504f7ab58eSDimitry Andricbool 251d72607e9SDimitry Andricshared_timed_mutex::try_lock_until( 2524f7ab58eSDimitry Andric const chrono::time_point<_Clock, _Duration>& __abs_time) 2534f7ab58eSDimitry Andric{ 254854fa44bSDimitry Andric unique_lock<mutex> __lk(__base.__mut_); 255854fa44bSDimitry Andric if (__base.__state_ & __base.__write_entered_) 2564f7ab58eSDimitry Andric { 2574f7ab58eSDimitry Andric while (true) 2584f7ab58eSDimitry Andric { 259854fa44bSDimitry Andric cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time); 260854fa44bSDimitry Andric if ((__base.__state_ & __base.__write_entered_) == 0) 2614f7ab58eSDimitry Andric break; 2624f7ab58eSDimitry Andric if (__status == cv_status::timeout) 2634f7ab58eSDimitry Andric return false; 2644f7ab58eSDimitry Andric } 2654f7ab58eSDimitry Andric } 266854fa44bSDimitry Andric __base.__state_ |= __base.__write_entered_; 267854fa44bSDimitry Andric if (__base.__state_ & __base.__n_readers_) 2684f7ab58eSDimitry Andric { 2694f7ab58eSDimitry Andric while (true) 2704f7ab58eSDimitry Andric { 271854fa44bSDimitry Andric cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time); 272854fa44bSDimitry Andric if ((__base.__state_ & __base.__n_readers_) == 0) 2734f7ab58eSDimitry Andric break; 2744f7ab58eSDimitry Andric if (__status == cv_status::timeout) 2754f7ab58eSDimitry Andric { 276854fa44bSDimitry Andric __base.__state_ &= ~__base.__write_entered_; 277854fa44bSDimitry Andric __base.__gate1_.notify_all(); 2784f7ab58eSDimitry Andric return false; 2794f7ab58eSDimitry Andric } 2804f7ab58eSDimitry Andric } 2814f7ab58eSDimitry Andric } 2824f7ab58eSDimitry Andric return true; 2834f7ab58eSDimitry Andric} 2844f7ab58eSDimitry Andric 2854f7ab58eSDimitry Andrictemplate <class _Clock, class _Duration> 2864f7ab58eSDimitry Andricbool 287d72607e9SDimitry Andricshared_timed_mutex::try_lock_shared_until( 2884f7ab58eSDimitry Andric const chrono::time_point<_Clock, _Duration>& __abs_time) 2894f7ab58eSDimitry Andric{ 290854fa44bSDimitry Andric unique_lock<mutex> __lk(__base.__mut_); 291854fa44bSDimitry Andric if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_) 2924f7ab58eSDimitry Andric { 2934f7ab58eSDimitry Andric while (true) 2944f7ab58eSDimitry Andric { 295854fa44bSDimitry Andric cv_status status = __base.__gate1_.wait_until(__lk, __abs_time); 296854fa44bSDimitry Andric if ((__base.__state_ & __base.__write_entered_) == 0 && 297854fa44bSDimitry Andric (__base.__state_ & __base.__n_readers_) < __base.__n_readers_) 2984f7ab58eSDimitry Andric break; 2994f7ab58eSDimitry Andric if (status == cv_status::timeout) 3004f7ab58eSDimitry Andric return false; 3014f7ab58eSDimitry Andric } 3024f7ab58eSDimitry Andric } 303854fa44bSDimitry Andric unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1; 304854fa44bSDimitry Andric __base.__state_ &= ~__base.__n_readers_; 305854fa44bSDimitry Andric __base.__state_ |= __num_readers; 3064f7ab58eSDimitry Andric return true; 3074f7ab58eSDimitry Andric} 3084f7ab58eSDimitry Andric 3094f7ab58eSDimitry Andrictemplate <class _Mutex> 3104f7ab58eSDimitry Andricclass shared_lock 3114f7ab58eSDimitry Andric{ 3124f7ab58eSDimitry Andricpublic: 3134f7ab58eSDimitry Andric typedef _Mutex mutex_type; 3144f7ab58eSDimitry Andric 3154f7ab58eSDimitry Andricprivate: 3164f7ab58eSDimitry Andric mutex_type* __m_; 3174f7ab58eSDimitry Andric bool __owns_; 3184f7ab58eSDimitry Andric 3194f7ab58eSDimitry Andricpublic: 3204f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 321d72607e9SDimitry Andric shared_lock() _NOEXCEPT 3224f7ab58eSDimitry Andric : __m_(nullptr), 3234f7ab58eSDimitry Andric __owns_(false) 3244f7ab58eSDimitry Andric {} 3254f7ab58eSDimitry Andric 3264f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3274f7ab58eSDimitry Andric explicit shared_lock(mutex_type& __m) 3287c82a1ecSDimitry Andric : __m_(_VSTD::addressof(__m)), 3294f7ab58eSDimitry Andric __owns_(true) 3304f7ab58eSDimitry Andric {__m_->lock_shared();} 3314f7ab58eSDimitry Andric 3324f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 333d72607e9SDimitry Andric shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 3347c82a1ecSDimitry Andric : __m_(_VSTD::addressof(__m)), 3354f7ab58eSDimitry Andric __owns_(false) 3364f7ab58eSDimitry Andric {} 3374f7ab58eSDimitry Andric 3384f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3394f7ab58eSDimitry Andric shared_lock(mutex_type& __m, try_to_lock_t) 3407c82a1ecSDimitry Andric : __m_(_VSTD::addressof(__m)), 3414f7ab58eSDimitry Andric __owns_(__m.try_lock_shared()) 3424f7ab58eSDimitry Andric {} 3434f7ab58eSDimitry Andric 3444f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3454f7ab58eSDimitry Andric shared_lock(mutex_type& __m, adopt_lock_t) 3467c82a1ecSDimitry Andric : __m_(_VSTD::addressof(__m)), 3474f7ab58eSDimitry Andric __owns_(true) 3484f7ab58eSDimitry Andric {} 3494f7ab58eSDimitry Andric 3504f7ab58eSDimitry Andric template <class _Clock, class _Duration> 3514f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3524f7ab58eSDimitry Andric shared_lock(mutex_type& __m, 3534f7ab58eSDimitry Andric const chrono::time_point<_Clock, _Duration>& __abs_time) 3547c82a1ecSDimitry Andric : __m_(_VSTD::addressof(__m)), 3554f7ab58eSDimitry Andric __owns_(__m.try_lock_shared_until(__abs_time)) 3564f7ab58eSDimitry Andric {} 3574f7ab58eSDimitry Andric 3584f7ab58eSDimitry Andric template <class _Rep, class _Period> 3594f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3604f7ab58eSDimitry Andric shared_lock(mutex_type& __m, 3614f7ab58eSDimitry Andric const chrono::duration<_Rep, _Period>& __rel_time) 3627c82a1ecSDimitry Andric : __m_(_VSTD::addressof(__m)), 3634f7ab58eSDimitry Andric __owns_(__m.try_lock_shared_for(__rel_time)) 3644f7ab58eSDimitry Andric {} 3654f7ab58eSDimitry Andric 3664f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3674f7ab58eSDimitry Andric ~shared_lock() 3684f7ab58eSDimitry Andric { 3694f7ab58eSDimitry Andric if (__owns_) 3704f7ab58eSDimitry Andric __m_->unlock_shared(); 3714f7ab58eSDimitry Andric } 3724f7ab58eSDimitry Andric 3734f7ab58eSDimitry Andric shared_lock(shared_lock const&) = delete; 3744f7ab58eSDimitry Andric shared_lock& operator=(shared_lock const&) = delete; 3754f7ab58eSDimitry Andric 3764f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 377d72607e9SDimitry Andric shared_lock(shared_lock&& __u) _NOEXCEPT 3784f7ab58eSDimitry Andric : __m_(__u.__m_), 3794f7ab58eSDimitry Andric __owns_(__u.__owns_) 3804f7ab58eSDimitry Andric { 3814f7ab58eSDimitry Andric __u.__m_ = nullptr; 3824f7ab58eSDimitry Andric __u.__owns_ = false; 3834f7ab58eSDimitry Andric } 3844f7ab58eSDimitry Andric 3854f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 386d72607e9SDimitry Andric shared_lock& operator=(shared_lock&& __u) _NOEXCEPT 3874f7ab58eSDimitry Andric { 3884f7ab58eSDimitry Andric if (__owns_) 3894f7ab58eSDimitry Andric __m_->unlock_shared(); 3904f7ab58eSDimitry Andric __m_ = nullptr; 3914f7ab58eSDimitry Andric __owns_ = false; 3924f7ab58eSDimitry Andric __m_ = __u.__m_; 3934f7ab58eSDimitry Andric __owns_ = __u.__owns_; 3944f7ab58eSDimitry Andric __u.__m_ = nullptr; 3954f7ab58eSDimitry Andric __u.__owns_ = false; 3964f7ab58eSDimitry Andric return *this; 3974f7ab58eSDimitry Andric } 3984f7ab58eSDimitry Andric 3994f7ab58eSDimitry Andric void lock(); 4004f7ab58eSDimitry Andric bool try_lock(); 4014f7ab58eSDimitry Andric template <class Rep, class Period> 4024f7ab58eSDimitry Andric bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 4034f7ab58eSDimitry Andric template <class Clock, class Duration> 4044f7ab58eSDimitry Andric bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 4054f7ab58eSDimitry Andric void unlock(); 4064f7ab58eSDimitry Andric 4074f7ab58eSDimitry Andric // Setters 4084f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 409d72607e9SDimitry Andric void swap(shared_lock& __u) _NOEXCEPT 4104f7ab58eSDimitry Andric { 4114f7ab58eSDimitry Andric _VSTD::swap(__m_, __u.__m_); 4124f7ab58eSDimitry Andric _VSTD::swap(__owns_, __u.__owns_); 4134f7ab58eSDimitry Andric } 4144f7ab58eSDimitry Andric 4154f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 416d72607e9SDimitry Andric mutex_type* release() _NOEXCEPT 4174f7ab58eSDimitry Andric { 4184f7ab58eSDimitry Andric mutex_type* __m = __m_; 4194f7ab58eSDimitry Andric __m_ = nullptr; 4204f7ab58eSDimitry Andric __owns_ = false; 4214f7ab58eSDimitry Andric return __m; 4224f7ab58eSDimitry Andric } 4234f7ab58eSDimitry Andric 4244f7ab58eSDimitry Andric // Getters 4254f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 426d72607e9SDimitry Andric bool owns_lock() const _NOEXCEPT {return __owns_;} 4274f7ab58eSDimitry Andric 4284f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 429d72607e9SDimitry Andric explicit operator bool () const _NOEXCEPT {return __owns_;} 4304f7ab58eSDimitry Andric 4314f7ab58eSDimitry Andric _LIBCPP_INLINE_VISIBILITY 432d72607e9SDimitry Andric mutex_type* mutex() const _NOEXCEPT {return __m_;} 4334f7ab58eSDimitry Andric}; 4344f7ab58eSDimitry Andric 4354f7ab58eSDimitry Andrictemplate <class _Mutex> 4364f7ab58eSDimitry Andricvoid 4374f7ab58eSDimitry Andricshared_lock<_Mutex>::lock() 4384f7ab58eSDimitry Andric{ 4394f7ab58eSDimitry Andric if (__m_ == nullptr) 4404f7ab58eSDimitry Andric __throw_system_error(EPERM, "shared_lock::lock: references null mutex"); 4414f7ab58eSDimitry Andric if (__owns_) 4424f7ab58eSDimitry Andric __throw_system_error(EDEADLK, "shared_lock::lock: already locked"); 4434f7ab58eSDimitry Andric __m_->lock_shared(); 4444f7ab58eSDimitry Andric __owns_ = true; 4454f7ab58eSDimitry Andric} 4464f7ab58eSDimitry Andric 4474f7ab58eSDimitry Andrictemplate <class _Mutex> 4484f7ab58eSDimitry Andricbool 4494f7ab58eSDimitry Andricshared_lock<_Mutex>::try_lock() 4504f7ab58eSDimitry Andric{ 4514f7ab58eSDimitry Andric if (__m_ == nullptr) 4524f7ab58eSDimitry Andric __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex"); 4534f7ab58eSDimitry Andric if (__owns_) 4544f7ab58eSDimitry Andric __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked"); 4554f7ab58eSDimitry Andric __owns_ = __m_->try_lock_shared(); 4564f7ab58eSDimitry Andric return __owns_; 4574f7ab58eSDimitry Andric} 4584f7ab58eSDimitry Andric 4594f7ab58eSDimitry Andrictemplate <class _Mutex> 4604f7ab58eSDimitry Andrictemplate <class _Rep, class _Period> 4614f7ab58eSDimitry Andricbool 4624f7ab58eSDimitry Andricshared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 4634f7ab58eSDimitry Andric{ 4644f7ab58eSDimitry Andric if (__m_ == nullptr) 4654f7ab58eSDimitry Andric __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex"); 4664f7ab58eSDimitry Andric if (__owns_) 4674f7ab58eSDimitry Andric __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked"); 4684f7ab58eSDimitry Andric __owns_ = __m_->try_lock_shared_for(__d); 4694f7ab58eSDimitry Andric return __owns_; 4704f7ab58eSDimitry Andric} 4714f7ab58eSDimitry Andric 4724f7ab58eSDimitry Andrictemplate <class _Mutex> 4734f7ab58eSDimitry Andrictemplate <class _Clock, class _Duration> 4744f7ab58eSDimitry Andricbool 4754f7ab58eSDimitry Andricshared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 4764f7ab58eSDimitry Andric{ 4774f7ab58eSDimitry Andric if (__m_ == nullptr) 4784f7ab58eSDimitry Andric __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex"); 4794f7ab58eSDimitry Andric if (__owns_) 4804f7ab58eSDimitry Andric __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked"); 4814f7ab58eSDimitry Andric __owns_ = __m_->try_lock_shared_until(__t); 4824f7ab58eSDimitry Andric return __owns_; 4834f7ab58eSDimitry Andric} 4844f7ab58eSDimitry Andric 4854f7ab58eSDimitry Andrictemplate <class _Mutex> 4864f7ab58eSDimitry Andricvoid 4874f7ab58eSDimitry Andricshared_lock<_Mutex>::unlock() 4884f7ab58eSDimitry Andric{ 4894f7ab58eSDimitry Andric if (!__owns_) 4904f7ab58eSDimitry Andric __throw_system_error(EPERM, "shared_lock::unlock: not locked"); 4914f7ab58eSDimitry Andric __m_->unlock_shared(); 4924f7ab58eSDimitry Andric __owns_ = false; 4934f7ab58eSDimitry Andric} 4944f7ab58eSDimitry Andric 4954f7ab58eSDimitry Andrictemplate <class _Mutex> 4964f7ab58eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 4974f7ab58eSDimitry Andricvoid 498d72607e9SDimitry Andricswap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT 4994f7ab58eSDimitry Andric {__x.swap(__y);} 5004f7ab58eSDimitry Andric 5014f7ab58eSDimitry Andric_LIBCPP_END_NAMESPACE_STD 5024f7ab58eSDimitry Andric 503d72607e9SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS 504d72607e9SDimitry Andric 5054f7ab58eSDimitry Andric#endif // _LIBCPP_STD_VER > 11 5064f7ab58eSDimitry Andric 507f9448bf3SDimitry Andric_LIBCPP_POP_MACROS 508f9448bf3SDimitry Andric 5094f7ab58eSDimitry Andric#endif // _LIBCPP_SHARED_MUTEX 510