Skip to content

Commit 802d662

Browse files
authored
[SE-0317] Update TaskGroup.async to TaskGroup.addTask (#2534)
1 parent 686b10e commit 802d662

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

proposals/0317-async-let.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ func makeDinner() async -> Meal {
4242
// Create a task group to scope the lifetime of our three child tasks
4343
return try await withThrowingTaskGroup(of: CookingTask.self) { group in
4444
// spawn three cooking tasks and execute them in parallel:
45-
group.async {
45+
group.addTask {
4646
CookingTask.veggies(try await chopVegetables())
4747
}
48-
group.async {
48+
group.addTask {
4949
CookingTask.meat(await marinateMeat())
5050
}
51-
group.async {
51+
group.addTask {
5252
CookingTask.oven(await preheatOven(temperature: 350))
5353
}
5454

@@ -180,9 +180,9 @@ The child-task created to initialize the `async let` by default runs on the glob
180180

181181
> Customizing the execution context of async lets is a future direction we are likely to explore with the introduction of Custom Executors.
182182
183-
The initializer of the `async let` can be thought of as a closure that runs the code contained within it in a separate task, very much like the explicit `group.async { <work here/> }` API of task groups.
183+
The initializer of the `async let` can be thought of as a closure that runs the code contained within it in a separate task, very much like the explicit `group.addTask { <work here/> }` API of task groups.
184184

185-
Similarly to the `group.async()` function, the closure is `@Sendable` and `nonisolated`, meaning that it cannot access non-sendable state of the enclosing context. For example, it will result in a compile-time error, preventing a potential race condition, for a `async let` initializer to attempt mutating a closed-over variable:
185+
Similarly to the `group.addTask()` function, the closure is `@Sendable` and `nonisolated`, meaning that it cannot access non-sendable state of the enclosing context. For example, it will result in a compile-time error, preventing a potential race condition, for a `async let` initializer to attempt mutating a closed-over variable:
186186

187187
```swift
188188
var localText: [String] = ...
@@ -372,7 +372,7 @@ This is the same as spawning a number of child-tasks in a task group, and not co
372372

373373
```swift
374374
try await withThrowingTaskGroup(of: Int.self) { group in
375-
group.async { throw Boom() }
375+
group.addTask { throw Boom() }
376376

377377
return 0 // we didn't care about the child-task at all(!)
378378
} // returns 0
@@ -414,7 +414,7 @@ Cancellation propagates recursively through the task hierarchy from parent to ch
414414

415415
Because tasks spawned by `async let` are child tasks, they naturally participate in their parent's cancellation.
416416

417-
Cancellation of the parent task means that the context in which the `async let` declarations exist is cancelled, and any tasks created by those declarations will be cancelled as well. Because cancellation in Swift is co-operative, it does not prevent the spawning of tasks, however tasks spawned from a cancelled context are *immediately* marked as cancelled. This exhibits the same semantics as `TaskGroup.async` which, when used from an already cancelled task, _will_ spawn more child-tasks, however they will be immediately created as cancelled tasks — which they can inspect by calling `Task.isCancelled`.
417+
Cancellation of the parent task means that the context in which the `async let` declarations exist is cancelled, and any tasks created by those declarations will be cancelled as well. Because cancellation in Swift is co-operative, it does not prevent the spawning of tasks, however tasks spawned from a cancelled context are *immediately* marked as cancelled. This exhibits the same semantics as `TaskGroup.addTask` which, when used from an already cancelled task, _will_ spawn more child-tasks, however they will be immediately created as cancelled tasks — which they can inspect by calling `Task.isCancelled`.
418418

419419
We can observe this in the following example:
420420

@@ -459,7 +459,7 @@ func toyParallelMap<A, B>(_ items: [A], f: (A) async -> B) async -> [B] {
459459
// spawn off processing all `f` mapping functions in parallel
460460
// in reality, one might want to limit the "width" of these
461461
for i in items.indices {
462-
group.async { (i, await f(items[i])) }
462+
group.addTask { (i, await f(items[i])) }
463463
}
464464

465465
// collect all results
@@ -494,8 +494,8 @@ For example, the `race(left:right:)` function shown below, runs two child tasks
494494
```swift
495495
func race(left: () async -> Int, right: () async -> Int) async -> Int {
496496
await withTaskGroup(of: Int.self) { group in
497-
group.async { left() }
498-
group.async { right() }
497+
group.addTask { left() }
498+
group.addTask { right() }
499499

500500
let first = await group.next()! // !-safe, there is at-least one result to collect
501501
group.cancelAll() // cancel the other task

0 commit comments

Comments
 (0)