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