Skip to content

Commit dd10132

Browse files
committed
[Concurrency] Cancelled group should only spawn already cancelled tasks
1 parent 11e3a65 commit dd10132

File tree

5 files changed

+21
-10
lines changed

5 files changed

+21
-10
lines changed

include/swift/ABI/TaskGroup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class alignas(Alignment_TaskGroup) TaskGroup {
3939

4040
/// Upon a future task's completion, offer it to the task group it belongs to.
4141
void offer(AsyncTask *completed, AsyncContext *context);
42+
43+
/// Checks the cancellation status of the group.
44+
bool isCancelled();
4245
};
4346

4447
} // end namespace swift

stdlib/public/Concurrency/Task.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,8 @@ static AsyncTaskAndContext swift_task_create_group_future_commonImpl(
565565
// In a task group we would not have allowed the `add` to create a child anymore,
566566
// however better safe than sorry and `async let` are not expressed as task groups,
567567
// so they may have been spawned in any case still.
568-
if (swift_task_isCancelled(parent))
568+
if (swift_task_isCancelled(parent) ||
569+
(group && group->isCancelled()))
569570
swift_task_cancel(task);
570571

571572
// Initialize task locals with a link to the parent task.

stdlib/public/Concurrency/TaskGroup.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,10 @@ void TaskGroup::offer(AsyncTask *completedTask, AsyncContext *context) {
508508
asImpl(this)->offer(completedTask, context);
509509
}
510510

511+
bool TaskGroup::isCancelled() {
512+
return asImpl(this)->isCancelled();
513+
}
514+
511515
static void fillGroupNextResult(TaskFutureWaitAsyncContext *context,
512516
PollResult result) {
513517
/// Fill in the result value

stdlib/public/Concurrency/TaskGroup.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -355,12 +355,12 @@ public struct TaskGroup<ChildTaskResult> {
355355
_taskGroupIsEmpty(_group)
356356
}
357357

358-
/// Cancel all the remaining tasks in the group.
359-
///
360-
/// A cancelled group will not will NOT accept new tasks being added into it.
358+
/// Cancel all the remaining, and future, tasks in the group.
361359
///
362-
/// Any results, including errors thrown by tasks affected by this
363-
/// cancellation, are silently discarded.
360+
/// A cancelled group will not will create new tasks when the `asyncUnlessCancelled`,
361+
/// function is used. It will, however, continue to create tasks when the plain `async`
362+
/// function is used. Such tasks will be created yet immediately cancelled, allowing
363+
/// the tasks to perform some short-cut implementation, if they are responsive to cancellation.
364364
///
365365
/// This function may be called even from within child (or any other) tasks,
366366
/// and will reliably cause the group to become cancelled.

test/Concurrency/Runtime/async_taskgroup_cancel_then_spawn.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@ func test_taskGroup_cancel_then_add() async {
3737
let none = await group.next()
3838
print("next second: \(none)") // CHECK: next second: nil
3939

40-
group.spawn { 3 }
41-
print("added third, unconditionally") // CHECK: added third, unconditionally
42-
print("group isCancelled: \(group.isCancelled)") // CHECK: group isCancelled: true
43-
40+
group.spawn {
41+
print("child task isCancelled: \(Task.isCancelled)") // CHECK: child task isCancelled: true
42+
return 3
43+
}
4444
let three = await group.next()!
4545
print("next third: \(three)") // CHECK: next third: 3
4646

47+
print("added third, unconditionally") // CHECK: added third, unconditionally
48+
print("group isCancelled: \(group.isCancelled)") // CHECK: group isCancelled: true
49+
4750
return one + (none ?? 0)
4851
}
4952

0 commit comments

Comments
 (0)