Skip to content

Commit dc19ff3

Browse files
authored
Merge pull request #74 from DougGregor/parallel
Respect numParallelJobs and also install INT handler
2 parents 26b72bf + 908dbe8 commit dc19ff3

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

Sources/SwiftDriver/Driver/Driver.swift

+5-2
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ extension Driver {
364364
/// Run the driver.
365365
public mutating func run(
366366
resolver: ArgsResolver,
367-
executorDelegate: JobExecutorDelegate? = nil
367+
executorDelegate: JobExecutorDelegate? = nil,
368+
processSet: ProcessSet? = nil
368369
) throws {
369370
// We just need to invoke the corresponding tool if the kind isn't Swift compiler.
370371
guard driverKind.isSwiftCompiler else {
@@ -402,7 +403,9 @@ extension Driver {
402403
// Start up an executor and perform the build.
403404
let jobExecutor = JobExecutor(
404405
jobs: jobs, resolver: resolver,
405-
executorDelegate: executorDelegate
406+
executorDelegate: executorDelegate,
407+
numParallelJobs: numParallelJobs,
408+
processSet: processSet
406409
)
407410
try jobExecutor.execute()
408411
}

Sources/SwiftDriver/Execution/JobExecutor.swift

+41-3
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,24 @@ public final class JobExecutor {
8686
/// Queue for executor delegate.
8787
let delegateQueue: DispatchQueue = DispatchQueue(label: "org.swift.driver.job-executor-delegate")
8888

89+
/// Operation queue for executing tasks in parallel.
90+
let jobQueue: OperationQueue
91+
92+
/// The process set to use when launching new processes.
93+
let processSet: ProcessSet?
94+
8995
init(
9096
argsResolver: ArgsResolver,
9197
producerMap: [VirtualPath: Job],
92-
executorDelegate: JobExecutorDelegate
98+
executorDelegate: JobExecutorDelegate,
99+
jobQueue: OperationQueue,
100+
processSet: ProcessSet?
93101
) {
94102
self.producerMap = producerMap
95103
self.argsResolver = argsResolver
96104
self.executorDelegate = executorDelegate
105+
self.jobQueue = jobQueue
106+
self.processSet = processSet
97107
}
98108
}
99109

@@ -106,14 +116,24 @@ public final class JobExecutor {
106116
/// The job executor delegate.
107117
let executorDelegate: JobExecutorDelegate
108118

119+
/// The number of jobs to run in parallel.
120+
let numParallelJobs: Int
121+
122+
/// The process set to use when launching new processes.
123+
let processSet: ProcessSet?
124+
109125
public init(
110126
jobs: [Job],
111127
resolver: ArgsResolver,
112-
executorDelegate: JobExecutorDelegate
128+
executorDelegate: JobExecutorDelegate,
129+
numParallelJobs: Int? = nil,
130+
processSet: ProcessSet? = nil
113131
) {
114132
self.jobs = jobs
115133
self.argsResolver = resolver
116134
self.executorDelegate = executorDelegate
135+
self.numParallelJobs = numParallelJobs ?? 1
136+
self.processSet = processSet
117137
}
118138

119139
/// Execute all jobs.
@@ -141,10 +161,16 @@ public final class JobExecutor {
141161
}
142162
}
143163

164+
let jobQueue = OperationQueue()
165+
jobQueue.name = "org.swift.driver.job-execution"
166+
jobQueue.maxConcurrentOperationCount = numParallelJobs
167+
144168
return Context(
145169
argsResolver: argsResolver,
146170
producerMap: producerMap,
147-
executorDelegate: executorDelegate
171+
executorDelegate: executorDelegate,
172+
jobQueue: jobQueue,
173+
processSet: processSet
148174
)
149175
}
150176
}
@@ -281,6 +307,13 @@ class ExecuteJobRule: LLBuildRule {
281307
return engine.taskIsComplete(DriverBuildValue.jobExecution(success: false))
282308
}
283309

310+
let context = engine.jobExecutorContext
311+
context.jobQueue.addOperation {
312+
self.executeJob(engine)
313+
}
314+
}
315+
316+
private func executeJob(_ engine: LLTaskBuildEngine) {
284317
let context = engine.jobExecutorContext
285318
let resolver = context.argsResolver
286319
let job = key.job
@@ -295,6 +328,11 @@ class ExecuteJobRule: LLBuildRule {
295328
let process = try context.executorDelegate.launchProcess(for: job, arguments: arguments)
296329
pid = Int(process.processID)
297330

331+
// Add it to the process set if it's a real process.
332+
if case let realProcess as TSCBasic.Process = process {
333+
try context.processSet?.add(realProcess)
334+
}
335+
298336
// Inform the delegate.
299337
context.delegateQueue.async {
300338
context.executorDelegate.jobStarted(job: job, arguments: arguments, pid: pid)

Sources/swift-driver/main.swift

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import SwiftDriver
2+
23
import TSCLibc
3-
import enum TSCUtility.Diagnostics
4+
import TSCBasic
5+
import TSCUtility
6+
7+
var intHandler: InterruptHandler?
48

59
do {
10+
let processSet = ProcessSet()
11+
intHandler = try InterruptHandler {
12+
processSet.terminate()
13+
}
14+
615
var driver = try Driver(args: CommandLine.arguments)
716
let resolver = try ArgsResolver()
8-
try driver.run(resolver: resolver)
17+
try driver.run(resolver: resolver, processSet: processSet)
918

1019
if driver.diagnosticEngine.hasErrors {
1120
exit(EXIT_FAILURE)

0 commit comments

Comments
 (0)