[swift-evolution] New async keyword usage

Wallacy wallacyf at gmail.com
Sat Aug 26 23:08:28 CDT 2017


Chris's proposal is very explicit about the advantages of the async/await
over the Future/Task, we don't need to rephrase here. The most obvious
advantage of course is because "await" does not block the execution
(Future.get() does).

And the whole proposal about async/await/actors is very, very good!
Except... When talks about the need to implement Future class as part of
the standard library! Like said on async/await proposal, the "Future" needs
another proposal to adress the details. But describ only one "good" feature
of the "Future" over the async/await:

...
"allow parallel execution, by moving await from the call to the result when
it is needed, and wrapping the parallel calls in individual Future objects"
...

This is very important thing! And if not addressed by the language or the
standlibrary,  third party libraries will. But also, has few downsides. The
proposal already covered this:

...
"A Future type designed for Swift today would need to be a class, and
therefore need to guard against potentially multithreaded access, races to
fulfill or attempts to fulfill multiple times, and potentially unbounded
queueing of awaiting coroutines on the shared future;"
"The proposed design eliminates the problem of calling an API (without
knowing it is async) and getting a Future<T> back instead of the expected T
result type."
"By encoding async as a first-class part of function types, closure
literals can also be transparently async by contextual type inference. "
"Requiring a future object to be instantiated at every await point adds
overhead."
etc...
...

So... My proposal is: Extend async/await functionality to close the gap
needed to allow parallel execution.

Something like that: (using the same exemple as before)

func downloadUserData() async -> UserData { ... }func downloadImage()
async -> UIImage { ... }
func someAsyncFunc() async -> User {
	var userData = async downloadUserData() // userData is of type `async
UserData` as we used async	var image = async downloadImage() // image
is of type `async UserData`	return await User(userData, image) //
needs to call await to use any `async T`}


await  still does not block execution, the lifetime of `async T` is very
previsible, (Future<T> can be stored, passed around, etc.), and any "Future
Like" type can be implement on the top of this!

async at call side needs to replace beginAsync? Not necessarily. We may
consider that calling anything with 'async' at startup implies beginAsync with
return T and can be 'awaited', suspended, etc. But its not the main use for
async at call side in my opinion. The lifetime of this call can handled in
the same way as beginAsync.

async at call side created another type? No! Its the point here! This
"virtual type" only need to exists on the context of the caller, and can be
used by the compiler to enforce the "await" at some point.

I can "reasync"any call? It's interesting, I think it's worth to be
considered.

func someAsyncFunc() async -> User {
	var userData = async downloadUserData()	var image = async
downloadImage() 	return async User(userData, image) // actually return
() async ->{ await User(userData, image) } or similar.

}


Can i suspend any calls? Maybe in this way:

let imageResource = try async loadWebResource("imagedata.dat")
  do {
    let imageTmp    = try await decodeImage(dataResource, imageResource)
  } catch _ as InvalidResourc {
    // Does not need to finish the imageResource await.    await
suspendAsync(imageResource) // just a exemple...  }catch _ as
CorruptedImage {
    // Give up hope now.    await abandon() // like before  }


Also, i dont like the idea of suspendAsync be a standlibrary function!
Maybe a keyword modifier? (await suspendAsync _ / await suspendAsync abc )

Anyway... I do not want to be adding too many ideas at the same time, there
are several ideas around "async". My point is just to enable parallel
execution without the introduction of another type. Whatever comes next is
profit!


Em sáb, 26 de ago de 2017 às 14:37, Adam Kemp via swift-evolution <
swift-evolution at swift.org> escreveu:

> C# had futures (in the form of the Task Parallel Library) before it had
> async/await. If you could see how much async/await has revolutionized C#
> programming you would not be making this argument. It is night and day.
> Asynchronous code is so much clearer with this feature than without. You
> can write code the is simpler and safer at the same time.
>
> This isn’t an either/or proposition. We should have both, and they should
> work together.
>
> --
> Adam Kemp
>
> On Aug 25, 2017, at 10:08 PM, Howard Lovatt via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I just don't see that async/await adds enough to warrant a language
> change. You can write Future on top of GCD and a future type can do more,
> like having a cancel, having a timeout, and giving control over what thread
> is used.
>
>   -- Howard.
>
> On 26 August 2017 at 10:57, Florent Vilmart via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> Isn’t async / await an evolution over Promises / Tasks / Futures? AFAIK
>> in JS, any function that returns a promise can be ‘await’ upon, and
>> underneath, to be able to await, a function has to return a promise.
>> Marking a function async in JS, tells the consumer that some await are
>> going on inside, and it’s impossible to use await outside of an async
>> marked function. I believe swift is going that direction too. Futures /
>> Promises are the foundation on which async / await can truly express as it
>> formalizes the boxing of the result types.
>> What would be interesting is async being based on a protocol FutureType
>> for example, so you can bring your own library and yet, leverage async /
>> await
>>
>> On Aug 25, 2017, 20:50 -0400, Jonathan Hull <jhull at gbis.com>, wrote:
>>
>>
>> On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise <
>> trevor.annedenise at icloud.com> wrote:
>>
>> =============================================================
>>
>> Jonathan Hull jhull at gbis.com
>>
>> This looks somewhat similar to a future, but you can’t interact with it
>> as a separate type of object.  The value above is just a UIImage, but with
>> a compiler flag/annotation that forces me to call await on it before it can
>> be accessed/used.  The compiler has a lot more freedom to
>> optimize/reorganize things behind the scenes, because it doesn’t
>> necessarily need to make an intermediate object.
>>
>>
>> As for the message of Wallacy I'd be interested the pros and cons of
>> hiding the implementation details ! :)
>>
>>
>> To prove (or potentially disprove) my assertion that this is not just
>> sugar, how would you accomplish the following under the current proposal?
>>
>> let a = async longCalculationA()
>> let b = async longCalculationB() //b doesn’t wait for a to complete
>> before starting
>> let c = async longCalculationC() //c doesn’t wait for a or b
>> let result = await combineCalculations(a: a, b: b, c: c) //waits until a,
>> b, and c are all available
>>
>>
>> Would this be implemented differently than with Futures? I don't have
>> much experience with concurrency, but I don't see how this would be handled
>> differently than by using Futures, internally ? (at least for this case)
>>
>>
>> It looks/behaves very similar to futures, but would potentially be
>> implemented differently.  The main difference is that the resulting type is
>> actually the desired type (instead of Future<Type>) with a compiler flag
>> saying that it needs to call await to be used.  Behind the scenes, this
>> could be implemented as some sort of future, but the compiler has a lot
>> more freedom to rearrange things to be much more efficient because there is
>> no affordance for the user to introspect or cancel. So for example, it
>> might actually change:
>>
>> let image = async downloadImage()
>> let size = await image.size
>>
>> to:
>>
>> let size = await downloadImage().size
>>
>> This would depend on the other code around it, but the compiler has much
>> more freedom to avoid creating intermediate values, or even to create
>> different types of intermediate values which are more efficient for the
>> situation at hand.
>>
>> Given that as a base, it would be trivial to create a framework offering
>> true Futures (which allow cancelling, etc…)
>>
>> Thanks,
>> Jon
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> 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/20170827/6ed00d32/attachment.html>


More information about the swift-evolution mailing list