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