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