99//
1010//===----------------------------------------------------------------------===//
1111
12- import _CAsyncSequenceValidationSupport
12+ @ preconcurrency import _CAsyncSequenceValidationSupport
1313import AsyncAlgorithms
1414
1515@_silgen_name ( " swift_job_run " )
@@ -48,17 +48,17 @@ extension AsyncSequenceValidationDiagram {
4848 do {
4949 if let pastEnd = try await iterator. next ( ) {
5050 let failure = ExpectationFailure (
51- when: Context . clock!. now,
51+ when: Context . state . withCriticalRegion ( \ . clock!. now) ,
5252 kind: . specificationViolationGotValueAfterIteration( pastEnd) ,
5353 specification: output)
54- Context . specificationFailures. append ( failure)
54+ Context . state . withCriticalRegion { $0 . specificationFailures. append ( failure) }
5555 }
5656 } catch {
5757 let failure = ExpectationFailure (
58- when: Context . clock!. now,
58+ when: Context . state . withCriticalRegion ( \ . clock!. now) ,
5959 kind: . specificationViolationGotFailureAfterIteration( error) ,
6060 specification: output)
61- Context . specificationFailures. append ( failure)
61+ Context . state . withCriticalRegion { $0 . specificationFailures. append ( failure) }
6262 }
6363 } catch {
6464 throw error
@@ -107,7 +107,7 @@ extension AsyncSequenceValidationDiagram {
107107 }
108108 }
109109
110- private static let _executor : AnyObject = {
110+ private static let _executor : any SerialExecutor = {
111111 if #available( macOS 14 . 0 , iOS 17 . 0 , watchOS 10 . 0 , tvOS 17 . 0 , * ) {
112112 return ClockExecutor_5_9 ( )
113113 } else {
@@ -116,19 +116,18 @@ extension AsyncSequenceValidationDiagram {
116116 } ( )
117117
118118 static var unownedExecutor : UnownedSerialExecutor {
119- ( _executor as! any SerialExecutor ) . asUnownedSerialExecutor ( )
119+ _executor. asUnownedSerialExecutor ( )
120120 }
121121#endif
122122
123- static var clock : Clock ?
124-
125-
126-
127- static var driver : TaskDriver ?
128-
129- static var currentJob : Job ?
130-
131- static var specificationFailures = [ ExpectationFailure] ( )
123+ static let state = ManagedCriticalState ( State ( ) )
124+
125+ struct State {
126+ var clock : Clock ?
127+ var driver : TaskDriver ?
128+ var currentJob : Job ?
129+ var specificationFailures = [ ExpectationFailure] ( )
130+ }
132131 }
133132
134133 enum ActualResult {
@@ -158,9 +157,9 @@ extension AsyncSequenceValidationDiagram {
158157 actual: [ ( Clock . Instant , Result < String ? , Error > ) ]
159158 ) -> ( ExpectationResult , [ ExpectationFailure ] ) {
160159 let result = ExpectationResult ( expected: expected, actual: actual)
161- var failures = Context . specificationFailures
162- Context . specificationFailures. removeAll ( )
163-
160+ var failures = Context . state . withCriticalRegion ( \ . specificationFailures)
161+ Context . state . withCriticalRegion { $0 . specificationFailures. removeAll ( ) }
162+
164163 let actualTimes = actual. map { when, _ in when }
165164 let expectedTimes = expected. map { $0. when }
166165
@@ -349,55 +348,58 @@ extension AsyncSequenceValidationDiagram {
349348 }
350349
351350 let actual = ManagedCriticalState ( [ ( Clock . Instant , Result < String ? , Error > ) ] ( ) )
352- Context . clock = clock
353- Context . specificationFailures. removeAll ( )
354- // This all needs to be isolated from potential Tasks (the caller function might be async!)
355- Context . driver = TaskDriver ( queue: diagram. queue) { driver in
356- swift_task_enqueueGlobal_hook = { job, original in
357- Context . driver? . enqueue ( job)
358- }
359-
360- let runner = Task {
361- do {
362- try await test. test ( with: clock, activeTicks: activeTicks, output: test. output) { event in
351+ Context . state. withCriticalRegion { state in
352+ state. clock = clock
353+ state. specificationFailures. removeAll ( )
354+ // This all needs to be isolated from potential Tasks (the caller function might be async!)
355+ state. driver = TaskDriver ( queue: diagram. queue) { driver in
356+ swift_task_enqueueGlobal_hook = { job, original in
357+ Context . state. withCriticalRegion ( \. driver) ? . enqueue ( job)
358+ }
359+
360+ let runner = Task {
361+ do {
362+ try await test. test ( with: clock, activeTicks: activeTicks, output: test. output) { event in
363+ actual. withCriticalRegion { values in
364+ values. append ( ( clock. now, . success( event) ) )
365+ }
366+ }
363367 actual. withCriticalRegion { values in
364- values. append ( ( clock. now, . success( event) ) )
368+ values. append ( ( clock. now, . success( nil ) ) )
369+ }
370+ } catch {
371+ actual. withCriticalRegion { values in
372+ values. append ( ( clock. now, . failure( error) ) )
365373 }
366- }
367- actual. withCriticalRegion { values in
368- values. append ( ( clock. now, . success( nil ) ) )
369- }
370- } catch {
371- actual. withCriticalRegion { values in
372- values. append ( ( clock. now, . failure( error) ) )
373374 }
374375 }
375- }
376-
377- // Drain off any initial work. Work may spawn additional work to be done.
378- // If the driver ever becomes blocked on the clock, exit early out of that
379- // drain, because the drain cant make any forward progress if it is blocked
380- // by a needed clock advancement.
381- diagram. queue. drain ( )
382- // Next make sure to iterate a decent amount past the end of the maximum
383- // scheduled things (that way we ensure any reasonable errors are caught)
384- for _ in 0 ..< ( end. when. rawValue * 2 ) {
385- if cancelEvents. contains ( diagram. queue. now. advanced ( by: . steps( 1 ) ) ) {
386- runner. cancel ( )
376+
377+ // Drain off any initial work. Work may spawn additional work to be done.
378+ // If the driver ever becomes blocked on the clock, exit early out of that
379+ // drain, because the drain cant make any forward progress if it is blocked
380+ // by a needed clock advancement.
381+ diagram. queue. drain ( )
382+ // Next make sure to iterate a decent amount past the end of the maximum
383+ // scheduled things (that way we ensure any reasonable errors are caught)
384+ for _ in 0 ..< ( end. when. rawValue * 2 ) {
385+ if cancelEvents. contains ( diagram. queue. now. advanced ( by: . steps( 1 ) ) ) {
386+ runner. cancel ( )
387+ }
388+ diagram. queue. advance ( )
387389 }
388- diagram. queue. advance ( )
390+
391+ runner. cancel ( )
392+ Context . state. withCriticalRegion { $0. clock = nil }
393+ swift_task_enqueueGlobal_hook = nil
389394 }
390-
391- runner. cancel ( )
392- Context . clock = nil
393- swift_task_enqueueGlobal_hook = nil
394395 }
395- Context . driver? . start ( )
396+ let driver = Context . state. withCriticalRegion ( \. driver)
397+ driver? . start ( )
396398 // This is only valid since we are doing tests here
397399 // else wise this would cause QoS inversions
398- Context . driver? . join ( )
399- Context . driver = nil
400-
400+ driver? . join ( )
401+ Context . state . withCriticalRegion { $0 . driver = nil }
402+
401403 return validate (
402404 inputs: test. inputs,
403405 output: test. output,
0 commit comments