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