Skip to content

Remove more blocking_sync calls #491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Sources/SWBBuildSystem/BuildOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,7 @@ private class InProcessCommand: SWBLLBuild.ExternalCommand, SWBLLBuild.ExternalD
// Get the current output delegate from the adaptor.
//
// FIXME: This should never fail (since we are executing), but we have seen a crash here with that assumption. For now we are defensive until the source can be tracked down: <rdar://problem/31670274> Diagnose unexpected missing output delegate from: <rdar://problem/31669245> Crash in InProcessCommand.execute()
guard let outputDelegate = adaptor.getActiveOutputDelegate(command) else {
guard let outputDelegate = await adaptor.getActiveOutputDelegate(command) else {
return .failed
}

Expand Down Expand Up @@ -1604,9 +1604,9 @@ internal final class OperationSystemAdaptor: SWBLLBuild.BuildSystemDelegate, Act
/// Get the active output delegate for an executing command.
///
/// - returns: The active delegate, or nil if not found.
func getActiveOutputDelegate(_ command: Command) -> (any TaskOutputDelegate)? {
func getActiveOutputDelegate(_ command: Command) async -> (any TaskOutputDelegate)? {
// FIXME: This is a very bad idea, doing a sync against the response queue is introducing artificial latency when an in-process command needs to wait for the response queue to flush. However, we also can't simply move to a decoupled lock, because we don't want the command to start reporting output before it has been fully reported as having started. We need to move in-process task to another model.
return queue.blocking_sync {
return await queue.sync {
self.commandOutputDelegates[command]
}
}
Expand Down
6 changes: 3 additions & 3 deletions Sources/SWBCore/LibSwiftDriver/LibSwiftDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,9 @@ public final class SwiftModuleDependencyGraph: SwiftGlobalExplicitDependencyGrap
return fileDependencies
}

public func queryTransitiveDependencyModuleNames(for key: String) throws -> [String] {
let graph = try registryQueue.blocking_sync {
guard let driver = registry[key] else {
public func queryTransitiveDependencyModuleNames(for key: String) async throws -> [String] {
let graph = try await registryQueue.sync {
guard let driver = self.registry[key] else {
throw StubError.error("Unable to find jobs for key \(key). Be sure to plan the build ahead of fetching results.")
}
return driver.intermoduleDependencyGraph
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ final public class SwiftDriverTaskAction: TaskAction, BuildValueValidatingTaskAc
}

if driverPayload.reportRequiredTargetDependencies != .no && driverPayload.explicitModulesEnabled, let target = task.forTarget {
let dependencyModuleNames = try dependencyGraph.queryTransitiveDependencyModuleNames(for: driverPayload.uniqueID)
let dependencyModuleNames = try await dependencyGraph.queryTransitiveDependencyModuleNames(for: driverPayload.uniqueID)
for dependencyModuleName in dependencyModuleNames {
if let targetDependencies = dynamicExecutionDelegate.operationContext.definingTargetsByModuleName[dependencyModuleName] {
for targetDependency in targetDependencies {
Expand Down
14 changes: 14 additions & 0 deletions Sources/SWBUtil/SWBDispatch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,20 @@ public final class SWBQueue: Sendable {
}
}

/// Submits a block object for execution and returns after that block finishes executing.
/// - note: This implementation won't block the calling thread, unlike the synchronous overload of ``sync()``.
public func sync<T>(qos: SWBQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute block: @Sendable @escaping () throws -> T) async throws -> T {
try await withCheckedThrowingContinuation { continuation in
queue.async(qos: qos.dispatchQoS, flags: flags.dispatchFlags) {
do {
continuation.resume(returning: try block())
} catch {
continuation.resume(throwing: error)
}
}
}
}

public func async(group: SWBDispatchGroup? = nil, qos: SWBQoS = .unspecified, execute body: @escaping @Sendable () -> Void) {
return queue.async(group: group?.group, qos: qos.dispatchQoS, execute: body)
}
Expand Down
Loading