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