Swift Structured Concurrency: Task cancellation propagation across actor boundaries
0 reputation · 15 May 2021, 07:53 UTC
0 reputation · 15 May 2021, 07:53 UTC
Swift's cooperative cancellation model ensures that cancellation propagates from parent tasks to child tasks created via async let or TaskGroup. This mechanism relies on the task hierarchy to signal termination to all nested operations.
When asynchronous operations transition across different actor isolation boundaries, the timing and priority of this propagation can vary. There is uncertainty regarding how the system handles the latency between a parent task being marked as cancelled and the child task on a separate actor receiving that signal, especially when the actor's mailbox is heavily congested.
Given a high-load environment using Swift 5.10+, what is the guaranteed behavior for cancellation propagation across actor boundaries? Does the system prioritize the cancellation signal over pending messages in the actor's queue?
35275 reputation · 15 May 2021, 13:35 UTC
In Swift 5.10+, cancellation propagation is guaranteed to be independent of actor mailbox queuing. When a parent task is cancelled, the cancellation state is propagated to all child tasks in the hierarchy immediately, regardless of which actor those children are isolated to.
The critical distinction in Swift's concurrency model is that cancellation is a state change on the Task object, not a message sent to an actor's mailbox. Because the cancellation signal does not travel through the actor's queue, it cannot be delayed by a congested mailbox.
While the cancellation state is updated instantly, the effect of that cancellation depends on the task's current status:
Task.isCancelled or calling try Task.checkCancellation().true.To ensure your system remains responsive under heavy actor load, implement the following cooperative patterns:
try Task.checkCancellation() as the very first line of any actor-isolated function. This ensures that tasks that spent significant time waiting in a congested mailbox terminate immediately without performing expensive work.You can verify this behavior by creating a TaskGroup that spawns child tasks on a specific actor. Saturate that actor with several long-running synchronous operations to create a backlog. Cancel the parent task and observe that the child tasks, once they finally begin execution, immediately report Task.isCancelled == true.
Missing Diagnostic Detail: To provide a more tailored recommendation, are you using DistributedActor (across network boundaries) or standard local actor types? Cancellation propagation for Distributed Actors involves different transport-layer mechanisms.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.