@@ -2,33 +2,40 @@ import Testing
22
33@testable import DispatchAsync
44
5- @Test
5+ @Test ( . timeLimit ( . minutes ( 1 ) ) )
66func asyncSemaphoreWaitSignal( ) async throws {
77 let semaphore = AsyncSemaphore ( value: 1 )
88
99 // First wait should succeed immediately and bring the count to 0
1010 await semaphore. wait ( )
1111
1212 // Launch a task that tries to wait – it should be suspended until we signal
13- var didEnterCriticalSection = false
14- let waiter = Task {
15- await semaphore. wait ( )
16- didEnterCriticalSection = true
17- await semaphore. signal ( )
13+ nonisolated ( unsafe) var didEnterCriticalSection = false
14+ await withCheckedContinuation { continuation in
15+ Task { @Sendable in
16+ // Ensure the rest of this test doesn't
17+ // proceed until the Task block has started executing
18+ continuation. resume ( )
19+
20+ await semaphore. wait ( )
21+ didEnterCriticalSection = true
22+ await semaphore. signal ( )
23+ }
1824 }
1925
20- // Allow the task a brief moment to start and (hopefully) suspend
26+ // Allow the task a few cycles to reach the initial semaphore.wait()
2127 try ? await Task . sleep ( nanoseconds: 1_000 )
2228
2329 #expect( !didEnterCriticalSection) // should still be waiting
2430
2531 // Now release the semaphore – the waiter should proceed
2632 await semaphore. signal ( )
2733
28- // Give the waiter a chance to run
29- try ? await Task . sleep ( nanoseconds: 1_000 )
34+ // Wait for second signal to fire from inside the task above
35+ // There is a timeout on this test, so if there is a problem
36+ // we'll either hit the timeout and fail, or didEnterCriticalSection
37+ // will be false below
38+ await semaphore. wait ( )
3039
3140 #expect( didEnterCriticalSection) // waiter must have run
32-
33- _ = await waiter. value
3441}
0 commit comments