@@ -22,27 +22,51 @@ import Swift
2222/// and reacting to it in that the cancellation handler is _always_ and
2323/// _immediately_ invoked when the task is canceled. For example, even if the
2424/// operation is running code that never checks for cancellation, a cancellation
25- /// handler still runs and provides a chance to run some cleanup code.
25+ /// handler still runs and provides a chance to run some cleanup code:
26+ ///
27+ /// ```
28+ /// await withTaskCancellationHandler {
29+ /// var sum = 0
30+ /// while condition {
31+ /// sum += 1
32+ /// }
33+ /// return sum
34+ /// } onCancel: {
35+ /// // This onCancel closure might execute concurrently with the operation.
36+ /// condition.cancel()
37+ /// }
38+ /// ```
39+ ///
40+ /// ### Execution order and semantics
41+ /// The `operation` closure is always invoked, even when the
42+ /// `withTaskCancellationHandler(operation:onCancel:)` method is called from a task
43+ /// that was already cancelled.
44+ ///
45+ /// When `withTaskCancellationHandler(operation:onCancel:)` is used in a task that has already been
46+ /// cancelled, the cancellation handler will be executed
47+ /// immediately before the `operation` closure gets to execute.
48+ ///
49+ /// This allows the cancellation handler to set some external "cancelled" flag
50+ /// that the operation may be *atomically* checking for in order to avoid
51+ /// performing any actual work once the operation gets to run.
52+ ///
53+ /// The `operation` closure executes on the calling execution context, and doesn't
54+ /// suspend or change execution context unless code contained within the closure
55+ /// does so. In other words, the potential suspension point of the
56+ /// `withTaskCancellationHandler(operation:onCancel:)` never suspends by itself before
57+ /// executing the operation.
58+ ///
59+ /// If cancellation occurs while the operation is running, the cancellation
60+ /// handler executes *concurrently* with the operation.
61+ ///
62+ /// ### Cancellation handlers and locks
2663///
2764/// Cancellation handlers which acquire locks must take care to avoid deadlock.
2865/// The cancellation handler may be invoked while holding internal locks
2966/// associated with the task or other tasks. Other operations on the task, such
3067/// as resuming a continuation, may acquire these same internal locks.
3168/// Therefore, if a cancellation handler must acquire a lock, other code should
3269/// not cancel tasks or resume continuations while holding that lock.
33- ///
34- /// Doesn't check for cancellation, and always executes the passed `operation`.
35- ///
36- /// The `operation` executes on the calling execution context and does not suspend by itself,
37- /// unless the code contained within the closure does. If cancellation occurs while the
38- /// operation is running, the cancellation `handler` will execute *concurrently* with the `operation`.
39- ///
40- /// ### Already cancelled tasks
41- /// When `withTaskCancellationHandler` is used in a `Task` that has already been cancelled,
42- /// the `onCancel` cancellation ``handler`` will be executed immediately before operation gets
43- /// to execute. This allows the cancellation handler to set some external "cancelled" flag that the
44- /// operation may be *atomically* checking for in order to avoid performing any actual work once
45- /// the operation gets to run.
4670@_unsafeInheritExecutor // the operation runs on the same executor as we start out with
4771@available ( SwiftStdlib 5 . 1 , * )
4872@backDeployed ( before: SwiftStdlib 5.8 )
0 commit comments