Skip to content

Conversation

@ktoso
Copy link
Contributor

@ktoso ktoso commented Nov 21, 2025

Introduce a proposal for task cancellation shields to allow certain code to execute regardless of task cancellation status.

Implementation WIP PR: swiftlang/swift#85637

Introduce a proposal for task cancellation shields to allow certain code to execute regardless of task cancellation status.

Implementation WIP PR: swiftlang/swift#85637
Updated reference to SE-0493 to include a link.
Comment on lines +76 to +84
public func withTaskCancellationShield<T, E>(
_ operation: () throws(E) -> T,
file: String = #fileID, line: Int = #line
) throws(E) -> T

public nonisolated(nonsending) func withTaskCancellationShield<T, E>(
_ operation: nonisolated(nonsending) () async throws(E) -> T, // FIXME: order of attrs
file: String = #fileID, line: Int = #line
) async throws(E) -> T
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we give the generic types a slightly more descriptive name so it shows up nicely in the docs. On the PR that introduced nonisolated(nonsending) to the withTaskCancellationHandler methods we used Return and Failure for those two generic types.

Suggested change
public func withTaskCancellationShield<T, E>(
_ operation: () throws(E) -> T,
file: String = #fileID, line: Int = #line
) throws(E) -> T
public nonisolated(nonsending) func withTaskCancellationShield<T, E>(
_ operation: nonisolated(nonsending) () async throws(E) -> T, // FIXME: order of attrs
file: String = #fileID, line: Int = #line
) async throws(E) -> T
public func withTaskCancellationShield<Result, Failure>(
_ operation: () throws(Failure) -> Result,
file: String = #fileID, line: Int = #line
) throws(Failure) -> Result
public nonisolated(nonsending) func withTaskCancellationShield<Result, Failure>(
_ operation: nonisolated(nonsending) () async throws(Failure) -> Result, // FIXME: order of attrs
file: String = #fileID, line: Int = #line
) async throws(Failure) -> Result


func cleanup() {
withTaskCancellationShield {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this missing a slowOperation call here?

}
```

However if a child task were to be cancelled explicitly the shield of the parent, has no effect on the child itself becoming cancelled:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line needs editing.


This is sub-optimal for a few reasons:

- We are introducing an unstructured task which needs to be scheduled to execute, and therefore delaying the timing when a cleanup may be executed,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory Task.immediate can be used to avoid the scheduling delay in a manual cancellation shield.

Of course that still doesn't work for synchronous code, still needs to pay the task creation cost, etc. So it doesn't affect the overall point of a builtin cancellation shield being preferable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 – the proposal should note this and contrast the new functionality with the current 'best' available status quo behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants