@@ -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,32 @@ 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+ unsafe { msg_send ! [ semaphore, retainCount] }
69+ }
70+
71+ #[ test]
72+ fn acquire_release ( ) {
73+ let semaphore = DispatchSemaphore :: new ( 1 ) ;
74+
75+ assert_eq ! ( retain_count( & semaphore) , 1 ) ;
76+ {
77+ let _guard = semaphore. try_acquire ( DispatchTime :: NOW ) . unwrap ( ) ;
78+ assert_eq ! ( retain_count( & semaphore) , 2 ) ;
79+ }
80+ assert_eq ! ( retain_count( & semaphore) , 1 ) ;
81+ {
82+ let guard = semaphore. try_acquire ( DispatchTime :: NOW ) . unwrap ( ) ;
83+ assert_eq ! ( retain_count( & semaphore) , 2 ) ;
84+ guard. release ( ) ;
85+ assert_eq ! ( retain_count( & semaphore) , 1 ) ;
86+ }
87+ assert_eq ! ( retain_count( & semaphore) , 1 ) ;
88+ }
89+ }
0 commit comments