14684ddb6SLionel Sambuc// -*- C++ -*- 24684ddb6SLionel Sambuc//===------------------------ shared_mutex --------------------------------===// 34684ddb6SLionel Sambuc// 44684ddb6SLionel Sambuc// The LLVM Compiler Infrastructure 54684ddb6SLionel Sambuc// 64684ddb6SLionel Sambuc// This file is dual licensed under the MIT and the University of Illinois Open 74684ddb6SLionel Sambuc// Source Licenses. See LICENSE.TXT for details. 84684ddb6SLionel Sambuc// 94684ddb6SLionel Sambuc//===----------------------------------------------------------------------===// 104684ddb6SLionel Sambuc 114684ddb6SLionel Sambuc#ifndef _LIBCPP_SHARED_MUTEX 124684ddb6SLionel Sambuc#define _LIBCPP_SHARED_MUTEX 134684ddb6SLionel Sambuc 144684ddb6SLionel Sambuc/* 154684ddb6SLionel Sambuc shared_mutex synopsis 164684ddb6SLionel Sambuc 174684ddb6SLionel Sambuc// C++1y 184684ddb6SLionel Sambuc 194684ddb6SLionel Sambucnamespace std 204684ddb6SLionel Sambuc{ 214684ddb6SLionel Sambuc 22*0a6a1f1dSLionel Sambucclass shared_mutex // C++17 234684ddb6SLionel Sambuc{ 244684ddb6SLionel Sambucpublic: 254684ddb6SLionel Sambuc shared_mutex(); 264684ddb6SLionel Sambuc ~shared_mutex(); 274684ddb6SLionel Sambuc 284684ddb6SLionel Sambuc shared_mutex(const shared_mutex&) = delete; 294684ddb6SLionel Sambuc shared_mutex& operator=(const shared_mutex&) = delete; 304684ddb6SLionel Sambuc 314684ddb6SLionel Sambuc // Exclusive ownership 324684ddb6SLionel Sambuc void lock(); // blocking 334684ddb6SLionel Sambuc bool try_lock(); 34*0a6a1f1dSLionel Sambuc void unlock(); 35*0a6a1f1dSLionel Sambuc 36*0a6a1f1dSLionel Sambuc // Shared ownership 37*0a6a1f1dSLionel Sambuc void lock_shared(); // blocking 38*0a6a1f1dSLionel Sambuc bool try_lock_shared(); 39*0a6a1f1dSLionel Sambuc void unlock_shared(); 40*0a6a1f1dSLionel Sambuc 41*0a6a1f1dSLionel Sambuc typedef implementation-defined native_handle_type; // See 30.2.3 42*0a6a1f1dSLionel Sambuc native_handle_type native_handle(); // See 30.2.3 43*0a6a1f1dSLionel Sambuc}; 44*0a6a1f1dSLionel Sambuc 45*0a6a1f1dSLionel Sambucclass shared_timed_mutex 46*0a6a1f1dSLionel Sambuc{ 47*0a6a1f1dSLionel Sambucpublic: 48*0a6a1f1dSLionel Sambuc shared_timed_mutex(); 49*0a6a1f1dSLionel Sambuc ~shared_timed_mutex(); 50*0a6a1f1dSLionel Sambuc 51*0a6a1f1dSLionel Sambuc shared_timed_mutex(const shared_timed_mutex&) = delete; 52*0a6a1f1dSLionel Sambuc shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; 53*0a6a1f1dSLionel Sambuc 54*0a6a1f1dSLionel Sambuc // Exclusive ownership 55*0a6a1f1dSLionel Sambuc void lock(); // blocking 56*0a6a1f1dSLionel Sambuc bool try_lock(); 574684ddb6SLionel Sambuc template <class Rep, class Period> 584684ddb6SLionel Sambuc bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 594684ddb6SLionel Sambuc template <class Clock, class Duration> 604684ddb6SLionel Sambuc bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 614684ddb6SLionel Sambuc void unlock(); 624684ddb6SLionel Sambuc 634684ddb6SLionel Sambuc // Shared ownership 644684ddb6SLionel Sambuc void lock_shared(); // blocking 654684ddb6SLionel Sambuc bool try_lock_shared(); 664684ddb6SLionel Sambuc template <class Rep, class Period> 674684ddb6SLionel Sambuc bool 684684ddb6SLionel Sambuc try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time); 694684ddb6SLionel Sambuc template <class Clock, class Duration> 704684ddb6SLionel Sambuc bool 714684ddb6SLionel Sambuc try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time); 724684ddb6SLionel Sambuc void unlock_shared(); 734684ddb6SLionel Sambuc}; 744684ddb6SLionel Sambuc 754684ddb6SLionel Sambuctemplate <class Mutex> 764684ddb6SLionel Sambucclass shared_lock 774684ddb6SLionel Sambuc{ 784684ddb6SLionel Sambucpublic: 794684ddb6SLionel Sambuc typedef Mutex mutex_type; 804684ddb6SLionel Sambuc 814684ddb6SLionel Sambuc // Shared locking 824684ddb6SLionel Sambuc shared_lock() noexcept; 834684ddb6SLionel Sambuc explicit shared_lock(mutex_type& m); // blocking 844684ddb6SLionel Sambuc shared_lock(mutex_type& m, defer_lock_t) noexcept; 854684ddb6SLionel Sambuc shared_lock(mutex_type& m, try_to_lock_t); 864684ddb6SLionel Sambuc shared_lock(mutex_type& m, adopt_lock_t); 874684ddb6SLionel Sambuc template <class Clock, class Duration> 884684ddb6SLionel Sambuc shared_lock(mutex_type& m, 894684ddb6SLionel Sambuc const chrono::time_point<Clock, Duration>& abs_time); 904684ddb6SLionel Sambuc template <class Rep, class Period> 914684ddb6SLionel Sambuc shared_lock(mutex_type& m, 924684ddb6SLionel Sambuc const chrono::duration<Rep, Period>& rel_time); 934684ddb6SLionel Sambuc ~shared_lock(); 944684ddb6SLionel Sambuc 954684ddb6SLionel Sambuc shared_lock(shared_lock const&) = delete; 964684ddb6SLionel Sambuc shared_lock& operator=(shared_lock const&) = delete; 974684ddb6SLionel Sambuc 984684ddb6SLionel Sambuc shared_lock(shared_lock&& u) noexcept; 994684ddb6SLionel Sambuc shared_lock& operator=(shared_lock&& u) noexcept; 1004684ddb6SLionel Sambuc 1014684ddb6SLionel Sambuc void lock(); // blocking 1024684ddb6SLionel Sambuc bool try_lock(); 1034684ddb6SLionel Sambuc template <class Rep, class Period> 1044684ddb6SLionel Sambuc bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 1054684ddb6SLionel Sambuc template <class Clock, class Duration> 1064684ddb6SLionel Sambuc bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 1074684ddb6SLionel Sambuc void unlock(); 1084684ddb6SLionel Sambuc 1094684ddb6SLionel Sambuc // Setters 1104684ddb6SLionel Sambuc void swap(shared_lock& u) noexcept; 1114684ddb6SLionel Sambuc mutex_type* release() noexcept; 1124684ddb6SLionel Sambuc 1134684ddb6SLionel Sambuc // Getters 1144684ddb6SLionel Sambuc bool owns_lock() const noexcept; 1154684ddb6SLionel Sambuc explicit operator bool () const noexcept; 1164684ddb6SLionel Sambuc mutex_type* mutex() const noexcept; 1174684ddb6SLionel Sambuc}; 1184684ddb6SLionel Sambuc 1194684ddb6SLionel Sambuctemplate <class Mutex> 1204684ddb6SLionel Sambuc void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept; 1214684ddb6SLionel Sambuc 1224684ddb6SLionel Sambuc} // std 1234684ddb6SLionel Sambuc 1244684ddb6SLionel Sambuc*/ 1254684ddb6SLionel Sambuc 1264684ddb6SLionel Sambuc#include <__config> 1274684ddb6SLionel Sambuc 1284684ddb6SLionel Sambuc#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_SHARED_MUTEX) 1294684ddb6SLionel Sambuc 1304684ddb6SLionel Sambuc#include <__mutex_base> 1314684ddb6SLionel Sambuc 1324684ddb6SLionel Sambuc#include <__undef_min_max> 1334684ddb6SLionel Sambuc 1344684ddb6SLionel Sambuc#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1354684ddb6SLionel Sambuc#pragma GCC system_header 1364684ddb6SLionel Sambuc#endif 1374684ddb6SLionel Sambuc 138*0a6a1f1dSLionel Sambuc#ifdef _LIBCPP_HAS_NO_THREADS 139*0a6a1f1dSLionel Sambuc#error <shared_mutex> is not supported on this single threaded system 140*0a6a1f1dSLionel Sambuc#else // !_LIBCPP_HAS_NO_THREADS 141*0a6a1f1dSLionel Sambuc 1424684ddb6SLionel Sambuc_LIBCPP_BEGIN_NAMESPACE_STD 1434684ddb6SLionel Sambuc 144*0a6a1f1dSLionel Sambucstruct _LIBCPP_TYPE_VIS __shared_mutex_base 1454684ddb6SLionel Sambuc{ 1464684ddb6SLionel Sambuc mutex __mut_; 1474684ddb6SLionel Sambuc condition_variable __gate1_; 1484684ddb6SLionel Sambuc condition_variable __gate2_; 1494684ddb6SLionel Sambuc unsigned __state_; 1504684ddb6SLionel Sambuc 1514684ddb6SLionel Sambuc static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1); 1524684ddb6SLionel Sambuc static const unsigned __n_readers_ = ~__write_entered_; 153*0a6a1f1dSLionel Sambuc 154*0a6a1f1dSLionel Sambuc __shared_mutex_base(); 155*0a6a1f1dSLionel Sambuc _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default; 156*0a6a1f1dSLionel Sambuc 157*0a6a1f1dSLionel Sambuc __shared_mutex_base(const __shared_mutex_base&) = delete; 158*0a6a1f1dSLionel Sambuc __shared_mutex_base& operator=(const __shared_mutex_base&) = delete; 159*0a6a1f1dSLionel Sambuc 160*0a6a1f1dSLionel Sambuc // Exclusive ownership 161*0a6a1f1dSLionel Sambuc void lock(); // blocking 162*0a6a1f1dSLionel Sambuc bool try_lock(); 163*0a6a1f1dSLionel Sambuc void unlock(); 164*0a6a1f1dSLionel Sambuc 165*0a6a1f1dSLionel Sambuc // Shared ownership 166*0a6a1f1dSLionel Sambuc void lock_shared(); // blocking 167*0a6a1f1dSLionel Sambuc bool try_lock_shared(); 168*0a6a1f1dSLionel Sambuc void unlock_shared(); 169*0a6a1f1dSLionel Sambuc 170*0a6a1f1dSLionel Sambuc// typedef implementation-defined native_handle_type; // See 30.2.3 171*0a6a1f1dSLionel Sambuc// native_handle_type native_handle(); // See 30.2.3 172*0a6a1f1dSLionel Sambuc}; 173*0a6a1f1dSLionel Sambuc 174*0a6a1f1dSLionel Sambuc 175*0a6a1f1dSLionel Sambuc#if _LIBCPP_STD_VER > 14 176*0a6a1f1dSLionel Sambucclass _LIBCPP_TYPE_VIS shared_mutex 177*0a6a1f1dSLionel Sambuc{ 178*0a6a1f1dSLionel Sambuc __shared_mutex_base __base; 1794684ddb6SLionel Sambucpublic: 180*0a6a1f1dSLionel Sambuc shared_mutex() : __base() {} 1814684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default; 1824684ddb6SLionel Sambuc 1834684ddb6SLionel Sambuc shared_mutex(const shared_mutex&) = delete; 1844684ddb6SLionel Sambuc shared_mutex& operator=(const shared_mutex&) = delete; 1854684ddb6SLionel Sambuc 1864684ddb6SLionel Sambuc // Exclusive ownership 187*0a6a1f1dSLionel Sambuc _LIBCPP_INLINE_VISIBILITY void lock() { return __base.lock(); } 188*0a6a1f1dSLionel Sambuc _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); } 189*0a6a1f1dSLionel Sambuc _LIBCPP_INLINE_VISIBILITY void unlock() { return __base.unlock(); } 190*0a6a1f1dSLionel Sambuc 191*0a6a1f1dSLionel Sambuc // Shared ownership 192*0a6a1f1dSLionel Sambuc _LIBCPP_INLINE_VISIBILITY void lock_shared() { return __base.lock_shared(); } 193*0a6a1f1dSLionel Sambuc _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); } 194*0a6a1f1dSLionel Sambuc _LIBCPP_INLINE_VISIBILITY void unlock_shared() { return __base.unlock_shared(); } 195*0a6a1f1dSLionel Sambuc 196*0a6a1f1dSLionel Sambuc// typedef __shared_mutex_base::native_handle_type native_handle_type; 197*0a6a1f1dSLionel Sambuc// _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); } 198*0a6a1f1dSLionel Sambuc}; 199*0a6a1f1dSLionel Sambuc#endif 200*0a6a1f1dSLionel Sambuc 201*0a6a1f1dSLionel Sambuc 202*0a6a1f1dSLionel Sambucclass _LIBCPP_TYPE_VIS shared_timed_mutex 203*0a6a1f1dSLionel Sambuc{ 204*0a6a1f1dSLionel Sambuc __shared_mutex_base __base; 205*0a6a1f1dSLionel Sambucpublic: 206*0a6a1f1dSLionel Sambuc shared_timed_mutex(); 207*0a6a1f1dSLionel Sambuc _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default; 208*0a6a1f1dSLionel Sambuc 209*0a6a1f1dSLionel Sambuc shared_timed_mutex(const shared_timed_mutex&) = delete; 210*0a6a1f1dSLionel Sambuc shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; 211*0a6a1f1dSLionel Sambuc 212*0a6a1f1dSLionel Sambuc // Exclusive ownership 2134684ddb6SLionel Sambuc void lock(); 2144684ddb6SLionel Sambuc bool try_lock(); 2154684ddb6SLionel Sambuc template <class _Rep, class _Period> 2164684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 2174684ddb6SLionel Sambuc bool 2184684ddb6SLionel Sambuc try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) 2194684ddb6SLionel Sambuc { 2204684ddb6SLionel Sambuc return try_lock_until(chrono::steady_clock::now() + __rel_time); 2214684ddb6SLionel Sambuc } 2224684ddb6SLionel Sambuc template <class _Clock, class _Duration> 2234684ddb6SLionel Sambuc bool 2244684ddb6SLionel Sambuc try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time); 2254684ddb6SLionel Sambuc void unlock(); 2264684ddb6SLionel Sambuc 2274684ddb6SLionel Sambuc // Shared ownership 2284684ddb6SLionel Sambuc void lock_shared(); 2294684ddb6SLionel Sambuc bool try_lock_shared(); 2304684ddb6SLionel Sambuc template <class _Rep, class _Period> 2314684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 2324684ddb6SLionel Sambuc bool 2334684ddb6SLionel Sambuc try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) 2344684ddb6SLionel Sambuc { 2354684ddb6SLionel Sambuc return try_lock_shared_until(chrono::steady_clock::now() + __rel_time); 2364684ddb6SLionel Sambuc } 2374684ddb6SLionel Sambuc template <class _Clock, class _Duration> 2384684ddb6SLionel Sambuc bool 2394684ddb6SLionel Sambuc try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time); 2404684ddb6SLionel Sambuc void unlock_shared(); 2414684ddb6SLionel Sambuc}; 2424684ddb6SLionel Sambuc 2434684ddb6SLionel Sambuctemplate <class _Clock, class _Duration> 2444684ddb6SLionel Sambucbool 245*0a6a1f1dSLionel Sambucshared_timed_mutex::try_lock_until( 2464684ddb6SLionel Sambuc const chrono::time_point<_Clock, _Duration>& __abs_time) 2474684ddb6SLionel Sambuc{ 248*0a6a1f1dSLionel Sambuc unique_lock<mutex> __lk(__base.__mut_); 249*0a6a1f1dSLionel Sambuc if (__base.__state_ & __base.__write_entered_) 2504684ddb6SLionel Sambuc { 2514684ddb6SLionel Sambuc while (true) 2524684ddb6SLionel Sambuc { 253*0a6a1f1dSLionel Sambuc cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time); 254*0a6a1f1dSLionel Sambuc if ((__base.__state_ & __base.__write_entered_) == 0) 2554684ddb6SLionel Sambuc break; 2564684ddb6SLionel Sambuc if (__status == cv_status::timeout) 2574684ddb6SLionel Sambuc return false; 2584684ddb6SLionel Sambuc } 2594684ddb6SLionel Sambuc } 260*0a6a1f1dSLionel Sambuc __base.__state_ |= __base.__write_entered_; 261*0a6a1f1dSLionel Sambuc if (__base.__state_ & __base.__n_readers_) 2624684ddb6SLionel Sambuc { 2634684ddb6SLionel Sambuc while (true) 2644684ddb6SLionel Sambuc { 265*0a6a1f1dSLionel Sambuc cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time); 266*0a6a1f1dSLionel Sambuc if ((__base.__state_ & __base.__n_readers_) == 0) 2674684ddb6SLionel Sambuc break; 2684684ddb6SLionel Sambuc if (__status == cv_status::timeout) 2694684ddb6SLionel Sambuc { 270*0a6a1f1dSLionel Sambuc __base.__state_ &= ~__base.__write_entered_; 271*0a6a1f1dSLionel Sambuc __base.__gate1_.notify_all(); 2724684ddb6SLionel Sambuc return false; 2734684ddb6SLionel Sambuc } 2744684ddb6SLionel Sambuc } 2754684ddb6SLionel Sambuc } 2764684ddb6SLionel Sambuc return true; 2774684ddb6SLionel Sambuc} 2784684ddb6SLionel Sambuc 2794684ddb6SLionel Sambuctemplate <class _Clock, class _Duration> 2804684ddb6SLionel Sambucbool 281*0a6a1f1dSLionel Sambucshared_timed_mutex::try_lock_shared_until( 2824684ddb6SLionel Sambuc const chrono::time_point<_Clock, _Duration>& __abs_time) 2834684ddb6SLionel Sambuc{ 284*0a6a1f1dSLionel Sambuc unique_lock<mutex> __lk(__base.__mut_); 285*0a6a1f1dSLionel Sambuc if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_) 2864684ddb6SLionel Sambuc { 2874684ddb6SLionel Sambuc while (true) 2884684ddb6SLionel Sambuc { 289*0a6a1f1dSLionel Sambuc cv_status status = __base.__gate1_.wait_until(__lk, __abs_time); 290*0a6a1f1dSLionel Sambuc if ((__base.__state_ & __base.__write_entered_) == 0 && 291*0a6a1f1dSLionel Sambuc (__base.__state_ & __base.__n_readers_) < __base.__n_readers_) 2924684ddb6SLionel Sambuc break; 2934684ddb6SLionel Sambuc if (status == cv_status::timeout) 2944684ddb6SLionel Sambuc return false; 2954684ddb6SLionel Sambuc } 2964684ddb6SLionel Sambuc } 297*0a6a1f1dSLionel Sambuc unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1; 298*0a6a1f1dSLionel Sambuc __base.__state_ &= ~__base.__n_readers_; 299*0a6a1f1dSLionel Sambuc __base.__state_ |= __num_readers; 3004684ddb6SLionel Sambuc return true; 3014684ddb6SLionel Sambuc} 3024684ddb6SLionel Sambuc 3034684ddb6SLionel Sambuctemplate <class _Mutex> 3044684ddb6SLionel Sambucclass shared_lock 3054684ddb6SLionel Sambuc{ 3064684ddb6SLionel Sambucpublic: 3074684ddb6SLionel Sambuc typedef _Mutex mutex_type; 3084684ddb6SLionel Sambuc 3094684ddb6SLionel Sambucprivate: 3104684ddb6SLionel Sambuc mutex_type* __m_; 3114684ddb6SLionel Sambuc bool __owns_; 3124684ddb6SLionel Sambuc 3134684ddb6SLionel Sambucpublic: 3144684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 315*0a6a1f1dSLionel Sambuc shared_lock() _NOEXCEPT 3164684ddb6SLionel Sambuc : __m_(nullptr), 3174684ddb6SLionel Sambuc __owns_(false) 3184684ddb6SLionel Sambuc {} 3194684ddb6SLionel Sambuc 3204684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 3214684ddb6SLionel Sambuc explicit shared_lock(mutex_type& __m) 3224684ddb6SLionel Sambuc : __m_(&__m), 3234684ddb6SLionel Sambuc __owns_(true) 3244684ddb6SLionel Sambuc {__m_->lock_shared();} 3254684ddb6SLionel Sambuc 3264684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 327*0a6a1f1dSLionel Sambuc shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 3284684ddb6SLionel Sambuc : __m_(&__m), 3294684ddb6SLionel Sambuc __owns_(false) 3304684ddb6SLionel Sambuc {} 3314684ddb6SLionel Sambuc 3324684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 3334684ddb6SLionel Sambuc shared_lock(mutex_type& __m, try_to_lock_t) 3344684ddb6SLionel Sambuc : __m_(&__m), 3354684ddb6SLionel Sambuc __owns_(__m.try_lock_shared()) 3364684ddb6SLionel Sambuc {} 3374684ddb6SLionel Sambuc 3384684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 3394684ddb6SLionel Sambuc shared_lock(mutex_type& __m, adopt_lock_t) 3404684ddb6SLionel Sambuc : __m_(&__m), 3414684ddb6SLionel Sambuc __owns_(true) 3424684ddb6SLionel Sambuc {} 3434684ddb6SLionel Sambuc 3444684ddb6SLionel Sambuc template <class _Clock, class _Duration> 3454684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 3464684ddb6SLionel Sambuc shared_lock(mutex_type& __m, 3474684ddb6SLionel Sambuc const chrono::time_point<_Clock, _Duration>& __abs_time) 3484684ddb6SLionel Sambuc : __m_(&__m), 3494684ddb6SLionel Sambuc __owns_(__m.try_lock_shared_until(__abs_time)) 3504684ddb6SLionel Sambuc {} 3514684ddb6SLionel Sambuc 3524684ddb6SLionel Sambuc template <class _Rep, class _Period> 3534684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 3544684ddb6SLionel Sambuc shared_lock(mutex_type& __m, 3554684ddb6SLionel Sambuc const chrono::duration<_Rep, _Period>& __rel_time) 3564684ddb6SLionel Sambuc : __m_(&__m), 3574684ddb6SLionel Sambuc __owns_(__m.try_lock_shared_for(__rel_time)) 3584684ddb6SLionel Sambuc {} 3594684ddb6SLionel Sambuc 3604684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 3614684ddb6SLionel Sambuc ~shared_lock() 3624684ddb6SLionel Sambuc { 3634684ddb6SLionel Sambuc if (__owns_) 3644684ddb6SLionel Sambuc __m_->unlock_shared(); 3654684ddb6SLionel Sambuc } 3664684ddb6SLionel Sambuc 3674684ddb6SLionel Sambuc shared_lock(shared_lock const&) = delete; 3684684ddb6SLionel Sambuc shared_lock& operator=(shared_lock const&) = delete; 3694684ddb6SLionel Sambuc 3704684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 371*0a6a1f1dSLionel Sambuc shared_lock(shared_lock&& __u) _NOEXCEPT 3724684ddb6SLionel Sambuc : __m_(__u.__m_), 3734684ddb6SLionel Sambuc __owns_(__u.__owns_) 3744684ddb6SLionel Sambuc { 3754684ddb6SLionel Sambuc __u.__m_ = nullptr; 3764684ddb6SLionel Sambuc __u.__owns_ = false; 3774684ddb6SLionel Sambuc } 3784684ddb6SLionel Sambuc 3794684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 380*0a6a1f1dSLionel Sambuc shared_lock& operator=(shared_lock&& __u) _NOEXCEPT 3814684ddb6SLionel Sambuc { 3824684ddb6SLionel Sambuc if (__owns_) 3834684ddb6SLionel Sambuc __m_->unlock_shared(); 3844684ddb6SLionel Sambuc __m_ = nullptr; 3854684ddb6SLionel Sambuc __owns_ = false; 3864684ddb6SLionel Sambuc __m_ = __u.__m_; 3874684ddb6SLionel Sambuc __owns_ = __u.__owns_; 3884684ddb6SLionel Sambuc __u.__m_ = nullptr; 3894684ddb6SLionel Sambuc __u.__owns_ = false; 3904684ddb6SLionel Sambuc return *this; 3914684ddb6SLionel Sambuc } 3924684ddb6SLionel Sambuc 3934684ddb6SLionel Sambuc void lock(); 3944684ddb6SLionel Sambuc bool try_lock(); 3954684ddb6SLionel Sambuc template <class Rep, class Period> 3964684ddb6SLionel Sambuc bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 3974684ddb6SLionel Sambuc template <class Clock, class Duration> 3984684ddb6SLionel Sambuc bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 3994684ddb6SLionel Sambuc void unlock(); 4004684ddb6SLionel Sambuc 4014684ddb6SLionel Sambuc // Setters 4024684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 403*0a6a1f1dSLionel Sambuc void swap(shared_lock& __u) _NOEXCEPT 4044684ddb6SLionel Sambuc { 4054684ddb6SLionel Sambuc _VSTD::swap(__m_, __u.__m_); 4064684ddb6SLionel Sambuc _VSTD::swap(__owns_, __u.__owns_); 4074684ddb6SLionel Sambuc } 4084684ddb6SLionel Sambuc 4094684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 410*0a6a1f1dSLionel Sambuc mutex_type* release() _NOEXCEPT 4114684ddb6SLionel Sambuc { 4124684ddb6SLionel Sambuc mutex_type* __m = __m_; 4134684ddb6SLionel Sambuc __m_ = nullptr; 4144684ddb6SLionel Sambuc __owns_ = false; 4154684ddb6SLionel Sambuc return __m; 4164684ddb6SLionel Sambuc } 4174684ddb6SLionel Sambuc 4184684ddb6SLionel Sambuc // Getters 4194684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 420*0a6a1f1dSLionel Sambuc bool owns_lock() const _NOEXCEPT {return __owns_;} 4214684ddb6SLionel Sambuc 4224684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 423*0a6a1f1dSLionel Sambuc explicit operator bool () const _NOEXCEPT {return __owns_;} 4244684ddb6SLionel Sambuc 4254684ddb6SLionel Sambuc _LIBCPP_INLINE_VISIBILITY 426*0a6a1f1dSLionel Sambuc mutex_type* mutex() const _NOEXCEPT {return __m_;} 4274684ddb6SLionel Sambuc}; 4284684ddb6SLionel Sambuc 4294684ddb6SLionel Sambuctemplate <class _Mutex> 4304684ddb6SLionel Sambucvoid 4314684ddb6SLionel Sambucshared_lock<_Mutex>::lock() 4324684ddb6SLionel Sambuc{ 4334684ddb6SLionel Sambuc if (__m_ == nullptr) 4344684ddb6SLionel Sambuc __throw_system_error(EPERM, "shared_lock::lock: references null mutex"); 4354684ddb6SLionel Sambuc if (__owns_) 4364684ddb6SLionel Sambuc __throw_system_error(EDEADLK, "shared_lock::lock: already locked"); 4374684ddb6SLionel Sambuc __m_->lock_shared(); 4384684ddb6SLionel Sambuc __owns_ = true; 4394684ddb6SLionel Sambuc} 4404684ddb6SLionel Sambuc 4414684ddb6SLionel Sambuctemplate <class _Mutex> 4424684ddb6SLionel Sambucbool 4434684ddb6SLionel Sambucshared_lock<_Mutex>::try_lock() 4444684ddb6SLionel Sambuc{ 4454684ddb6SLionel Sambuc if (__m_ == nullptr) 4464684ddb6SLionel Sambuc __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex"); 4474684ddb6SLionel Sambuc if (__owns_) 4484684ddb6SLionel Sambuc __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked"); 4494684ddb6SLionel Sambuc __owns_ = __m_->try_lock_shared(); 4504684ddb6SLionel Sambuc return __owns_; 4514684ddb6SLionel Sambuc} 4524684ddb6SLionel Sambuc 4534684ddb6SLionel Sambuctemplate <class _Mutex> 4544684ddb6SLionel Sambuctemplate <class _Rep, class _Period> 4554684ddb6SLionel Sambucbool 4564684ddb6SLionel Sambucshared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 4574684ddb6SLionel Sambuc{ 4584684ddb6SLionel Sambuc if (__m_ == nullptr) 4594684ddb6SLionel Sambuc __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex"); 4604684ddb6SLionel Sambuc if (__owns_) 4614684ddb6SLionel Sambuc __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked"); 4624684ddb6SLionel Sambuc __owns_ = __m_->try_lock_shared_for(__d); 4634684ddb6SLionel Sambuc return __owns_; 4644684ddb6SLionel Sambuc} 4654684ddb6SLionel Sambuc 4664684ddb6SLionel Sambuctemplate <class _Mutex> 4674684ddb6SLionel Sambuctemplate <class _Clock, class _Duration> 4684684ddb6SLionel Sambucbool 4694684ddb6SLionel Sambucshared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 4704684ddb6SLionel Sambuc{ 4714684ddb6SLionel Sambuc if (__m_ == nullptr) 4724684ddb6SLionel Sambuc __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex"); 4734684ddb6SLionel Sambuc if (__owns_) 4744684ddb6SLionel Sambuc __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked"); 4754684ddb6SLionel Sambuc __owns_ = __m_->try_lock_shared_until(__t); 4764684ddb6SLionel Sambuc return __owns_; 4774684ddb6SLionel Sambuc} 4784684ddb6SLionel Sambuc 4794684ddb6SLionel Sambuctemplate <class _Mutex> 4804684ddb6SLionel Sambucvoid 4814684ddb6SLionel Sambucshared_lock<_Mutex>::unlock() 4824684ddb6SLionel Sambuc{ 4834684ddb6SLionel Sambuc if (!__owns_) 4844684ddb6SLionel Sambuc __throw_system_error(EPERM, "shared_lock::unlock: not locked"); 4854684ddb6SLionel Sambuc __m_->unlock_shared(); 4864684ddb6SLionel Sambuc __owns_ = false; 4874684ddb6SLionel Sambuc} 4884684ddb6SLionel Sambuc 4894684ddb6SLionel Sambuctemplate <class _Mutex> 4904684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY 4914684ddb6SLionel Sambucvoid 492*0a6a1f1dSLionel Sambucswap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT 4934684ddb6SLionel Sambuc {__x.swap(__y);} 4944684ddb6SLionel Sambuc 4954684ddb6SLionel Sambuc_LIBCPP_END_NAMESPACE_STD 4964684ddb6SLionel Sambuc 497*0a6a1f1dSLionel Sambuc#endif // !_LIBCPP_HAS_NO_THREADS 498*0a6a1f1dSLionel Sambuc 4994684ddb6SLionel Sambuc#endif // _LIBCPP_STD_VER > 11 5004684ddb6SLionel Sambuc 5014684ddb6SLionel Sambuc#endif // _LIBCPP_SHARED_MUTEX 502