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