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