1
+ use crate :: fmt:: Debug ;
2
+ use crate :: ops:: FnMut ;
3
+ use crate :: panic:: { self , AssertUnwindSafe } ;
1
4
use crate :: sync:: atomic:: { AtomicUsize , Ordering } ;
2
5
use crate :: sync:: mpsc:: channel;
3
6
use crate :: sync:: { Arc , Condvar , MappedMutexGuard , Mutex , MutexGuard , TryLockError } ;
4
- use crate :: thread;
7
+ use crate :: { hint , mem , thread} ;
5
8
6
9
struct Packet < T > ( Arc < ( Mutex < T > , Condvar ) > ) ;
7
10
8
11
#[ derive( Eq , PartialEq , Debug ) ]
9
12
struct NonCopy ( i32 ) ;
10
13
14
+ #[ derive( Eq , PartialEq , Debug ) ]
15
+ struct NonCopyNeedsDrop ( i32 ) ;
16
+
17
+ impl Drop for NonCopyNeedsDrop {
18
+ fn drop ( & mut self ) {
19
+ hint:: black_box ( ( ) ) ;
20
+ }
21
+ }
22
+
23
+ #[ test]
24
+ fn test_needs_drop ( ) {
25
+ assert ! ( !mem:: needs_drop:: <NonCopy >( ) ) ;
26
+ assert ! ( mem:: needs_drop:: <NonCopyNeedsDrop >( ) ) ;
27
+ }
28
+
29
+ #[ derive( Clone , Eq , PartialEq , Debug ) ]
30
+ struct Cloneable ( i32 ) ;
31
+
11
32
#[ test]
12
33
fn smoke ( ) {
13
34
let m = Mutex :: new ( ( ) ) ;
@@ -57,6 +78,21 @@ fn try_lock() {
57
78
* m. try_lock ( ) . unwrap ( ) = ( ) ;
58
79
}
59
80
81
+ fn new_poisoned_mutex < T > ( value : T ) -> Mutex < T > {
82
+ let mutex = Mutex :: new ( value) ;
83
+
84
+ let catch_unwind_result = panic:: catch_unwind ( AssertUnwindSafe ( || {
85
+ let _guard = mutex. lock ( ) . unwrap ( ) ;
86
+
87
+ panic ! ( "test panic to poison mutex" ) ;
88
+ } ) ) ;
89
+
90
+ assert ! ( catch_unwind_result. is_err( ) ) ;
91
+ assert ! ( mutex. is_poisoned( ) ) ;
92
+
93
+ mutex
94
+ }
95
+
60
96
#[ test]
61
97
fn test_into_inner ( ) {
62
98
let m = Mutex :: new ( NonCopy ( 10 ) ) ;
@@ -83,21 +119,31 @@ fn test_into_inner_drop() {
83
119
84
120
#[ test]
85
121
fn test_into_inner_poison ( ) {
86
- let m = Arc :: new ( Mutex :: new ( NonCopy ( 10 ) ) ) ;
87
- let m2 = m. clone ( ) ;
88
- let _ = thread:: spawn ( move || {
89
- let _lock = m2. lock ( ) . unwrap ( ) ;
90
- panic ! ( "test panic in inner thread to poison mutex" ) ;
91
- } )
92
- . join ( ) ;
122
+ let m = new_poisoned_mutex ( NonCopy ( 10 ) ) ;
93
123
94
- assert ! ( m. is_poisoned( ) ) ;
95
- match Arc :: try_unwrap ( m) . unwrap ( ) . into_inner ( ) {
124
+ match m. into_inner ( ) {
96
125
Err ( e) => assert_eq ! ( e. into_inner( ) , NonCopy ( 10 ) ) ,
97
126
Ok ( x) => panic ! ( "into_inner of poisoned Mutex is Ok: {x:?}" ) ,
98
127
}
99
128
}
100
129
130
+ #[ test]
131
+ fn test_get_cloned ( ) {
132
+ let m = Mutex :: new ( Cloneable ( 10 ) ) ;
133
+
134
+ assert_eq ! ( m. get_cloned( ) . unwrap( ) , Cloneable ( 10 ) ) ;
135
+ }
136
+
137
+ #[ test]
138
+ fn test_get_cloned_poison ( ) {
139
+ let m = new_poisoned_mutex ( Cloneable ( 10 ) ) ;
140
+
141
+ match m. get_cloned ( ) {
142
+ Err ( e) => assert_eq ! ( e. into_inner( ) , ( ) ) ,
143
+ Ok ( x) => panic ! ( "get of poisoned Mutex is Ok: {x:?}" ) ,
144
+ }
145
+ }
146
+
101
147
#[ test]
102
148
fn test_get_mut ( ) {
103
149
let mut m = Mutex :: new ( NonCopy ( 10 ) ) ;
@@ -107,21 +153,90 @@ fn test_get_mut() {
107
153
108
154
#[ test]
109
155
fn test_get_mut_poison ( ) {
110
- let m = Arc :: new ( Mutex :: new ( NonCopy ( 10 ) ) ) ;
111
- let m2 = m. clone ( ) ;
112
- let _ = thread:: spawn ( move || {
113
- let _lock = m2. lock ( ) . unwrap ( ) ;
114
- panic ! ( "test panic in inner thread to poison mutex" ) ;
115
- } )
116
- . join ( ) ;
156
+ let mut m = new_poisoned_mutex ( NonCopy ( 10 ) ) ;
117
157
118
- assert ! ( m. is_poisoned( ) ) ;
119
- match Arc :: try_unwrap ( m) . unwrap ( ) . get_mut ( ) {
158
+ match m. get_mut ( ) {
120
159
Err ( e) => assert_eq ! ( * e. into_inner( ) , NonCopy ( 10 ) ) ,
121
160
Ok ( x) => panic ! ( "get_mut of poisoned Mutex is Ok: {x:?}" ) ,
122
161
}
123
162
}
124
163
164
+ #[ test]
165
+ fn test_set ( ) {
166
+ fn inner < T > ( mut init : impl FnMut ( ) -> T , mut value : impl FnMut ( ) -> T )
167
+ where
168
+ T : Debug + Eq ,
169
+ {
170
+ let m = Mutex :: new ( init ( ) ) ;
171
+
172
+ assert_eq ! ( * m. lock( ) . unwrap( ) , init( ) ) ;
173
+ m. set ( value ( ) ) . unwrap ( ) ;
174
+ assert_eq ! ( * m. lock( ) . unwrap( ) , value( ) ) ;
175
+ }
176
+
177
+ inner ( || NonCopy ( 10 ) , || NonCopy ( 20 ) ) ;
178
+ inner ( || NonCopyNeedsDrop ( 10 ) , || NonCopyNeedsDrop ( 20 ) ) ;
179
+ }
180
+
181
+ #[ test]
182
+ fn test_set_poison ( ) {
183
+ fn inner < T > ( mut init : impl FnMut ( ) -> T , mut value : impl FnMut ( ) -> T )
184
+ where
185
+ T : Debug + Eq ,
186
+ {
187
+ let m = new_poisoned_mutex ( init ( ) ) ;
188
+
189
+ match m. set ( value ( ) ) {
190
+ Err ( e) => {
191
+ assert_eq ! ( e. into_inner( ) , value( ) ) ;
192
+ assert_eq ! ( m. into_inner( ) . unwrap_err( ) . into_inner( ) , init( ) ) ;
193
+ }
194
+ Ok ( x) => panic ! ( "set of poisoned Mutex is Ok: {x:?}" ) ,
195
+ }
196
+ }
197
+
198
+ inner ( || NonCopy ( 10 ) , || NonCopy ( 20 ) ) ;
199
+ inner ( || NonCopyNeedsDrop ( 10 ) , || NonCopyNeedsDrop ( 20 ) ) ;
200
+ }
201
+
202
+ #[ test]
203
+ fn test_replace ( ) {
204
+ fn inner < T > ( mut init : impl FnMut ( ) -> T , mut value : impl FnMut ( ) -> T )
205
+ where
206
+ T : Debug + Eq ,
207
+ {
208
+ let m = Mutex :: new ( init ( ) ) ;
209
+
210
+ assert_eq ! ( * m. lock( ) . unwrap( ) , init( ) ) ;
211
+ assert_eq ! ( m. replace( value( ) ) . unwrap( ) , init( ) ) ;
212
+ assert_eq ! ( * m. lock( ) . unwrap( ) , value( ) ) ;
213
+ }
214
+
215
+ inner ( || NonCopy ( 10 ) , || NonCopy ( 20 ) ) ;
216
+ inner ( || NonCopyNeedsDrop ( 10 ) , || NonCopyNeedsDrop ( 20 ) ) ;
217
+ }
218
+
219
+ #[ test]
220
+ fn test_replace_poison ( ) {
221
+ fn inner < T > ( mut init : impl FnMut ( ) -> T , mut value : impl FnMut ( ) -> T )
222
+ where
223
+ T : Debug + Eq ,
224
+ {
225
+ let m = new_poisoned_mutex ( init ( ) ) ;
226
+
227
+ match m. replace ( value ( ) ) {
228
+ Err ( e) => {
229
+ assert_eq ! ( e. into_inner( ) , value( ) ) ;
230
+ assert_eq ! ( m. into_inner( ) . unwrap_err( ) . into_inner( ) , init( ) ) ;
231
+ }
232
+ Ok ( x) => panic ! ( "replace of poisoned Mutex is Ok: {x:?}" ) ,
233
+ }
234
+ }
235
+
236
+ inner ( || NonCopy ( 10 ) , || NonCopy ( 20 ) ) ;
237
+ inner ( || NonCopyNeedsDrop ( 10 ) , || NonCopyNeedsDrop ( 20 ) ) ;
238
+ }
239
+
125
240
#[ test]
126
241
fn test_mutex_arc_condvar ( ) {
127
242
let packet = Packet ( Arc :: new ( ( Mutex :: new ( false ) , Condvar :: new ( ) ) ) ) ;
@@ -269,7 +384,7 @@ fn test_mapping_mapped_guard() {
269
384
fn panic_while_mapping_unlocked_poison ( ) {
270
385
let lock = Mutex :: new ( ( ) ) ;
271
386
272
- let _ = crate :: panic:: catch_unwind ( || {
387
+ let _ = panic:: catch_unwind ( || {
273
388
let guard = lock. lock ( ) . unwrap ( ) ;
274
389
let _guard = MutexGuard :: map :: < ( ) , _ > ( guard, |_| panic ! ( ) ) ;
275
390
} ) ;
@@ -282,7 +397,7 @@ fn panic_while_mapping_unlocked_poison() {
282
397
Err ( TryLockError :: Poisoned ( _) ) => { }
283
398
}
284
399
285
- let _ = crate :: panic:: catch_unwind ( || {
400
+ let _ = panic:: catch_unwind ( || {
286
401
let guard = lock. lock ( ) . unwrap ( ) ;
287
402
let _guard = MutexGuard :: try_map :: < ( ) , _ > ( guard, |_| panic ! ( ) ) ;
288
403
} ) ;
@@ -295,7 +410,7 @@ fn panic_while_mapping_unlocked_poison() {
295
410
Err ( TryLockError :: Poisoned ( _) ) => { }
296
411
}
297
412
298
- let _ = crate :: panic:: catch_unwind ( || {
413
+ let _ = panic:: catch_unwind ( || {
299
414
let guard = lock. lock ( ) . unwrap ( ) ;
300
415
let guard = MutexGuard :: map :: < ( ) , _ > ( guard, |val| val) ;
301
416
let _guard = MappedMutexGuard :: map :: < ( ) , _ > ( guard, |_| panic ! ( ) ) ;
@@ -309,7 +424,7 @@ fn panic_while_mapping_unlocked_poison() {
309
424
Err ( TryLockError :: Poisoned ( _) ) => { }
310
425
}
311
426
312
- let _ = crate :: panic:: catch_unwind ( || {
427
+ let _ = panic:: catch_unwind ( || {
313
428
let guard = lock. lock ( ) . unwrap ( ) ;
314
429
let guard = MutexGuard :: map :: < ( ) , _ > ( guard, |val| val) ;
315
430
let _guard = MappedMutexGuard :: try_map :: < ( ) , _ > ( guard, |_| panic ! ( ) ) ;
0 commit comments