1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
2ead6f169SHoward Hinnant //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ead6f169SHoward Hinnant //
7ead6f169SHoward Hinnant //===----------------------------------------------------------------------===//
8ead6f169SHoward Hinnant 
9*bbb0f2c7SArthur O'Dwyer #include <__config>
10*bbb0f2c7SArthur O'Dwyer 
11b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
12b3fcc67fSJonathan Roelofs 
13*bbb0f2c7SArthur O'Dwyer #include <shared_mutex>
14a9b5fff5SMichał Górny #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
15996e62eeSPetr Hosek #  pragma comment(lib, "pthread")
16996e62eeSPetr Hosek #endif
17ead6f169SHoward Hinnant 
18ead6f169SHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD
19ead6f169SHoward Hinnant 
20f69ae471SMarshall Clow // Shared Mutex Base
__shared_mutex_base()21f69ae471SMarshall Clow __shared_mutex_base::__shared_mutex_base()
22ead6f169SHoward Hinnant     : __state_(0)
23ead6f169SHoward Hinnant {
24ead6f169SHoward Hinnant }
25ead6f169SHoward Hinnant 
26ead6f169SHoward Hinnant // Exclusive ownership
27ead6f169SHoward Hinnant 
28ead6f169SHoward Hinnant void
lock()29f69ae471SMarshall Clow __shared_mutex_base::lock()
30ead6f169SHoward Hinnant {
31ead6f169SHoward Hinnant     unique_lock<mutex> lk(__mut_);
32ead6f169SHoward Hinnant     while (__state_ & __write_entered_)
33ead6f169SHoward Hinnant         __gate1_.wait(lk);
34ead6f169SHoward Hinnant     __state_ |= __write_entered_;
35ead6f169SHoward Hinnant     while (__state_ & __n_readers_)
36ead6f169SHoward Hinnant         __gate2_.wait(lk);
37ead6f169SHoward Hinnant }
38ead6f169SHoward Hinnant 
39ead6f169SHoward Hinnant bool
try_lock()40f69ae471SMarshall Clow __shared_mutex_base::try_lock()
41ead6f169SHoward Hinnant {
42ead6f169SHoward Hinnant     unique_lock<mutex> lk(__mut_);
43ead6f169SHoward Hinnant     if (__state_ == 0)
44ead6f169SHoward Hinnant     {
45ead6f169SHoward Hinnant         __state_ = __write_entered_;
46ead6f169SHoward Hinnant         return true;
47ead6f169SHoward Hinnant     }
48ead6f169SHoward Hinnant     return false;
49ead6f169SHoward Hinnant }
50ead6f169SHoward Hinnant 
51ead6f169SHoward Hinnant void
unlock()52f69ae471SMarshall Clow __shared_mutex_base::unlock()
53ead6f169SHoward Hinnant {
54ead6f169SHoward Hinnant     lock_guard<mutex> _(__mut_);
55ead6f169SHoward Hinnant     __state_ = 0;
56ead6f169SHoward Hinnant     __gate1_.notify_all();
57ead6f169SHoward Hinnant }
58ead6f169SHoward Hinnant 
59ead6f169SHoward Hinnant // Shared ownership
60ead6f169SHoward Hinnant 
61ead6f169SHoward Hinnant void
lock_shared()62f69ae471SMarshall Clow __shared_mutex_base::lock_shared()
63ead6f169SHoward Hinnant {
64ead6f169SHoward Hinnant     unique_lock<mutex> lk(__mut_);
65ead6f169SHoward Hinnant     while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
66ead6f169SHoward Hinnant         __gate1_.wait(lk);
67ead6f169SHoward Hinnant     unsigned num_readers = (__state_ & __n_readers_) + 1;
68ead6f169SHoward Hinnant     __state_ &= ~__n_readers_;
69ead6f169SHoward Hinnant     __state_ |= num_readers;
70ead6f169SHoward Hinnant }
71ead6f169SHoward Hinnant 
72ead6f169SHoward Hinnant bool
try_lock_shared()73f69ae471SMarshall Clow __shared_mutex_base::try_lock_shared()
74ead6f169SHoward Hinnant {
75ead6f169SHoward Hinnant     unique_lock<mutex> lk(__mut_);
76ead6f169SHoward Hinnant     unsigned num_readers = __state_ & __n_readers_;
77ead6f169SHoward Hinnant     if (!(__state_ & __write_entered_) && num_readers != __n_readers_)
78ead6f169SHoward Hinnant     {
79ead6f169SHoward Hinnant         ++num_readers;
80ead6f169SHoward Hinnant         __state_ &= ~__n_readers_;
81ead6f169SHoward Hinnant         __state_ |= num_readers;
82ead6f169SHoward Hinnant         return true;
83ead6f169SHoward Hinnant     }
84ead6f169SHoward Hinnant     return false;
85ead6f169SHoward Hinnant }
86ead6f169SHoward Hinnant 
87ead6f169SHoward Hinnant void
unlock_shared()88f69ae471SMarshall Clow __shared_mutex_base::unlock_shared()
89ead6f169SHoward Hinnant {
90ead6f169SHoward Hinnant     lock_guard<mutex> _(__mut_);
91ead6f169SHoward Hinnant     unsigned num_readers = (__state_ & __n_readers_) - 1;
92ead6f169SHoward Hinnant     __state_ &= ~__n_readers_;
93ead6f169SHoward Hinnant     __state_ |= num_readers;
94ead6f169SHoward Hinnant     if (__state_ & __write_entered_)
95ead6f169SHoward Hinnant     {
96ead6f169SHoward Hinnant         if (num_readers == 0)
97ead6f169SHoward Hinnant             __gate2_.notify_one();
98ead6f169SHoward Hinnant     }
99ead6f169SHoward Hinnant     else
100ead6f169SHoward Hinnant     {
101ead6f169SHoward Hinnant         if (num_readers == __n_readers_ - 1)
102ead6f169SHoward Hinnant             __gate1_.notify_one();
103ead6f169SHoward Hinnant     }
104ead6f169SHoward Hinnant }
105ead6f169SHoward Hinnant 
106ead6f169SHoward Hinnant 
107f69ae471SMarshall Clow // Shared Timed Mutex
108f69ae471SMarshall Clow // These routines are here for ABI stability
shared_timed_mutex()109f69ae471SMarshall Clow shared_timed_mutex::shared_timed_mutex() : __base() {}
lock()110f69ae471SMarshall Clow void shared_timed_mutex::lock()     { return __base.lock(); }
try_lock()111f69ae471SMarshall Clow bool shared_timed_mutex::try_lock() { return __base.try_lock(); }
unlock()112f69ae471SMarshall Clow void shared_timed_mutex::unlock()   { return __base.unlock(); }
lock_shared()113f69ae471SMarshall Clow void shared_timed_mutex::lock_shared() { return __base.lock_shared(); }
try_lock_shared()114f69ae471SMarshall Clow bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); }
unlock_shared()115f69ae471SMarshall Clow void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); }
116f69ae471SMarshall Clow 
117ead6f169SHoward Hinnant _LIBCPP_END_NAMESPACE_STD
118b3fcc67fSJonathan Roelofs 
119b3fcc67fSJonathan Roelofs #endif // !_LIBCPP_HAS_NO_THREADS
120