1*4d6fc14bSjoerg //===---------------------- shared_mutex.cpp ------------------------------===// 2*4d6fc14bSjoerg // 3*4d6fc14bSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*4d6fc14bSjoerg // See https://llvm.org/LICENSE.txt for license information. 5*4d6fc14bSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*4d6fc14bSjoerg // 7*4d6fc14bSjoerg //===----------------------------------------------------------------------===// 8*4d6fc14bSjoerg 9*4d6fc14bSjoerg #include "__config" 10*4d6fc14bSjoerg #ifndef _LIBCPP_HAS_NO_THREADS 11*4d6fc14bSjoerg 12*4d6fc14bSjoerg #include "shared_mutex" 13*4d6fc14bSjoerg #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) 14*4d6fc14bSjoerg #pragma comment(lib, "pthread") 15*4d6fc14bSjoerg #endif 16*4d6fc14bSjoerg 17*4d6fc14bSjoerg _LIBCPP_BEGIN_NAMESPACE_STD 18*4d6fc14bSjoerg 19*4d6fc14bSjoerg // Shared Mutex Base __shared_mutex_base()20*4d6fc14bSjoerg__shared_mutex_base::__shared_mutex_base() 21*4d6fc14bSjoerg : __state_(0) 22*4d6fc14bSjoerg { 23*4d6fc14bSjoerg } 24*4d6fc14bSjoerg 25*4d6fc14bSjoerg // Exclusive ownership 26*4d6fc14bSjoerg 27*4d6fc14bSjoerg void lock()28*4d6fc14bSjoerg__shared_mutex_base::lock() 29*4d6fc14bSjoerg { 30*4d6fc14bSjoerg unique_lock<mutex> lk(__mut_); 31*4d6fc14bSjoerg while (__state_ & __write_entered_) 32*4d6fc14bSjoerg __gate1_.wait(lk); 33*4d6fc14bSjoerg __state_ |= __write_entered_; 34*4d6fc14bSjoerg while (__state_ & __n_readers_) 35*4d6fc14bSjoerg __gate2_.wait(lk); 36*4d6fc14bSjoerg } 37*4d6fc14bSjoerg 38*4d6fc14bSjoerg bool try_lock()39*4d6fc14bSjoerg__shared_mutex_base::try_lock() 40*4d6fc14bSjoerg { 41*4d6fc14bSjoerg unique_lock<mutex> lk(__mut_); 42*4d6fc14bSjoerg if (__state_ == 0) 43*4d6fc14bSjoerg { 44*4d6fc14bSjoerg __state_ = __write_entered_; 45*4d6fc14bSjoerg return true; 46*4d6fc14bSjoerg } 47*4d6fc14bSjoerg return false; 48*4d6fc14bSjoerg } 49*4d6fc14bSjoerg 50*4d6fc14bSjoerg void unlock()51*4d6fc14bSjoerg__shared_mutex_base::unlock() 52*4d6fc14bSjoerg { 53*4d6fc14bSjoerg lock_guard<mutex> _(__mut_); 54*4d6fc14bSjoerg __state_ = 0; 55*4d6fc14bSjoerg __gate1_.notify_all(); 56*4d6fc14bSjoerg } 57*4d6fc14bSjoerg 58*4d6fc14bSjoerg // Shared ownership 59*4d6fc14bSjoerg 60*4d6fc14bSjoerg void lock_shared()61*4d6fc14bSjoerg__shared_mutex_base::lock_shared() 62*4d6fc14bSjoerg { 63*4d6fc14bSjoerg unique_lock<mutex> lk(__mut_); 64*4d6fc14bSjoerg while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) 65*4d6fc14bSjoerg __gate1_.wait(lk); 66*4d6fc14bSjoerg unsigned num_readers = (__state_ & __n_readers_) + 1; 67*4d6fc14bSjoerg __state_ &= ~__n_readers_; 68*4d6fc14bSjoerg __state_ |= num_readers; 69*4d6fc14bSjoerg } 70*4d6fc14bSjoerg 71*4d6fc14bSjoerg bool try_lock_shared()72*4d6fc14bSjoerg__shared_mutex_base::try_lock_shared() 73*4d6fc14bSjoerg { 74*4d6fc14bSjoerg unique_lock<mutex> lk(__mut_); 75*4d6fc14bSjoerg unsigned num_readers = __state_ & __n_readers_; 76*4d6fc14bSjoerg if (!(__state_ & __write_entered_) && num_readers != __n_readers_) 77*4d6fc14bSjoerg { 78*4d6fc14bSjoerg ++num_readers; 79*4d6fc14bSjoerg __state_ &= ~__n_readers_; 80*4d6fc14bSjoerg __state_ |= num_readers; 81*4d6fc14bSjoerg return true; 82*4d6fc14bSjoerg } 83*4d6fc14bSjoerg return false; 84*4d6fc14bSjoerg } 85*4d6fc14bSjoerg 86*4d6fc14bSjoerg void unlock_shared()87*4d6fc14bSjoerg__shared_mutex_base::unlock_shared() 88*4d6fc14bSjoerg { 89*4d6fc14bSjoerg lock_guard<mutex> _(__mut_); 90*4d6fc14bSjoerg unsigned num_readers = (__state_ & __n_readers_) - 1; 91*4d6fc14bSjoerg __state_ &= ~__n_readers_; 92*4d6fc14bSjoerg __state_ |= num_readers; 93*4d6fc14bSjoerg if (__state_ & __write_entered_) 94*4d6fc14bSjoerg { 95*4d6fc14bSjoerg if (num_readers == 0) 96*4d6fc14bSjoerg __gate2_.notify_one(); 97*4d6fc14bSjoerg } 98*4d6fc14bSjoerg else 99*4d6fc14bSjoerg { 100*4d6fc14bSjoerg if (num_readers == __n_readers_ - 1) 101*4d6fc14bSjoerg __gate1_.notify_one(); 102*4d6fc14bSjoerg } 103*4d6fc14bSjoerg } 104*4d6fc14bSjoerg 105*4d6fc14bSjoerg 106*4d6fc14bSjoerg // Shared Timed Mutex 107*4d6fc14bSjoerg // These routines are here for ABI stability shared_timed_mutex()108*4d6fc14bSjoergshared_timed_mutex::shared_timed_mutex() : __base() {} lock()109*4d6fc14bSjoergvoid shared_timed_mutex::lock() { return __base.lock(); } try_lock()110*4d6fc14bSjoergbool shared_timed_mutex::try_lock() { return __base.try_lock(); } unlock()111*4d6fc14bSjoergvoid shared_timed_mutex::unlock() { return __base.unlock(); } lock_shared()112*4d6fc14bSjoergvoid shared_timed_mutex::lock_shared() { return __base.lock_shared(); } try_lock_shared()113*4d6fc14bSjoergbool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); } unlock_shared()114*4d6fc14bSjoergvoid shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); } 115*4d6fc14bSjoerg 116*4d6fc14bSjoerg _LIBCPP_END_NAMESPACE_STD 117*4d6fc14bSjoerg 118*4d6fc14bSjoerg #endif // !_LIBCPP_HAS_NO_THREADS 119