100 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include <mutex>10#include <shared_mutex>11#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)12# pragma comment(lib, "pthread")13#endif14 15_LIBCPP_BEGIN_NAMESPACE_STD16 17// Shared Mutex Base18__shared_mutex_base::__shared_mutex_base() : __state_(0) {}19 20// Exclusive ownership21 22void __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 31bool __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 40void __shared_mutex_base::unlock() {41 {42 lock_guard<mutex> _(__mut_);43 __state_ = 0;44 }45 __gate1_.notify_all();46}47 48// Shared ownership49 50void __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 59bool __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 71void __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 Mutex90// These routines are here for ABI stability91shared_timed_mutex::shared_timed_mutex() : __base_() {}92void shared_timed_mutex::lock() { return __base_.lock(); }93bool shared_timed_mutex::try_lock() { return __base_.try_lock(); }94void shared_timed_mutex::unlock() { return __base_.unlock(); }95void shared_timed_mutex::lock_shared() { return __base_.lock_shared(); }96bool shared_timed_mutex::try_lock_shared() { return __base_.try_lock_shared(); }97void shared_timed_mutex::unlock_shared() { return __base_.unlock_shared(); }98 99_LIBCPP_END_NAMESPACE_STD100