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