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