1+ use crate :: fmt:: Debug ;
2+ use crate :: ops:: FnMut ;
3+ use crate :: panic:: { self , AssertUnwindSafe } ;
14use crate :: sync:: atomic:: { AtomicUsize , Ordering } ;
25use crate :: sync:: mpsc:: channel;
36use crate :: sync:: { Arc , Condvar , MappedMutexGuard , Mutex , MutexGuard , TryLockError } ;
4- use crate :: thread;
7+ use crate :: { hint , mem , thread} ;
58
69struct Packet < T > ( Arc < ( Mutex < T > , Condvar ) > ) ;
710
811#[ derive( Eq , PartialEq , Debug ) ]
912struct NonCopy ( i32 ) ;
1013
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+
1132#[ test]
1233fn smoke ( ) {
1334 let m = Mutex :: new ( ( ) ) ;
@@ -57,6 +78,21 @@ fn try_lock() {
5778 * m. try_lock ( ) . unwrap ( ) = ( ) ;
5879}
5980
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+
6096#[ test]
6197fn test_into_inner ( ) {
6298 let m = Mutex :: new ( NonCopy ( 10 ) ) ;
@@ -83,21 +119,31 @@ fn test_into_inner_drop() {
83119
84120#[ test]
85121fn 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 ) ) ;
93123
94- assert ! ( m. is_poisoned( ) ) ;
95- match Arc :: try_unwrap ( m) . unwrap ( ) . into_inner ( ) {
124+ match m. into_inner ( ) {
96125 Err ( e) => assert_eq ! ( e. into_inner( ) , NonCopy ( 10 ) ) ,
97126 Ok ( x) => panic ! ( "into_inner of poisoned Mutex is Ok: {x:?}" ) ,
98127 }
99128}
100129
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+
101147#[ test]
102148fn test_get_mut ( ) {
103149 let mut m = Mutex :: new ( NonCopy ( 10 ) ) ;
@@ -107,21 +153,90 @@ fn test_get_mut() {
107153
108154#[ test]
109155fn 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 ) ) ;
117157
118- assert ! ( m. is_poisoned( ) ) ;
119- match Arc :: try_unwrap ( m) . unwrap ( ) . get_mut ( ) {
158+ match m. get_mut ( ) {
120159 Err ( e) => assert_eq ! ( * e. into_inner( ) , NonCopy ( 10 ) ) ,
121160 Ok ( x) => panic ! ( "get_mut of poisoned Mutex is Ok: {x:?}" ) ,
122161 }
123162}
124163
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+
125240#[ test]
126241fn test_mutex_arc_condvar ( ) {
127242 let packet = Packet ( Arc :: new ( ( Mutex :: new ( false ) , Condvar :: new ( ) ) ) ) ;
@@ -269,7 +384,7 @@ fn test_mapping_mapped_guard() {
269384fn panic_while_mapping_unlocked_poison ( ) {
270385 let lock = Mutex :: new ( ( ) ) ;
271386
272- let _ = crate :: panic:: catch_unwind ( || {
387+ let _ = panic:: catch_unwind ( || {
273388 let guard = lock. lock ( ) . unwrap ( ) ;
274389 let _guard = MutexGuard :: map :: < ( ) , _ > ( guard, |_| panic ! ( ) ) ;
275390 } ) ;
@@ -282,7 +397,7 @@ fn panic_while_mapping_unlocked_poison() {
282397 Err ( TryLockError :: Poisoned ( _) ) => { }
283398 }
284399
285- let _ = crate :: panic:: catch_unwind ( || {
400+ let _ = panic:: catch_unwind ( || {
286401 let guard = lock. lock ( ) . unwrap ( ) ;
287402 let _guard = MutexGuard :: try_map :: < ( ) , _ > ( guard, |_| panic ! ( ) ) ;
288403 } ) ;
@@ -295,7 +410,7 @@ fn panic_while_mapping_unlocked_poison() {
295410 Err ( TryLockError :: Poisoned ( _) ) => { }
296411 }
297412
298- let _ = crate :: panic:: catch_unwind ( || {
413+ let _ = panic:: catch_unwind ( || {
299414 let guard = lock. lock ( ) . unwrap ( ) ;
300415 let guard = MutexGuard :: map :: < ( ) , _ > ( guard, |val| val) ;
301416 let _guard = MappedMutexGuard :: map :: < ( ) , _ > ( guard, |_| panic ! ( ) ) ;
@@ -309,7 +424,7 @@ fn panic_while_mapping_unlocked_poison() {
309424 Err ( TryLockError :: Poisoned ( _) ) => { }
310425 }
311426
312- let _ = crate :: panic:: catch_unwind ( || {
427+ let _ = panic:: catch_unwind ( || {
313428 let guard = lock. lock ( ) . unwrap ( ) ;
314429 let guard = MutexGuard :: map :: < ( ) , _ > ( guard, |val| val) ;
315430 let _guard = MappedMutexGuard :: try_map :: < ( ) , _ > ( guard, |_| panic ! ( ) ) ;
0 commit comments