@@ -75,31 +75,36 @@ impl RwLock {
75
75
76
76
#[ inline]
77
77
pub unsafe fn write ( & self ) {
78
- if let Err ( s) = self
79
- . state
80
- . fetch_update ( Acquire , Relaxed , |s| ( readers ( s) == 0 ) . then ( || s + WRITE_LOCKED ) )
81
- {
82
- self . write_contended ( s) ;
78
+ if !self . try_write ( ) {
79
+ self . write_contended ( ) ;
83
80
}
84
81
}
85
82
86
83
#[ inline]
87
84
pub unsafe fn read_unlock ( & self ) {
88
- if self . state . fetch_sub ( READ_LOCKED , Release ) == READ_LOCKED + WRITERS_WAITING {
85
+ let s = self . state . fetch_sub ( READ_LOCKED , Release ) ;
86
+
87
+ // It's impossible for readers to be waiting if it was read locked.
88
+ debug_assert ! ( !readers_waiting( s) ) ;
89
+
90
+ // Wake up a writer if we were the last reader and there's a writer waiting.
91
+ if s == READ_LOCKED + WRITERS_WAITING {
89
92
self . wake_after_read_unlock ( ) ;
90
93
}
91
94
}
92
95
93
96
#[ inline]
94
97
pub unsafe fn write_unlock ( & self ) {
95
98
if let Err ( e) = self . state . compare_exchange ( WRITE_LOCKED , 0 , Release , Relaxed ) {
99
+ // Readers or writers (or both) are waiting.
96
100
self . write_unlock_contended ( e) ;
97
101
}
98
102
}
99
103
100
104
#[ cold]
101
105
fn read_contended ( & self , mut state : i32 ) {
102
106
loop {
107
+ // If we can lock it, lock it.
103
108
if read_lockable ( state) {
104
109
match self . state . compare_exchange ( state, state + READ_LOCKED , Acquire , Relaxed ) {
105
110
Ok ( _) => return , // Locked!
@@ -110,6 +115,7 @@ impl RwLock {
110
115
}
111
116
}
112
117
118
+ // Check for overflow.
113
119
if readers ( state) == MAX_READERS {
114
120
panic ! ( "too many active read locks on RwLock" ) ;
115
121
}
0 commit comments