@@ -3,16 +3,14 @@ use crate::marker;
3
3
use crate :: ops:: Deref ;
4
4
use crate :: panic:: { RefUnwindSafe , UnwindSafe } ;
5
5
use crate :: sys:: mutex as sys;
6
- use crate :: sys_common:: poison:: { self , LockResult , TryLockError , TryLockResult } ;
7
6
8
7
/// A re-entrant mutual exclusion
9
8
///
10
9
/// This mutex will block *other* threads waiting for the lock to become
11
10
/// available. The thread which has already locked the mutex can lock it
12
11
/// multiple times without blocking, preventing a common source of deadlocks.
13
12
pub struct ReentrantMutex < T > {
14
- inner : Box < sys:: ReentrantMutex > ,
15
- poison : poison:: Flag ,
13
+ inner : sys:: ReentrantMutex ,
16
14
data : T ,
17
15
}
18
16
@@ -39,23 +37,30 @@ pub struct ReentrantMutexGuard<'a, T: 'a> {
39
37
// funny underscores due to how Deref currently works (it disregards field
40
38
// privacy).
41
39
__lock : & ' a ReentrantMutex < T > ,
42
- __poison : poison:: Guard ,
43
40
}
44
41
45
42
impl < T > !marker:: Send for ReentrantMutexGuard < ' _ , T > { }
46
43
47
44
impl < T > ReentrantMutex < T > {
48
45
/// Creates a new reentrant mutex in an unlocked state.
49
- pub fn new ( t : T ) -> ReentrantMutex < T > {
50
- unsafe {
51
- let mut mutex = ReentrantMutex {
52
- inner : box sys:: ReentrantMutex :: uninitialized ( ) ,
53
- poison : poison:: Flag :: new ( ) ,
54
- data : t,
55
- } ;
56
- mutex. inner . init ( ) ;
57
- mutex
58
- }
46
+ ///
47
+ /// # Unsafety
48
+ ///
49
+ /// This function is unsafe because it is required that `init` is called
50
+ /// once this mutex is in its final resting place, and only then are the
51
+ /// lock/unlock methods safe.
52
+ pub const unsafe fn new ( t : T ) -> ReentrantMutex < T > {
53
+ ReentrantMutex { inner : sys:: ReentrantMutex :: uninitialized ( ) , data : t }
54
+ }
55
+
56
+ /// Initializes this mutex so it's ready for use.
57
+ ///
58
+ /// # Unsafety
59
+ ///
60
+ /// Unsafe to call more than once, and must be called after this will no
61
+ /// longer move in memory.
62
+ pub unsafe fn init ( & self ) {
63
+ self . inner . init ( ) ;
59
64
}
60
65
61
66
/// Acquires a mutex, blocking the current thread until it is able to do so.
@@ -70,7 +75,7 @@ impl<T> ReentrantMutex<T> {
70
75
/// If another user of this mutex panicked while holding the mutex, then
71
76
/// this call will return failure if the mutex would otherwise be
72
77
/// acquired.
73
- pub fn lock ( & self ) -> LockResult < ReentrantMutexGuard < ' _ , T > > {
78
+ pub fn lock ( & self ) -> ReentrantMutexGuard < ' _ , T > {
74
79
unsafe { self . inner . lock ( ) }
75
80
ReentrantMutexGuard :: new ( & self )
76
81
}
@@ -87,12 +92,8 @@ impl<T> ReentrantMutex<T> {
87
92
/// If another user of this mutex panicked while holding the mutex, then
88
93
/// this call will return failure if the mutex would otherwise be
89
94
/// acquired.
90
- pub fn try_lock ( & self ) -> TryLockResult < ReentrantMutexGuard < ' _ , T > > {
91
- if unsafe { self . inner . try_lock ( ) } {
92
- Ok ( ReentrantMutexGuard :: new ( & self ) ?)
93
- } else {
94
- Err ( TryLockError :: WouldBlock )
95
- }
95
+ pub fn try_lock ( & self ) -> Option < ReentrantMutexGuard < ' _ , T > > {
96
+ if unsafe { self . inner . try_lock ( ) } { Some ( ReentrantMutexGuard :: new ( & self ) ) } else { None }
96
97
}
97
98
}
98
99
@@ -108,11 +109,8 @@ impl<T> Drop for ReentrantMutex<T> {
108
109
impl < T : fmt:: Debug + ' static > fmt:: Debug for ReentrantMutex < T > {
109
110
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
110
111
match self . try_lock ( ) {
111
- Ok ( guard) => f. debug_struct ( "ReentrantMutex" ) . field ( "data" , & * guard) . finish ( ) ,
112
- Err ( TryLockError :: Poisoned ( err) ) => {
113
- f. debug_struct ( "ReentrantMutex" ) . field ( "data" , & * * err. get_ref ( ) ) . finish ( )
114
- }
115
- Err ( TryLockError :: WouldBlock ) => {
112
+ Some ( guard) => f. debug_struct ( "ReentrantMutex" ) . field ( "data" , & * guard) . finish ( ) ,
113
+ None => {
116
114
struct LockedPlaceholder ;
117
115
impl fmt:: Debug for LockedPlaceholder {
118
116
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
@@ -127,11 +125,8 @@ impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
127
125
}
128
126
129
127
impl < ' mutex , T > ReentrantMutexGuard < ' mutex , T > {
130
- fn new ( lock : & ' mutex ReentrantMutex < T > ) -> LockResult < ReentrantMutexGuard < ' mutex , T > > {
131
- poison:: map_result ( lock. poison . borrow ( ) , |guard| ReentrantMutexGuard {
132
- __lock : lock,
133
- __poison : guard,
134
- } )
128
+ fn new ( lock : & ' mutex ReentrantMutex < T > ) -> ReentrantMutexGuard < ' mutex , T > {
129
+ ReentrantMutexGuard { __lock : lock }
135
130
}
136
131
}
137
132
@@ -147,7 +142,6 @@ impl<T> Drop for ReentrantMutexGuard<'_, T> {
147
142
#[ inline]
148
143
fn drop ( & mut self ) {
149
144
unsafe {
150
- self . __lock . poison . done ( & self . __poison ) ;
151
145
self . __lock . inner . unlock ( ) ;
152
146
}
153
147
}
@@ -162,13 +156,17 @@ mod tests {
162
156
163
157
#[ test]
164
158
fn smoke ( ) {
165
- let m = ReentrantMutex :: new ( ( ) ) ;
159
+ let m = unsafe {
160
+ let m = ReentrantMutex :: new ( ( ) ) ;
161
+ m. init ( ) ;
162
+ m
163
+ } ;
166
164
{
167
- let a = m. lock ( ) . unwrap ( ) ;
165
+ let a = m. lock ( ) ;
168
166
{
169
- let b = m. lock ( ) . unwrap ( ) ;
167
+ let b = m. lock ( ) ;
170
168
{
171
- let c = m. lock ( ) . unwrap ( ) ;
169
+ let c = m. lock ( ) ;
172
170
assert_eq ! ( * c, ( ) ) ;
173
171
}
174
172
assert_eq ! ( * b, ( ) ) ;
@@ -179,15 +177,19 @@ mod tests {
179
177
180
178
#[ test]
181
179
fn is_mutex ( ) {
182
- let m = Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( 0 ) ) ) ;
180
+ let m = unsafe {
181
+ let m = Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( 0 ) ) ) ;
182
+ m. init ( ) ;
183
+ m
184
+ } ;
183
185
let m2 = m. clone ( ) ;
184
- let lock = m. lock ( ) . unwrap ( ) ;
186
+ let lock = m. lock ( ) ;
185
187
let child = thread:: spawn ( move || {
186
- let lock = m2. lock ( ) . unwrap ( ) ;
188
+ let lock = m2. lock ( ) ;
187
189
assert_eq ! ( * lock. borrow( ) , 4950 ) ;
188
190
} ) ;
189
191
for i in 0 ..100 {
190
- let lock = m. lock ( ) . unwrap ( ) ;
192
+ let lock = m. lock ( ) ;
191
193
* lock. borrow_mut ( ) += i;
192
194
}
193
195
drop ( lock) ;
@@ -196,17 +198,21 @@ mod tests {
196
198
197
199
#[ test]
198
200
fn trylock_works ( ) {
199
- let m = Arc :: new ( ReentrantMutex :: new ( ( ) ) ) ;
201
+ let m = unsafe {
202
+ let m = Arc :: new ( ReentrantMutex :: new ( ( ) ) ) ;
203
+ m. init ( ) ;
204
+ m
205
+ } ;
200
206
let m2 = m. clone ( ) ;
201
- let _lock = m. try_lock ( ) . unwrap ( ) ;
202
- let _lock2 = m. try_lock ( ) . unwrap ( ) ;
207
+ let _lock = m. try_lock ( ) ;
208
+ let _lock2 = m. try_lock ( ) ;
203
209
thread:: spawn ( move || {
204
210
let lock = m2. try_lock ( ) ;
205
- assert ! ( lock. is_err ( ) ) ;
211
+ assert ! ( lock. is_none ( ) ) ;
206
212
} )
207
213
. join ( )
208
214
. unwrap ( ) ;
209
- let _lock3 = m. try_lock ( ) . unwrap ( ) ;
215
+ let _lock3 = m. try_lock ( ) ;
210
216
}
211
217
212
218
pub struct Answer < ' a > ( pub ReentrantMutexGuard < ' a , RefCell < u32 > > ) ;
@@ -215,22 +221,4 @@ mod tests {
215
221
* self . 0 . borrow_mut ( ) = 42 ;
216
222
}
217
223
}
218
-
219
- #[ test]
220
- fn poison_works ( ) {
221
- let m = Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( 0 ) ) ) ;
222
- let mc = m. clone ( ) ;
223
- let result = thread:: spawn ( move || {
224
- let lock = mc. lock ( ) . unwrap ( ) ;
225
- * lock. borrow_mut ( ) = 1 ;
226
- let lock2 = mc. lock ( ) . unwrap ( ) ;
227
- * lock. borrow_mut ( ) = 2 ;
228
- let _answer = Answer ( lock2) ;
229
- panic ! ( "What the answer to my lifetimes dilemma is?" ) ;
230
- } )
231
- . join ( ) ;
232
- assert ! ( result. is_err( ) ) ;
233
- let r = m. lock ( ) . err ( ) . unwrap ( ) . into_inner ( ) ;
234
- assert_eq ! ( * r. borrow( ) , 42 ) ;
235
- }
236
224
}
0 commit comments