Skip to content

[6.2][Docs] TaskGroup docs improvements & reorganization #82984

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 5 commits into from
Jul 11, 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
53 changes: 27 additions & 26 deletions stdlib/public/Concurrency/DiscardingTaskGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import Swift
/// best applied in situations where the result of a child task is some form
/// of side-effect.
///
/// A group waits for all of its child tasks
/// to complete before it returns. Even cancelled tasks must run until
/// A group *always* waits for all of its child tasks
/// to complete before it returns. Even canceled tasks must run until
/// completion before this function returns.
/// Cancelled child tasks cooperatively react to cancellation and attempt
/// Canceled child tasks cooperatively react to cancellation and attempt
/// to return as early as possible.
/// After this function returns, the task group is always empty.
///
Expand All @@ -41,6 +41,8 @@ import Swift
/// // guaranteed that slow-task has completed and the group is empty & destroyed
/// ```
///
/// Refer to ``TaskGroup`` documentation for detailed discussion of semantics shared between all task groups.
///
/// Task Group Cancellation
/// =======================
///
Expand All @@ -65,6 +67,7 @@ import Swift
/// For tasks that need to handle cancellation by throwing an error,
/// use the `withThrowingDiscardingTaskGroup(returning:body:)` method instead.
///
/// - SeeAlso: ``TaskGroup``
/// - SeeAlso: ``withThrowingDiscardingTaskGroup(returning:body:)``
@available(SwiftStdlib 5.9, *)
#if !hasFeature(Embedded)
Expand Down Expand Up @@ -131,9 +134,7 @@ public func _unsafeInheritExecutor_withDiscardingTaskGroup<GroupResult>(
/// and mutation operations can't be performed
/// from a concurrent execution context like a child task.
///
/// ### Task execution order
/// Tasks added to a task group execute concurrently, and may be scheduled in
/// any order.
/// Refer to ``TaskGroup`` documentation for detailed discussion of semantics shared between all task groups.
///
/// ### Discarding behavior
/// A discarding task group eagerly discards and releases its child tasks as
Expand All @@ -142,18 +143,18 @@ public func _unsafeInheritExecutor_withDiscardingTaskGroup<GroupResult>(
/// be the case with a ``TaskGroup``.
///
/// ### Cancellation behavior
/// A discarding task group becomes cancelled in one of the following ways:
/// A discarding task group becomes canceled in one of the following ways:
///
/// - when ``cancelAll()`` is invoked on it,
/// - when the ``Task`` running this task group is cancelled.
/// - when the ``Task`` running this task group is canceled.
///
/// Since a `DiscardingTaskGroup` is a structured concurrency primitive, cancellation is
/// automatically propagated through all of its child-tasks (and their child
/// tasks).
///
/// A cancelled task group can still keep adding tasks, however they will start
/// being immediately cancelled, and may act accordingly to this. To avoid adding
/// new tasks to an already cancelled task group, use ``addTaskUnlessCancelled(priority:body:)``
/// A canceled task group can still keep adding tasks, however they will start
/// being immediately canceled, and may act accordingly to this. To avoid adding
/// new tasks to an already canceled task group, use ``addTaskUnlessCancelled(priority:body:)``
/// rather than the plain ``addTask(priority:body:)`` which adds tasks unconditionally.
///
/// For information about the language-level concurrency model that `DiscardingTaskGroup` is part of,
Expand Down Expand Up @@ -204,7 +205,7 @@ public struct DiscardingTaskGroup {
/// If you add a task to a group after canceling the group,
/// that task is canceled immediately after being added to the group.
///
/// Immediately cancelled child tasks should therefore cooperatively check for and
/// Immediately canceled child tasks should therefore cooperatively check for and
/// react to cancellation, e.g. by throwing an `CancellationError` at their
/// earliest convenience, or otherwise handling the cancellation.
///
Expand Down Expand Up @@ -245,10 +246,10 @@ extension DiscardingTaskGroup: Sendable { }
/// best applied in situations where the result of a child task is some form
/// of side-effect.
///
/// A group waits for all of its child tasks
/// to complete before it returns. Even cancelled tasks must run until
/// A group *always* waits for all of its child tasks
/// to complete before it returns. Even canceled tasks must run until
/// completion before this function returns.
/// Cancelled child tasks cooperatively react to cancellation and attempt
/// Canceled child tasks cooperatively react to cancellation and attempt
/// to return as early as possible.
/// After this function returns, the task group is always empty.
///
Expand All @@ -264,6 +265,8 @@ extension DiscardingTaskGroup: Sendable { }
/// // guaranteed that slow-task has completed and the group is empty & destroyed
/// ```
///
/// Refer to ``TaskGroup`` documentation for detailed discussion of semantics shared between all task groups.
///
/// Task Group Cancellation
/// =======================
///
Expand Down Expand Up @@ -411,9 +414,7 @@ public func _unsafeInheritExecutor_withThrowingDiscardingTaskGroup<GroupResult>(
/// and mutation operations can't be performed
/// from a concurrent execution context like a child task.
///
/// ### Task execution order
/// Tasks added to a task group execute concurrently, and may be scheduled in
/// any order.
/// Refer to ``TaskGroup`` documentation for detailed discussion of semantics shared between all task groups.
///
/// ### Discarding behavior
/// A discarding task group eagerly discards and releases its child tasks as
Expand All @@ -422,20 +423,20 @@ public func _unsafeInheritExecutor_withThrowingDiscardingTaskGroup<GroupResult>(
/// be the case with a ``TaskGroup``.
///
/// ### Cancellation behavior
/// A throwing discarding task group becomes cancelled in one of the following ways:
/// A throwing discarding task group becomes canceled in one of the following ways:
///
/// - when ``cancelAll()`` is invoked on it,
/// - when an error is thrown out of the `withThrowingDiscardingTaskGroup { ... }` closure,
/// - when the ``Task`` running this task group is cancelled.
/// - when the ``Task`` running this task group is canceled.
///
/// But also, and uniquely in *discarding* task groups:
/// - when *any* of its child tasks throws.
///
/// The group becoming cancelled automatically, and cancelling all of its child tasks,
/// The group becoming canceled automatically, and cancelling all of its child tasks,
/// whenever *any* child task throws an error is a behavior unique to discarding task groups,
/// because achieving such semantics is not possible otherwise, due to the missing `next()` method
/// on discarding groups. Accumulating task groups can implement this by manually polling `next()`
/// and deciding to `cancelAll()` when they decide an error should cause the group to become cancelled,
/// and deciding to `cancelAll()` when they decide an error should cause the group to become canceled,
/// however a discarding group cannot poll child tasks for results and therefore assumes that child
/// task throws are an indication of a group wide failure. In order to avoid such behavior,
/// use a ``DiscardingTaskGroup`` instead of a throwing one, or catch specific errors in
Expand All @@ -445,9 +446,9 @@ public func _unsafeInheritExecutor_withThrowingDiscardingTaskGroup<GroupResult>(
/// automatically propagated through all of its child-tasks (and their child
/// tasks).
///
/// A cancelled task group can still keep adding tasks, however they will start
/// being immediately cancelled, and may act accordingly to this. To avoid adding
/// new tasks to an already cancelled task group, use ``addTaskUnlessCancelled(priority:body:)``
/// A canceled task group can still keep adding tasks, however they will start
/// being immediately canceled, and may act accordingly to this. To avoid adding
/// new tasks to an already canceled task group, use ``addTaskUnlessCancelled(priority:body:)``
/// rather than the plain ``addTask(priority:body:)`` which adds tasks unconditionally.
///
/// For information about the language-level concurrency model that `DiscardingTaskGroup` is part of,
Expand Down Expand Up @@ -496,7 +497,7 @@ public struct ThrowingDiscardingTaskGroup<Failure: Error> {
/// If you add a task to a group after canceling the group,
/// that task is canceled immediately after being added to the group.
///
/// Immediately cancelled child tasks should therefore cooperatively check for and
/// Immediately canceled child tasks should therefore cooperatively check for and
/// react to cancellation, e.g. by throwing an `CancellationError` at their
/// earliest convenience, or otherwise handling the cancellation.
///
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/Concurrency/TaskCancellation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ import Swift
/// ### Execution order and semantics
/// The `operation` closure is always invoked, even when the
/// `withTaskCancellationHandler(operation:onCancel:)` method is called from a task
/// that was already cancelled.
/// that was already canceled.
///
/// When `withTaskCancellationHandler(operation:onCancel:)` is used in a task that has already been
/// cancelled, the cancellation handler will be executed
/// canceled, the cancellation handler will be executed
/// immediately before the `operation` closure gets to execute.
///
/// This allows the cancellation handler to set some external "cancelled" flag
/// This allows the cancellation handler to set some external "canceled" flag
/// that the operation may be *atomically* checking for in order to avoid
/// performing any actual work once the operation gets to run.
///
Expand Down
Loading