@@ -39,10 +39,14 @@ pub struct DispatchSemaphoreGuard(DispatchRetained<DispatchSemaphore>);
3939impl DispatchSemaphoreGuard {
4040 /// Release the [`DispatchSemaphore`].
4141 pub fn release ( self ) -> bool {
42- let this = ManuallyDrop :: new ( self ) ;
42+ // Extract the inner `DispatchRetained` so that it will be dropped independently of
43+ // `self`. SAFETY: `self.0` is a valid `DispatchRetained`.
44+ let semaphore: DispatchRetained < DispatchSemaphore > = unsafe {
45+ DispatchRetained :: from_raw ( DispatchRetained :: as_ptr ( & ManuallyDrop :: new ( self ) . 0 ) )
46+ } ;
4347
4448 // SAFETY: DispatchSemaphore cannot be null.
45- let result = this . 0 . signal ( ) ;
49+ let result = semaphore . signal ( ) ;
4650
4751 result != 0
4852 }
@@ -54,3 +58,33 @@ impl Drop for DispatchSemaphoreGuard {
5458 self . 0 . signal ( ) ;
5559 }
5660}
61+
62+ #[ cfg( test) ]
63+ mod tests {
64+ use super :: * ;
65+ use objc2:: msg_send;
66+
67+ fn retain_count ( semaphore : & DispatchSemaphore ) -> usize {
68+ // SAFETY: semaphore is valid and the method signature is correct.
69+ unsafe { msg_send ! [ semaphore, retainCount] }
70+ }
71+
72+ #[ test]
73+ fn acquire_release ( ) {
74+ let semaphore = DispatchSemaphore :: new ( 1 ) ;
75+
76+ assert_eq ! ( retain_count( & semaphore) , 1 ) ;
77+ {
78+ let _guard = semaphore. try_acquire ( DispatchTime :: NOW ) . unwrap ( ) ;
79+ assert_eq ! ( retain_count( & semaphore) , 2 ) ;
80+ }
81+ assert_eq ! ( retain_count( & semaphore) , 1 ) ;
82+ {
83+ let guard = semaphore. try_acquire ( DispatchTime :: NOW ) . unwrap ( ) ;
84+ assert_eq ! ( retain_count( & semaphore) , 2 ) ;
85+ guard. release ( ) ;
86+ assert_eq ! ( retain_count( & semaphore) , 1 ) ;
87+ }
88+ assert_eq ! ( retain_count( & semaphore) , 1 ) ;
89+ }
90+ }
0 commit comments