Skip to content

Commit 58bce82

Browse files
committed
Add a concurrentForEach method to start a concurrent task for each element in a collection
This is simpler to reason about than creating a `TaskGroup`.
1 parent f4e015b commit 58bce82

File tree

2 files changed

+19
-27
lines changed

2 files changed

+19
-27
lines changed

Sources/SemanticIndex/SemanticIndexManager.swift

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,7 @@ package final actor SemanticIndexManager {
339339
}
340340

341341
private func waitForBuildGraphGenerationTasks() async {
342-
await withTaskGroup(of: Void.self) { taskGroup in
343-
for generateBuildGraphTask in scheduleIndexingTasks.values {
344-
taskGroup.addTask {
345-
await generateBuildGraphTask.value
346-
}
347-
}
348-
}
342+
await scheduleIndexingTasks.values.concurrentForEach { await $0.value }
349343
}
350344

351345
/// Wait for all in-progress index tasks to finish.
@@ -355,18 +349,13 @@ package final actor SemanticIndexManager {
355349
// can await the index tasks below.
356350
await waitForBuildGraphGenerationTasks()
357351

358-
await withTaskGroup(of: Void.self) { taskGroup in
359-
for (_, status) in inProgressIndexTasks {
360-
switch status {
361-
case .waitingForPreparation(preparationTaskID: _, indexTask: let indexTask),
362-
.preparing(preparationTaskID: _, indexTask: let indexTask),
363-
.updatingIndexStore(updateIndexStoreTask: _, indexTask: let indexTask):
364-
taskGroup.addTask {
365-
await indexTask.value
366-
}
367-
}
352+
await inProgressIndexTasks.concurrentForEach { (_, status) in
353+
switch status {
354+
case .waitingForPreparation(preparationTaskID: _, indexTask: let indexTask),
355+
.preparing(preparationTaskID: _, indexTask: let indexTask),
356+
.updatingIndexStore(updateIndexStoreTask: _, indexTask: let indexTask):
357+
await indexTask.value
368358
}
369-
await taskGroup.waitForAll()
370359
}
371360
index.pollForUnitChangesAndWait()
372361
logger.debug("Done waiting for up-to-date index")
@@ -786,17 +775,9 @@ package final actor SemanticIndexManager {
786775
}
787776
indexTasksWereScheduled(newIndexTasks)
788777
}
789-
let indexTasksImmutable = indexTasks
790778

791779
return Task(priority: priority) {
792-
await withTaskGroup(of: Void.self) { taskGroup in
793-
for indexTask in indexTasksImmutable {
794-
taskGroup.addTask {
795-
await indexTask.value
796-
}
797-
}
798-
await taskGroup.waitForAll()
799-
}
780+
await indexTasks.concurrentForEach { await $0.value }
800781
}
801782
}
802783
}

Sources/SwiftExtensions/AsyncUtils.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ extension Collection where Element: Sendable {
165165
count = indexedResults.count
166166
}
167167
}
168+
169+
/// Invoke `body` for every element in the collection and wait for all calls of `body` to finish
170+
package func concurrentForEach(_ body: @escaping @Sendable (Element) async -> Void) async {
171+
await withTaskGroup(of: Void.self) { taskGroup in
172+
for element in self {
173+
taskGroup.addTask {
174+
await body(element)
175+
}
176+
}
177+
}
178+
}
168179
}
169180

170181
package struct TimeoutError: Error, CustomStringConvertible {

0 commit comments

Comments
 (0)