Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ea58d5d

Browse files
committedJun 19, 2024·
Fix compile errors for Swift 6 language mode
1 parent 6ae9a05 commit ea58d5d

File tree

6 files changed

+96
-90
lines changed

6 files changed

+96
-90
lines changed
 

‎Sources/AsyncAlgorithms_XCTest/ValidationTest.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extension XCTestCase {
2424
#endif
2525
}
2626

27-
func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
27+
func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #filePath, line: UInt = #line) {
2828
var expectations = expectedFailures
2929
var result: AsyncSequenceValidationDiagram.ExpectationResult?
3030
var failures = [AsyncSequenceValidationDiagram.ExpectationFailure]()
@@ -62,15 +62,15 @@ extension XCTestCase {
6262
}
6363
}
6464

65-
func validate<Test: AsyncSequenceValidationTest>(expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
65+
func validate<Test: AsyncSequenceValidationTest>(expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #filePath, line: UInt = #line) {
6666
validate(theme: .ascii, expectedFailures: expectedFailures, build, file: file, line: line)
6767
}
6868

69-
public func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
69+
public func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #filePath, line: UInt = #line) {
7070
validate(theme: theme, expectedFailures: [], build, file: file, line: line)
7171
}
7272

73-
public func validate<Test: AsyncSequenceValidationTest>(@AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
73+
public func validate<Test: AsyncSequenceValidationTest>(@AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #filePath, line: UInt = #line) {
7474
validate(theme: .ascii, expectedFailures: [], build, file: file, line: line)
7575
}
7676
}

‎Sources/AsyncSequenceValidation/Clock.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ extension AsyncSequenceValidationDiagram.Clock {
115115
let token = queue.prepare()
116116
try await withTaskCancellationHandler {
117117
try await withUnsafeThrowingContinuation { continuation in
118-
queue.enqueue(AsyncSequenceValidationDiagram.Context.currentJob, deadline: deadline, continuation: continuation, token: token)
118+
queue.enqueue(AsyncSequenceValidationDiagram.Context.state.withCriticalRegion(\.currentJob), deadline: deadline, continuation: continuation, token: token)
119119
}
120120
} onCancel: {
121121
queue.cancel(token)

‎Sources/AsyncSequenceValidation/Input.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extension AsyncSequenceValidationDiagram {
5252
}
5353
return try await withTaskCancellationHandler {
5454
try await withUnsafeThrowingContinuation { continuation in
55-
queue.enqueue(Context.currentJob, deadline: when, continuation: continuation, results[eventIndex], index: index, token: token)
55+
queue.enqueue(Context.state.withCriticalRegion(\.currentJob), deadline: when, continuation: continuation, results[eventIndex], index: index, token: token)
5656
}
5757
} onCancel: { [queue] in
5858
queue.cancel(token)

‎Sources/AsyncSequenceValidation/TaskDriver.swift

+28-24
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,8 @@ import Glibc
1919
#error("TODO: Port TaskDriver threading to windows")
2020
#endif
2121

22-
#if canImport(Darwin)
23-
func start_thread(_ raw: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
24-
Unmanaged<TaskDriver>.fromOpaque(raw).takeRetainedValue().run()
25-
return nil
26-
}
27-
#elseif canImport(Glibc)
28-
func start_thread(_ raw: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? {
29-
Unmanaged<TaskDriver>.fromOpaque(raw!).takeRetainedValue().run()
30-
return nil
31-
}
32-
#elseif canImport(WinSDK)
33-
#error("TODO: Port TaskDriver threading to windows")
34-
#endif
35-
36-
final class TaskDriver {
37-
let work: (TaskDriver) -> Void
22+
final class TaskDriver: @unchecked Sendable {
23+
let work: @Sendable (TaskDriver) -> Void
3824
let queue: WorkQueue
3925
#if canImport(Darwin)
4026
var thread: pthread_t?
@@ -43,19 +29,37 @@ final class TaskDriver {
4329
#elseif canImport(WinSDK)
4430
#error("TODO: Port TaskDriver threading to windows")
4531
#endif
46-
47-
init(queue: WorkQueue, _ work: @escaping (TaskDriver) -> Void) {
32+
33+
private let lock = Lock.allocate()
34+
35+
init(queue: WorkQueue, _ work: @Sendable @escaping (TaskDriver) -> Void) {
4836
self.queue = queue
4937
self.work = work
5038
}
5139

5240
func start() {
41+
#if canImport(Darwin)
42+
func start_thread(_ raw: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
43+
Unmanaged<TaskDriver>.fromOpaque(raw).takeRetainedValue().run()
44+
return nil
45+
}
46+
#elseif canImport(Glibc)
47+
func start_thread(_ raw: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? {
48+
Unmanaged<TaskDriver>.fromOpaque(raw!).takeRetainedValue().run()
49+
return nil
50+
}
51+
#elseif canImport(WinSDK)
52+
#error("TODO: Port TaskDriver threading to windows")
53+
#endif
54+
55+
lock.withLockVoid {
5356
#if canImport(Darwin) || canImport(Glibc)
54-
pthread_create(&thread, nil, start_thread,
55-
Unmanaged.passRetained(self).toOpaque())
57+
pthread_create(&thread, nil, start_thread,
58+
Unmanaged.passRetained(self).toOpaque())
5659
#elseif canImport(WinSDK)
5760
#error("TODO: Port TaskDriver threading to windows")
5861
#endif
62+
}
5963
}
6064

6165
func run() {
@@ -77,11 +81,11 @@ final class TaskDriver {
7781

7882
func enqueue(_ job: JobRef) {
7983
let job = Job(job)
80-
queue.enqueue(AsyncSequenceValidationDiagram.Context.currentJob) {
81-
let previous = AsyncSequenceValidationDiagram.Context.currentJob
82-
AsyncSequenceValidationDiagram.Context.currentJob = job
84+
queue.enqueue(AsyncSequenceValidationDiagram.Context.state.withCriticalRegion(\.currentJob)) {
85+
let previous = AsyncSequenceValidationDiagram.Context.state.withCriticalRegion(\.currentJob)
86+
AsyncSequenceValidationDiagram.Context.state.withCriticalRegion { $0.currentJob = job }
8387
job.execute()
84-
AsyncSequenceValidationDiagram.Context.currentJob = previous
88+
AsyncSequenceValidationDiagram.Context.state.withCriticalRegion { $0.currentJob = previous }
8589
}
8690
}
8791
}

‎Sources/AsyncSequenceValidation/Test.swift

+61-59
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12-
import _CAsyncSequenceValidationSupport
12+
@preconcurrency import _CAsyncSequenceValidationSupport
1313
import 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,

‎Tests/AsyncAlgorithmsTests/Support/Asserts.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public func XCTAssertEqual<A: Equatable, B: Equatable, C: Equatable>(_ expressio
154154
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
155155
internal func XCTAssertThrowsError<T>(
156156
_ expression: @autoclosure () async throws -> T,
157-
file: StaticString = #file,
157+
file: StaticString = #filePath,
158158
line: UInt = #line,
159159
verify: (Error) -> Void = { _ in }
160160
) async {

0 commit comments

Comments
 (0)
Please sign in to comment.