1 //===---------------------- shared_mutex.cpp ------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #define _LIBCPP_BUILDING_SHARED_MUTEX
11 #include "shared_mutex"
12 
13 #if !_LIBCPP_SINGLE_THREADED
14 
15 _LIBCPP_BEGIN_NAMESPACE_STD
16 
shared_timed_mutex()17 shared_timed_mutex::shared_timed_mutex()
18     : __state_(0)
19 {
20 }
21 
22 // Exclusive ownership
23 
24 void
lock()25 shared_timed_mutex::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
try_lock()36 shared_timed_mutex::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
unlock()48 shared_timed_mutex::unlock()
49 {
50     lock_guard<mutex> _(__mut_);
51     __state_ = 0;
52     __gate1_.notify_all();
53 }
54 
55 // Shared ownership
56 
57 void
lock_shared()58 shared_timed_mutex::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
try_lock_shared()69 shared_timed_mutex::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
unlock_shared()84 shared_timed_mutex::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 _LIBCPP_END_NAMESPACE_STD
104 
105 #endif // !_LIBCPP_SINGLE_THREADED
106 
107 
108