Skip to content

Commit babe6f2

Browse files
committed
[Concurrency] Adopt typed throws and nonisolated(nonsending) in withTaskCancellationHandler
Replace the use of rethrows and #isolation in withTaskCancellationHandler with typed throws and nonisolated(nonsending), respectively. Fixes rdar://146901428.
1 parent 9ea8671 commit babe6f2

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

stdlib/public/Concurrency/TaskCancellation.swift

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,29 @@ import Swift
7474
/// Therefore, if a cancellation handler must acquire a lock, other code should
7575
/// not cancel tasks or resume continuations while holding that lock.
7676
@available(SwiftStdlib 5.1, *)
77+
@export(implementation)
78+
nonisolated(nonsending)
79+
public func withTaskCancellationHandler<T, E>(
80+
operation: () async throws(E) -> T,
81+
onCancel handler: @Sendable () -> Void
82+
) async throws(E) -> T {
83+
// unconditionally add the cancellation record to the task.
84+
// if the task was already cancelled, it will be executed right away.
85+
let record = unsafe Builtin.taskAddCancellationHandler(handler: handler)
86+
defer { unsafe Builtin.taskRemoveCancellationHandler(record: record) }
87+
88+
return try await operation()
89+
}
90+
7791
#if !$Embedded
78-
@backDeployed(before: SwiftStdlib 6.0)
79-
#endif
80-
public func withTaskCancellationHandler<T>(
92+
@available(SwiftStdlib 6.0, *)
93+
@usableFromInline
94+
@abi(func withTaskCancellationHandler<T>(
95+
operation: () async throws -> T,
96+
onCancel handler: @Sendable () -> Void,
97+
isolation: isolated (any Actor)?,
98+
) async rethrows -> T)
99+
func __abi_withTaskCancellationHandler<T>(
81100
operation: () async throws -> T,
82101
onCancel handler: @Sendable () -> Void,
83102
isolation: isolated (any Actor)? = #isolation
@@ -89,6 +108,7 @@ public func withTaskCancellationHandler<T>(
89108

90109
return try await operation()
91110
}
111+
#endif
92112

93113
// Note: hack to stage out @_unsafeInheritExecutor forms of various functions
94114
// in favor of #isolation. The _unsafeInheritExecutor_ prefix is meaningful

test/Concurrency/async_cancellation.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,23 @@ struct SomeFile: Sendable {
2828
func close() {}
2929
}
3030

31+
enum HomeworkError: Error {
32+
case dogAteIt
33+
}
34+
3135
@available(SwiftStdlib 5.1, *)
3236
func test_cancellation_withTaskCancellationHandler(_ anything: Any) async -> PictureData? {
3337
let handle: Task<PictureData, Error> = .init {
3438
let file = SomeFile()
3539

36-
return await withTaskCancellationHandler {
37-
await test_cancellation_guard_isCancelled(file)
38-
} onCancel: {
39-
file.close()
40+
do throws(HomeworkError) {
41+
return try await withTaskCancellationHandler { () throws(HomeworkError) in
42+
await test_cancellation_guard_isCancelled(file)
43+
} onCancel: {
44+
file.close()
45+
}
46+
} catch .dogAteIt {
47+
return PictureData.value("...")
4048
}
4149
}
4250

test/api-digester/stability-concurrency-abi.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ Func withCheckedThrowingContinuation(function:_:) has parameter 0 type change fr
8989
Func withCheckedThrowingContinuation(function:_:) has parameter 1 type change from (_Concurrency.CheckedContinuation<τ_0_0, any Swift.Error>) -> () to Swift.String
9090

9191
// #isolation adoption for cancellation handlers; old APIs are kept ABI compatible
92-
Func withTaskCancellationHandler(operation:onCancel:) has been renamed to Func withTaskCancellationHandler(operation:onCancel:isolation:)
93-
Func withTaskCancellationHandler(operation:onCancel:) has mangled name changing from '_Concurrency.withTaskCancellationHandler<A>(operation: () async throws -> A, onCancel: @Sendable () -> ()) async throws -> A' to '_Concurrency.withTaskCancellationHandler<A>(operation: () async throws -> A, onCancel: @Sendable () -> (), isolation: isolated Swift.Optional<Swift.Actor>) async throws -> A'
92+
Func withTaskCancellationHandler(operation:onCancel:) has been renamed to Func __abi_withTaskCancellationHandler(operation:onCancel:isolation:)
93+
Func withTaskCancellationHandler(operation:onCancel:) has mangled name changing from '_Concurrency.withTaskCancellationHandler<A>(operation: () async throws -> A, onCancel: @Sendable () -> ()) async throws -> A' to '_Concurrency.__abi_withTaskCancellationHandler<A>(operation: () async throws -> A, onCancel: @Sendable () -> (), isolation: isolated Swift.Optional<Swift.Actor>) async throws -> A'
9494

9595
// #isolated was adopted and the old methods kept: $ss31withCheckedThrowingContinuation8function_xSS_yScCyxs5Error_pGXEtYaKlF
9696
Func withCheckedContinuation(function:_:) has been renamed to Func withCheckedContinuation(isolation:function:_:)

0 commit comments

Comments
 (0)