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