@@ -15,6 +15,37 @@ import Swift
1515
1616// ==== Task Cancellation ------------------------------------------------------
1717
18+ /// Execute an operation with cancellation handler which will immediately be
19+ /// invoked if the current task is cancelled.
20+ ///
21+ /// This differs from the operation cooperatively checking for cancellation
22+ /// and reacting to it in that the cancellation handler is _always_ and
23+ /// _immediately_ invoked when the task is cancelled. For example, even if the
24+ /// operation is running code which never checks for cancellation, a cancellation
25+ /// handler still would run and give us a chance to run some cleanup code.
26+ ///
27+ /// Does not check for cancellation, and always executes the passed `operation`.
28+ ///
29+ /// This function returns instantly and will never suspend.
30+ @available ( macOS 9999 , iOS 9999 , watchOS 9999 , tvOS 9999 , * )
31+ public func withTaskCancellationHandler< T> (
32+ handler: @Sendable ( ) -> ( ) ,
33+ operation: ( ) async throws -> T
34+ ) async rethrows -> T {
35+ let task = Builtin . getCurrentAsyncTask ( )
36+
37+ guard !_taskIsCancelled( task) else {
38+ // If the current task is already cancelled, run the handler immediately.
39+ handler ( )
40+ return try await operation ( )
41+ }
42+
43+ let record = _taskAddCancellationHandler ( handler: handler)
44+ defer { _taskRemoveCancellationHandler ( record: record) }
45+
46+ return try await operation ( )
47+ }
48+
1849@available ( macOS 9999 , iOS 9999 , watchOS 9999 , tvOS 9999 , * )
1950extension Task {
2051
@@ -57,34 +88,12 @@ extension Task {
5788 }
5889 }
5990
60- /// Execute an operation with cancellation handler which will immediately be
61- /// invoked if the current task is cancelled.
62- ///
63- /// This differs from the operation cooperatively checking for cancellation
64- /// and reacting to it in that the cancellation handler is _always_ and
65- /// _immediately_ invoked when the task is cancelled. For example, even if the
66- /// operation is running code which never checks for cancellation, a cancellation
67- /// handler still would run and give us a chance to run some cleanup code.
68- ///
69- /// Does not check for cancellation, and always executes the passed `operation`.
70- ///
71- /// This function returns instantly and will never suspend.
91+ @available ( * , deprecated, message: " `Task.withCancellationHandler` has been replaced by `withTaskCancellationHandler` and will be removed shortly. " )
7292 public static func withCancellationHandler< T> (
7393 handler: @Sendable ( ) -> ( ) ,
7494 operation: ( ) async throws -> T
7595 ) async rethrows -> T {
76- let task = Builtin . getCurrentAsyncTask ( )
77-
78- guard !_taskIsCancelled( task) else {
79- // If the current task is already cancelled, run the handler immediately.
80- handler ( )
81- return try await operation ( )
82- }
83-
84- let record = _taskAddCancellationHandler ( handler: handler)
85- defer { _taskRemoveCancellationHandler ( record: record) }
86-
87- return try await operation ( )
96+ try await withTaskCancellationHandler ( handler: handler, operation: operation)
8897 }
8998
9099 /// The default cancellation thrown when a task is cancelled.
@@ -95,7 +104,6 @@ extension Task {
95104 // no extra information, cancellation is intended to be light-weight
96105 public init ( ) { }
97106 }
98-
99107}
100108
101109@available ( macOS 9999 , iOS 9999 , watchOS 9999 , tvOS 9999 , * )
0 commit comments