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