1*58b9f456SAndroid Build Coastguard Worker //===---------------------- shared_mutex.cpp ------------------------------===// 2*58b9f456SAndroid Build Coastguard Worker // 3*58b9f456SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*58b9f456SAndroid Build Coastguard Worker // 5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open 6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details. 7*58b9f456SAndroid Build Coastguard Worker // 8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*58b9f456SAndroid Build Coastguard Worker 10*58b9f456SAndroid Build Coastguard Worker #include "__config" 11*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_HAS_NO_THREADS 12*58b9f456SAndroid Build Coastguard Worker 13*58b9f456SAndroid Build Coastguard Worker #include "shared_mutex" 14*58b9f456SAndroid Build Coastguard Worker 15*58b9f456SAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD 16*58b9f456SAndroid Build Coastguard Worker 17*58b9f456SAndroid Build Coastguard Worker // Shared Mutex Base __shared_mutex_base()18*58b9f456SAndroid Build Coastguard Worker__shared_mutex_base::__shared_mutex_base() 19*58b9f456SAndroid Build Coastguard Worker : __state_(0) 20*58b9f456SAndroid Build Coastguard Worker { 21*58b9f456SAndroid Build Coastguard Worker } 22*58b9f456SAndroid Build Coastguard Worker 23*58b9f456SAndroid Build Coastguard Worker // Exclusive ownership 24*58b9f456SAndroid Build Coastguard Worker 25*58b9f456SAndroid Build Coastguard Worker void lock()26*58b9f456SAndroid Build Coastguard Worker__shared_mutex_base::lock() 27*58b9f456SAndroid Build Coastguard Worker { 28*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__mut_); 29*58b9f456SAndroid Build Coastguard Worker while (__state_ & __write_entered_) 30*58b9f456SAndroid Build Coastguard Worker __gate1_.wait(lk); 31*58b9f456SAndroid Build Coastguard Worker __state_ |= __write_entered_; 32*58b9f456SAndroid Build Coastguard Worker while (__state_ & __n_readers_) 33*58b9f456SAndroid Build Coastguard Worker __gate2_.wait(lk); 34*58b9f456SAndroid Build Coastguard Worker } 35*58b9f456SAndroid Build Coastguard Worker 36*58b9f456SAndroid Build Coastguard Worker bool try_lock()37*58b9f456SAndroid Build Coastguard Worker__shared_mutex_base::try_lock() 38*58b9f456SAndroid Build Coastguard Worker { 39*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__mut_); 40*58b9f456SAndroid Build Coastguard Worker if (__state_ == 0) 41*58b9f456SAndroid Build Coastguard Worker { 42*58b9f456SAndroid Build Coastguard Worker __state_ = __write_entered_; 43*58b9f456SAndroid Build Coastguard Worker return true; 44*58b9f456SAndroid Build Coastguard Worker } 45*58b9f456SAndroid Build Coastguard Worker return false; 46*58b9f456SAndroid Build Coastguard Worker } 47*58b9f456SAndroid Build Coastguard Worker 48*58b9f456SAndroid Build Coastguard Worker void unlock()49*58b9f456SAndroid Build Coastguard Worker__shared_mutex_base::unlock() 50*58b9f456SAndroid Build Coastguard Worker { 51*58b9f456SAndroid Build Coastguard Worker lock_guard<mutex> _(__mut_); 52*58b9f456SAndroid Build Coastguard Worker __state_ = 0; 53*58b9f456SAndroid Build Coastguard Worker __gate1_.notify_all(); 54*58b9f456SAndroid Build Coastguard Worker } 55*58b9f456SAndroid Build Coastguard Worker 56*58b9f456SAndroid Build Coastguard Worker // Shared ownership 57*58b9f456SAndroid Build Coastguard Worker 58*58b9f456SAndroid Build Coastguard Worker void lock_shared()59*58b9f456SAndroid Build Coastguard Worker__shared_mutex_base::lock_shared() 60*58b9f456SAndroid Build Coastguard Worker { 61*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__mut_); 62*58b9f456SAndroid Build Coastguard Worker while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) 63*58b9f456SAndroid Build Coastguard Worker __gate1_.wait(lk); 64*58b9f456SAndroid Build Coastguard Worker unsigned num_readers = (__state_ & __n_readers_) + 1; 65*58b9f456SAndroid Build Coastguard Worker __state_ &= ~__n_readers_; 66*58b9f456SAndroid Build Coastguard Worker __state_ |= num_readers; 67*58b9f456SAndroid Build Coastguard Worker } 68*58b9f456SAndroid Build Coastguard Worker 69*58b9f456SAndroid Build Coastguard Worker bool try_lock_shared()70*58b9f456SAndroid Build Coastguard Worker__shared_mutex_base::try_lock_shared() 71*58b9f456SAndroid Build Coastguard Worker { 72*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__mut_); 73*58b9f456SAndroid Build Coastguard Worker unsigned num_readers = __state_ & __n_readers_; 74*58b9f456SAndroid Build Coastguard Worker if (!(__state_ & __write_entered_) && num_readers != __n_readers_) 75*58b9f456SAndroid Build Coastguard Worker { 76*58b9f456SAndroid Build Coastguard Worker ++num_readers; 77*58b9f456SAndroid Build Coastguard Worker __state_ &= ~__n_readers_; 78*58b9f456SAndroid Build Coastguard Worker __state_ |= num_readers; 79*58b9f456SAndroid Build Coastguard Worker return true; 80*58b9f456SAndroid Build Coastguard Worker } 81*58b9f456SAndroid Build Coastguard Worker return false; 82*58b9f456SAndroid Build Coastguard Worker } 83*58b9f456SAndroid Build Coastguard Worker 84*58b9f456SAndroid Build Coastguard Worker void unlock_shared()85*58b9f456SAndroid Build Coastguard Worker__shared_mutex_base::unlock_shared() 86*58b9f456SAndroid Build Coastguard Worker { 87*58b9f456SAndroid Build Coastguard Worker lock_guard<mutex> _(__mut_); 88*58b9f456SAndroid Build Coastguard Worker unsigned num_readers = (__state_ & __n_readers_) - 1; 89*58b9f456SAndroid Build Coastguard Worker __state_ &= ~__n_readers_; 90*58b9f456SAndroid Build Coastguard Worker __state_ |= num_readers; 91*58b9f456SAndroid Build Coastguard Worker if (__state_ & __write_entered_) 92*58b9f456SAndroid Build Coastguard Worker { 93*58b9f456SAndroid Build Coastguard Worker if (num_readers == 0) 94*58b9f456SAndroid Build Coastguard Worker __gate2_.notify_one(); 95*58b9f456SAndroid Build Coastguard Worker } 96*58b9f456SAndroid Build Coastguard Worker else 97*58b9f456SAndroid Build Coastguard Worker { 98*58b9f456SAndroid Build Coastguard Worker if (num_readers == __n_readers_ - 1) 99*58b9f456SAndroid Build Coastguard Worker __gate1_.notify_one(); 100*58b9f456SAndroid Build Coastguard Worker } 101*58b9f456SAndroid Build Coastguard Worker } 102*58b9f456SAndroid Build Coastguard Worker 103*58b9f456SAndroid Build Coastguard Worker 104*58b9f456SAndroid Build Coastguard Worker // Shared Timed Mutex 105*58b9f456SAndroid Build Coastguard Worker // These routines are here for ABI stability shared_timed_mutex()106*58b9f456SAndroid Build Coastguard Workershared_timed_mutex::shared_timed_mutex() : __base() {} lock()107*58b9f456SAndroid Build Coastguard Workervoid shared_timed_mutex::lock() { return __base.lock(); } try_lock()108*58b9f456SAndroid Build Coastguard Workerbool shared_timed_mutex::try_lock() { return __base.try_lock(); } unlock()109*58b9f456SAndroid Build Coastguard Workervoid shared_timed_mutex::unlock() { return __base.unlock(); } lock_shared()110*58b9f456SAndroid Build Coastguard Workervoid shared_timed_mutex::lock_shared() { return __base.lock_shared(); } try_lock_shared()111*58b9f456SAndroid Build Coastguard Workerbool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); } unlock_shared()112*58b9f456SAndroid Build Coastguard Workervoid shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); } 113*58b9f456SAndroid Build Coastguard Worker 114*58b9f456SAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD 115*58b9f456SAndroid Build Coastguard Worker 116*58b9f456SAndroid Build Coastguard Worker #endif // !_LIBCPP_HAS_NO_THREADS 117