Skip to content

Commit da65429

Browse files
authored
APIDiff.swift: Address warning by using task group instead of semaphore (#7959)
1 parent e3721b3 commit da65429

File tree

1 file changed

+31
-27
lines changed

1 file changed

+31
-27
lines changed

Sources/Commands/PackageCommands/APIDiff.swift

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Dispatch
1717
import PackageGraph
1818
import PackageModel
1919
import SourceControl
20+
import _Concurrency
2021

2122
struct DeprecatedAPIDiff: ParsableCommand {
2223
static let configuration = CommandConfiguration(commandName: "experimental-api-diff",
@@ -119,50 +120,53 @@ struct APIDiff: AsyncSwiftCommand {
119120
swiftCommandState: swiftCommandState
120121
)
121122

122-
let results = ThreadSafeArrayStore<SwiftAPIDigester.ComparisonResult>()
123-
let group = DispatchGroup()
124-
let semaphore = DispatchSemaphore(value: Int(try buildSystem.buildPlan.destinationBuildParameters.workers))
125123
var skippedModules: Set<String> = []
126124

127-
for module in modulesToDiff {
128-
let moduleBaselinePath = baselineDir.appending("\(module).json")
129-
guard swiftCommandState.fileSystem.exists(moduleBaselinePath) else {
130-
print("\nSkipping \(module) because it does not exist in the baseline")
131-
skippedModules.insert(module)
132-
continue
133-
}
134-
semaphore.wait()
135-
DispatchQueue.sharedConcurrent.async(group: group) {
136-
do {
137-
if let comparisonResult = try apiDigesterTool.compareAPIToBaseline(
138-
at: moduleBaselinePath,
139-
for: module,
140-
buildPlan: try buildSystem.buildPlan,
141-
except: breakageAllowlistPath
142-
) {
143-
results.append(comparisonResult)
125+
let results = await withTaskGroup(of: SwiftAPIDigester.ComparisonResult?.self, returning: [SwiftAPIDigester.ComparisonResult].self) { taskGroup in
126+
127+
for module in modulesToDiff {
128+
let moduleBaselinePath = baselineDir.appending("\(module).json")
129+
guard swiftCommandState.fileSystem.exists(moduleBaselinePath) else {
130+
print("\nSkipping \(module) because it does not exist in the baseline")
131+
skippedModules.insert(module)
132+
continue
133+
}
134+
taskGroup.addTask {
135+
do {
136+
if let comparisonResult = try apiDigesterTool.compareAPIToBaseline(
137+
at: moduleBaselinePath,
138+
for: module,
139+
buildPlan: try buildSystem.buildPlan,
140+
except: breakageAllowlistPath
141+
) {
142+
return comparisonResult
143+
}
144+
} catch {
145+
swiftCommandState.observabilityScope.emit(error: "failed to compare API to baseline", underlyingError: error)
144146
}
145-
} catch {
146-
swiftCommandState.observabilityScope.emit(error: "failed to compare API to baseline", underlyingError: error)
147+
return nil
147148
}
148-
semaphore.signal()
149149
}
150+
var results = [SwiftAPIDigester.ComparisonResult]()
151+
for await result in taskGroup {
152+
guard let result else { continue }
153+
results.append(result)
154+
}
155+
return results
150156
}
151157

152-
group.wait()
153-
154158
let failedModules = modulesToDiff
155159
.subtracting(skippedModules)
156160
.subtracting(results.map(\.moduleName))
157161
for failedModule in failedModules {
158162
swiftCommandState.observabilityScope.emit(error: "failed to read API digester output for \(failedModule)")
159163
}
160164

161-
for result in results.get() {
165+
for result in results {
162166
try self.printComparisonResult(result, observabilityScope: swiftCommandState.observabilityScope)
163167
}
164168

165-
guard failedModules.isEmpty && results.get().allSatisfy(\.hasNoAPIBreakingChanges) else {
169+
guard failedModules.isEmpty && results.allSatisfy(\.hasNoAPIBreakingChanges) else {
166170
throw ExitCode.failure
167171
}
168172
}

0 commit comments

Comments
 (0)