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

Wallacy wallacyf at gmail.com
Mon Aug 21 14:40:49 CDT 2017


Based on these same concerns, how to do this using async/await ?

func process() -> Void) {

    loadWebResource("bigData.txt") { dataResource in
	  //....
    }

    printf("BigData Scheduled to load")
    loadWebResource("smallData.txt") { dataResource in
	  //....
    }
    printf("SmallData Scheduled to load")

}


Small data usually will finish first using GCD, but using async/await apear
to be no way to schedule other things (on other Queue maybe) in the same
function. I now this is about parallelism, but this is something that we
will lose about GCD.

I know the parallelism is not the focus, but is something important for the
people migration from GCD.

Maybe:

yield loadWebResource("bigData.txt") // has a void return.

yield loadWebResource("smallData.txt") // has a void return.


I don't know if yield is the right keyword here but i think is important
some way to "not" wait.

Em seg, 21 de ago de 2017 às 15:04, Adam Kemp via swift-evolution <
swift-evolution at swift.org> escreveu:

> On Aug 18, 2017, at 8:38 PM, Chris Lattner <clattner at nondot.org> wrote:
>
> On Aug 18, 2017, at 2:09 PM, Adam Kemp <adam.kemp at apple.com> wrote:
>
> Maybe I’m still missing something, but how does this help when you are
> interacting only with Swift code? If I were to write an asynchronous method
> in Swift then how could I do the same thing that you propose that the
> Objective-C importer do? That is, how do I write my function such that it
> calls back on the same queue?
>
>
> You’re right: if you’re calling something written in Swift, the ObjC
> importer isn’t going to help you.
>
> However, if you’re writing an async function in Swift, then it is
> reasonable for us to say what the convention is and expect you to follow
> it.  Async/await doesn’t itself help you implement an async operation: it
> would be turtles all the way down… until you get to GCD, which is where you
> do the async thing.
>
> As such, as part of rolling out async/await in Swift, I’d expect that GCD
> would introduce new API or design patterns to support doing the right thing
> here.  That is TBD as far as the proposal goes, because it doesn’t go into
> runtime issues.
>
>
> The point I’m trying to make is that this is so important that I don’t
> think it’s wise to leave it up to possible future library improvements, and
> especially not to convention. Consider this example again from your
> proposal:
>
> @IBAction func buttonDidClick(sender:AnyObject) {
>     doSomethingOnMainThread();
>     beginAsync {
>         let image = await processImage()
>         imageView.image = image
>     }
>     doSomethingElseOnMainThread();
> }
>
> The line that assigns the image to the image view is very likely running
> on the wrong thread. That code looks simple, but it is not safe. You would
> have to insert a line like your other examples to ensure it’s on the right
> thread:
>
> @IBAction func buttonDidClick(sender:AnyObject) {
>     doSomethingOnMainThread();
>     beginAsync {
>
>         let image = await processImage()
>
>         await DispatchQueue.main.asyncCoroutine()
>         imageView.image = image
>     }
>     doSomethingElseOnMainThread();
> }
>
>
> You would have to litter your code with that kind of stuff just in case
> you’re on the wrong thread because there’s no way to tell where you’ll end
> up after the await. In fact, this feature would make it much easier to end
> up calling back on different queues in different circumstances because it
> makes queue hopping invisible. From another example:
>
> func processImageData1() async -> Image {
>
>   let dataResource  = await loadWebResource("dataprofile.txt")
>
>   let imageResource = await loadWebResource("imagedata.dat")
>   let imageTmp      = await decodeImage(dataResource, imageResource)
>   let imageResult   =  await dewarpAndCleanupImage(imageTmp)
>   return imageResult
> }
>
>
> Which queue does a caller end up in? Whichever queue that last awaited
> call gives you. This function does nothing to try to ensure that you always
> end up on the same queue. If someone changes the code by adding or removing
> one of those await calls then the final callback queue would change. If
> there were conditionals in there that changed the code flow at runtime then
> you could end up calling back on different queues depending on some runtime
> state.
>
> IMO this would make doing safe async programming actually more difficult
> to get right. It would be tedious and error prone. This simplified
> async/await model may work well for JavaScript, which generally doesn’t
> have shared mutable state across threads, but it seems dangerous in a
> language that does.
>
> This isn’t a fair transformation though, and isn’t related to whether
> futures is part of the library or language.  The simplification you got
> here is by making IBAction’s implicitly async.  I don’t see that that is
> possible, since they have a very specific calling convention (which returns
> void) and are invoked by objc_msgSend.  OTOH, if it were possible to do
> this, it would be possible to do it with the proposal as outlined.
>
>
> I didn’t mean to imply that all IBActions implicitly async. I just allowed
> for an entire method to be async without being awaitable. In C# an async
> void function is a “fire and forget” function. It executes in the context
> of the caller’s thread/stack up until the first await, at which point it
> returns to the caller like normal. The continuation just happens without
> the caller knowing about it. The method signature is the same, and they are
> callable by code that is unaware of async/await. C# supports async void
> functions specifically for the event handler use case (and it is generally
> discouraged for all other use cases).
>
> Your proposal already has async void methods, but they are awaitable. You
> still need some ability to call an async method from a non-async method.
> The way that you solved that is a special function (beginAsync), which as I
> described earlier has some issues with readability. The other approach is
> to have some way to decorate the entire function as “fire and forget”.
>
> The reason I linked these to library support is that the way that C# makes
> this distinction is that an awaitable function must return a type that is
> awaitable (it’s actually the traits of the return type that make it
> awaitable, not the async keyword; you can await a function that is not
> marked async). In C# a void method is not awaitable, even if it is marked
> async.
>
> However, you’re right that these concepts don’t necessarily have to be
> linked, and I shouldn’t have conflated them. You could also use some other
> syntax to mark a non-awaitable method that is itself async. Maybe a
> different keyword (deliberately ugly):
>
> @IBAction fire_and_forget_async func buttonDidClick(sender:AnyObject) { … }
>
>
> To be clear, although this particular problem can be solved without
> library support I think that both this problem and the queue-hopping
> problem could be better solved by using a model closer to C#’s, with a
> richer compiler transform that uses the return type. Swift could do this
> using an awaitable protocol.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170821/6f9bca1e/attachment.html>


More information about the swift-evolution mailing list