[swift-evolution] [Concurrency] async/await + actors

Félix Cloutier felixcloutier at icloud.com
Fri Aug 18 01:59:52 CDT 2017


I'm glad to see this moving forward. I have a few questions and comments.

First, I'd like it if someone could clarify for me what beginAsync and suspendAsync "actually do", and how they interact with `async` functions. I'm throwing a lot of good will at this but my brain is still fairly imperatively-wired, so let me try to rephrase this in more procedural terms and let's see if I got anything wrong.

My understanding is that an `async` function takes its continuation closure as a hidden parameter. That closure accepts as a parameter the "asynchronous return type" of the function. In other words:

    func foo() async -> Int

Can (give or take error handling and parameter names) be rewritten as:

    func foo(completion: (Int) -> Void) -> Void

This is fairly straightforward; it's just the inverse transformation of what's shown in the conversion section <https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619#conversion-of-imported-objective-c-apis>.

The purpose of `beginAsync` is to start an `async` function while firewalling against the propagation of the `async` keyword to the caller. `beginAsync` does not return a value. By the time `beginAsync` returns, whatever continuation closure was generated for the `body` parameter has been passed off to someone else and some scheduling mechanism has a reference to it and will call it later. That's not giving me too much trouble either.

I'm somewhat bugged by `suspendAsync`. My understanding is that it allows you to take a synchronous function which accepts a callback and turn it into an asynchronous one, where "asynchronous" means "continuation-driven" more that "asynchronously executing", because something like `let foo: Int = await suspendAsync { $0(42) }` looks like it should be legal (although not particularly useful).

The interaction of `suspendAsync` and `await` is that `suspendAsync`, like any other `async` function, accepts a hidden closure parameter, and `await` takes the rest of the function and turns it into a continuation closure to pass as that hidden parameter. The explicit parameters of `suspendAsync` are closures that accept the continuation (either for success or failure), so `suspendAsync` is the primitive that's responsible for translating the rest of an `async` function into something that you can pass as a callback.

That seems to make sense to me (although I might have it wrong), but I'm having trouble with the terminology. I'm not trying to start a bike shed debate here; it's simply not immediately clear to me what "suspendAsync" means for a function that seems more about starting an "old world" asynchronous task than suspending anything (let alone an asynchronous thing).


Flurry of small questions:

* How does this interact with reference counting? The `suspendAsync` functions mark that its closures are @escaping,  yet `async` functions don't seem to need to write `self` to access members. What are the dangers?
* Are there ObjC functions right now whose continuation resembles `void(^)(Image* __nullable, Image* __nullable, NSError
* error))`, but for which only one of either the first or second Image parameter has a value if the call succeeded?
* in the DispatchQueue example, is there a meaningful difference between `syncCoroutine` and `asyncCoroutine`? Seems to me that `sync` is currently useful when you need your result before you return, but that doesn't really make sense to me in the context of an async function. Barring deadlocks in the synchronous version, the calling async function should return at the same time in both cases.
* Nit: the DispatchQueue example probably means `self.async`, and probably means `{ continuation() }` (and if not, someone needs to explain me what's going on).


The question where I just can't not get ahead of myself: you wrote that the underlying support can be used to implement generators. This is a feature that is very close to my heart. I understand that the compiler work that turns part of a function into a closure can be reused there; what about the higher-level stuff, do we foresee a set of more or less analogous keywords for generators, or should the async/await terminology be good enough to encompass any type of coroutine-based execution?


Thanks!

Félix

> Le 17 août 2017 à 15:25, Chris Lattner via swift-evolution <swift-evolution at swift.org> a écrit :
> 
>> 
>> On Aug 17, 2017, at 3:24 PM, Chris Lattner <clattner at nondot.org <mailto:clattner at nondot.org>> wrote:
>> 
>> Hi all,
>> 
>> As Ted mentioned in his email, it is great to finally kick off discussions for what concurrency should look like in Swift.  This will surely be an epic multi-year journey, but it is more important to find the right design than to get there fast.
>> 
>> I’ve been advocating for a specific model involving async/await and actors for many years now.  Handwaving only goes so far, so some folks asked me to write them down to make the discussion more helpful and concrete.  While I hope these ideas help push the discussion on concurrency forward, this isn’t in any way meant to cut off other directions: in fact I hope it helps give proponents of other designs a model to follow: a discussion giving extensive rationale, combined with the long term story arc to show that the features fit together.
>> 
>> Anyway, here is the document, I hope it is useful, and I’d love to hear comments and suggestions for improvement:
>> https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782 <https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782>
> 
> Oh, also, one relatively short term piece of this model is a proposal for adding an async/await model to Swift (in the form of general coroutine support).  Joe Groff and I wrote up a proposal for this, here:
> https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619 <https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619>
> 
> and I have a PR with the first half of the implementation here:
> https://github.com/apple/swift/pull/11501 <https://github.com/apple/swift/pull/11501>
> 
> The piece that is missing is code generation support.
> 
> -Chris
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170817/9a7bce71/attachment.html>


More information about the swift-evolution mailing list