-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[5.5] Handle multiple awaits and suspend-on-exit for async let tasks. #38579
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
DougGregor
merged 2 commits into
swiftlang:release/5.5
from
jckarter:async-let-multi-suspend-5.5
Jul 23, 2021
Merged
[5.5] Handle multiple awaits and suspend-on-exit for async let tasks. #38579
DougGregor
merged 2 commits into
swiftlang:release/5.5
from
jckarter:async-let-multi-suspend-5.5
Jul 23, 2021
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@swift-ci Please test |
Build failed |
Build failed |
5c50ed1
to
e47ab71
Compare
@swift-ci Please test |
ktoso
approved these changes
Jul 23, 2021
Build failed |
Change the code generation patterns for `async let` bindings to use an ABI based on the following functions: - `swift_asyncLet_begin`, which starts an `async let` child task, but which additionally now associates the `async let` with a caller-owned buffer to receive the result of the task. This is intended to allow the task to emplace its result in caller-owned memory, allowing the child task to be deallocated after completion without invalidating the result buffer. - `swift_asyncLet_get[_throwing]`, which replaces `swift_asyncLet_wait[_throwing]`. Instead of returning a copy of the value, this entry point concerns itself with populating the local buffer. If the buffer hasn't been populated, then it awaits completion of the task and emplaces the result in the buffer; otherwise, it simply returns. The caller can then read the result out of its owned memory. These entry points are intended to be used before every read from the `async let` binding, after which point the local buffer is guaranteed to contain an initialized value. - `swift_asyncLet_finish`, which replaces `swift_asyncLet_end`. Unlike `_end`, this variant is async and will suspend the parent task after cancelling the child to ensure it finishes before cleaning up. The local buffer will also be deinitialized if necessary. This is intended to be used on exit from an `async let` scope, to handle cleaning up the local buffer if necessary as well as cancelling, awaiting, and deallocating the child task. - `swift_asyncLet_consume[_throwing]`, which combines `get` and `finish`. This will await completion of the task, leaving the result value in the result buffer (or propagating the error, if it throws), while destroying and deallocating the child task. This is intended as an optimization for reading `async let` variables that are read exactly once by their parent task. To avoid an epoch break with existing swiftinterfaces and ABI clients, the old builtins and entry points are kept intact for now, but SILGen now only generates code using the new interface. This new interface fixes several issues with the old async let codegen, including use-after-free crashes if the `async let` was never awaited, and the inability to read from an `async let` variable more than once. rdar://77855176
This isn't implemented. It would never make sense for escaping captures of `async let` values, because doing so would either involve an implicit awaiting of the value on capture, or else stretching the lifetime of the task past its scope. In nonescaping contexts, and in nested `async let` expressions, it might be implementable in the future. rdar://80043610
e47ab71
to
b1a9253
Compare
@swift-ci Please test |
@swift-ci Please nominate |
DougGregor
approved these changes
Jul 23, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description: Implements a new ABI for
async let
that can support multiple awaits of the same binding, cancelling and suspending the task when it is still running on scope exit, and efficiently consuming and deallocating the task in one step in the common case.Scope: Completes the implementation of
async let
.Issues: rdar://77855176, rdar://80043610
Reviewed by: @ktoso
Risk: Moderate; it's a substantial reimplementation of the feature. However, impact on the rest of the compiler and runtime should be minimal.