[swift-evolution] [Concurrency] Fixing race conditions in async/await example

Vladimir.S svabox at gmail.com
Wed Aug 30 05:35:37 CDT 2017


On 30.08.2017 3:43, Howard Lovatt wrote:
> @Vladimir,
> 
> Default values are a problem for await/async when combined with parallel running 
> because await returns a value and not an optional (unlike future's get). Below is a 
> more realistic code for parallel running and a default value using async/await:

Thank you for the reply. Seems I'm missing something important, but

async render(image: await image, text: await text)

, as I understand currently, should NOT block the execution, execution will back here 
when image&text are 'ready', while

render(image: image.get ?? defaultImage, text: text.get ?? defaultText)

should block on .get(). No? This is why I asked if we need some 'sync' modifier like

sync preprocessImage(someImage)
, if we need to call func declared as async synchronously.

Vladimir.

> 
>     func updateImage() async {
> 
>         let image: Image
> 
>         async do { // Runs in parallel (async)
> 
>             image = try async preprocessImage(downloadImage())
> 
>         } catch {
> 
>             image = defaultImage
> 
>         }
> 
>         let text: String
> 
>         async do { // Runs in parallel (async)
> 
>             text = try async translate(downloadText())
> 
>         } catch {
> 
>             text = defaultText
> 
>         }
>         // This line is complicated! We want render not to block (async), but have to
>         await for image and text.
>         // Render does not throw because it always has valid input.
>         // If async were allowed to prevent blocking then await could not 
> 
>         async render(image: await image, text: await text)
> 
>     }
> 
> 
> Which I don't think reads as well as the Future version:
> 
>     func updateImage() -> Future<Void> {
> 
>         return AsynchronousFuture { _ -> Void in
> 
>             let image = preprocessImage(downloadImage()) // Parallel, Futures are
>             queued on creation
> 
>             let text = translate(downloadText()) // Parallel, Futures are queued on
>             creation
> 
>             // Does not block (Futures are queued on creation), but has to wait for
>             its inputs (get).
> 
>             render(image: image.get ?? defaultImage, text: text.get ?? defaultText)
> 
>         }
> 
>     }
> 
> 
> In addition the async/await version does not have timeout; unlike the Future version.
> 
> Suppose that downloadImage doesn't fail, it just takes forever to download the image. 
> The Future version will timeout automatically and the default image will be used. 
> With async/await the code for downloadImage and downloadText will have to start 
> timers and throw if the timers timeout. Nothing to do in the Future version, it 
> handles timeout for you.
> 
> Neither or the above versions have cancel or control over the queue they execute on, 
> but both would be much easier to add to the Future version, like timeout is much 
> easier to add, since Futures support cancel and queue control directly.
> 
>    -- Howard.
> 
> On 30 August 2017 at 02:45, Vladimir.S via swift-evolution <swift-evolution at swift.org 
> <mailto:swift-evolution at swift.org>> wrote:
> 
>     On 29.08.2017 19:02, Wallacy via swift-evolution wrote:
> 
>         In this example i think we lose clarity, just looking for the code we cant
>         know if this two line will run on parallel or not!
>         Also, image.get blocks the thread, in this case we need the await anyway! And
>         `async` can throws too... So the error handler can be pretty similar.
> 
>         let  image=  asyncpreprocessImage(downloadImage()) // These first two lines
>         run in parallel and I can "see" the async keyword.
>         let  text=  asynctranslate(downloadText())
>         await render(image: image ?? defaultImage,text: text ?? defaultText) // No
>         blocking!
> 
> 
>     FWIW: I'm following the whole discussion from the start, and do support the
>     opinion that async/await is much clear solution that proposed Futures, especially
>     for beginners.
>     We need a low-level building blocks which can be used to implement
>     Futures/Promises in libraries.
>     Also I really like the idea of 'async' on the caller side to have code running in
>     parallel.
> 
>     The 'async' version of func declaration is clearly saying what type it *want* to
>     return, and 'async' modifier just saying *how* it will/can return that
>     type('Image' in examples). So on both sides, on declaration and on caller side,
>     we are clear what types we are working with.
>     Future<Type> - is mixing of what is returning and how this will be returned. Code
>     is saying that we preprocessesImage, but actually we have Future<Image> type, no
>     'markers' of asynchronous code.
> 
>     Also, I wonder(if I missed that in proposal/discussion, please let me know), if I
>     have async function like
> 
>     func foo() async -> Type {}
> 
>     , may I want to call it synchronously? If so, what would be a solution here? I
>     can think about something like 'sync' modifier on caller side:
>     let x = sync foo() // calling asynchronous function synchronously
> 
>     I believe that is what Future.get is doing, no?
>     let future =  ...
>     future.get() // blocks the execution, waits for the result.
> 
>     Probably it is reasonable to allow just call foo() to get blocking result, just
>     like any other 'simple' blocking funcs that we call, but this can lead to
>     unexpected behavior as user can expect async execution.
> 
>     With Futures, it seems like we can't "just" call such function and need to call
>     .get() later:
>     let future = someFuncReturnsFuture() // already returns Future<Type> type
> 
>     Vladimir.
> 
> 
>         Like i said before! Today's, the proposal only lack two things over the
>         `Future`....
>         Parallel computing: Can be implemented by a third party library or a personal
>         one, but i don't think this is a good approach to the first version.
>         Coordination: This we can wait! And why? Because coordination, can be made in
>         different ways, maybe is more suitable to a standard library class/function,
>         not a language level resource.
> 
>         Also, coordination cant be applied to all variants of the runtimes in the
>         same way! async/await as language level  works just as well with GCD as with
>         pthreads or another API. And coordination is a compromise that we can make
>         after that one.
> 
>         Em ter, 29 de ago de 2017 às 05:23, Howard Lovatt via swift-evolution
>         <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>         <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>> escreveu:
> 
>              @David,
> 
>              Using the `Future` library based on GCD that I have previously posted your
>              example would be:
> 
>              let  image=  preprocessImage(downloadImage()) // These first two lines
>         run in parallel
>              let  text=  translate(downloadText())
>              render(image: image.get ?? defaultImage,text: text.get ?? defaultText)
> 
> 
>              The main difference, and I would argue an improvement, is that the `Future`
>              version handles errors.
> 
>              So what advantage does async/await have over a `Future` library we can
>         write today?
> 
> 
>                 -- Howard.
> 
>              On 29 August 2017 at 15:28, David Hart via swift-evolution
>              <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>         <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>> wrote:
> 
> 
>                      On 29 Aug 2017, at 02:22, Xiaodi Wu via swift-evolution
>                      <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>             <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>> wrote:
> 
>                      On Mon, Aug 28, 2017 at 16:10 Adam Kemp via swift-evolution
>                      <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>             <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>> wrote:
> 
>                          I know what the proposal said. I’m making a case that there
>             is value in
>                          doing it differently.
> 
>                          The composability of futures is valuable. Mixing and matching
>                          async/await with futures is also valuable. The
>             queue-returning behavior
>                          that you can get from futures is also valuable, and building
>                          async/await on top of futures means async/await can get that
>             for free.
> 
> 
>                      Why couldn't you mix and match async/await and futures and get the
>                      queue-return behavior of futures if futures are built on top of
>             async/await
>                      instead off the other way around?
> 
> 
>                  We could, but the syntax is much worse. Contrast:
> 
>                  *async/await built on top of Futures*
>                  *
>                  *
> 
>                  let  image=  preprocessImage(downloadImage())
>                  let  text=  translate(downloadText())
>                  awaitrender(image: image,text: text)
> 
> 
>                  *Futures built on top of async/await*
>                  *
>                  *
> 
>                  let  image=  Future(downloadImage).then({preprocessImage($0) })
>                  let  text=  Future(downloadText).then({translate($0) })
>                  awaitrender(image: image.get(),text: text.get())
> 
> 
>                          Maybe you don’t value those things, which is fine. But I do,
>             and maybe
>                          other people do too. That’s why we’re having a discussion
>             about it.
> 
>                          It can also be valuable having a minimal implementation, but
>             we have to
>                          acknowledge that it comes with a downside as well. The
>             problem with
>                          doing a minimal implementation is that you can be stuck with the
>                          consequences for a long time. I want to make sure that we’re
>             not stuck
>                          with the consequences of a minimal implementation that doesn’t
>                          adequately address the problems that async/await should be
>             addressing.
>                          I’d hate for Swift to get an async/await that is so weak
>             that it has to
>                          be augmented by tedious boilerplate code before it’s useful.
> 
> 
>                              On Aug 28, 2017, at 1:54 PM, Wallacy <wallacyf at gmail.com
>                 <mailto:wallacyf at gmail.com>
>                              <mailto:wallacyf at gmail.com <mailto:wallacyf at gmail.com>>>
>                 wrote:
> 
>                              We don't need to this now!
> 
>                              Again: (Using proposal words)
> 
>                              "It is important to understand that this is proposing
>                 compiler support
>                              that is completely concurrency runtime-agnostic. This
>                 proposal does
>                              not include a new runtime model (like "actors") - it
>                 works just as
>                              well with GCD as with pthreads or another API.
>                 Furthermore, unlike
>                              designs in other languages, it is independent of
>                 specific coordination
>                              mechanisms, such as futures or channels, allowing these
>                 to be built as
>                              library feature"
> 
>                              and
> 
>                              "This proposal does not formally propose a |Future|
>                 type, or any other
>                              coordination abstractions. There are many rational
>                 designs for
>                              futures, and a lot of experience working with them. On
>                 the other hand,
>                              there are also completely different coordination
>                 primitives that can
>                              be used with this coroutine design, and incorporating
>                 them into this
>                              proposal only makes it larger."
> 
>                              and
> 
>                              We focus on task-based concurrency abstractions commonly
>                 encountered
>                              in client and server applications, particularly those
>                 that are highly
>                              event driven (e.g. responding to UI events or requests
>                 from clients).
>                              This does not attempt to be a comprehensive survey of
>                 all possible
>                              options, nor does it attempt to solve all possible
>                 problems in the
>                              space of concurrency. Instead, it outlines a single
>                 coherent design
>                              thread that can be built over the span of years to
>                 incrementally drive
>                              Swift to further greatness.
> 
>                              and
> 
>                              This proposal has been kept intentionally minimal, but
>                 there are many
>                              possible ways to expand this in the future.
> 
>                              ....
> 
>                              The point is: No Future type is indeed proposed yet!
> 
>                              The proposal try to include de "minimum" required to
>                 implement a basic
>                              async/await to solve the problem created by the GCD!
>                 (Pyramid of doom)
> 
>                              The question is: How do you do the same using
>                 dispatch_async ?
>                              dispatch_async also does not return nothing to do what
>                 you are
>                              intentend do do!
> 
>                              Algo, by Swift 5 manifesto, there's no compromise to
>                 make a "complete"
>                              concurrency model by this time!
> 
>                              My intention is only make parity to dispatch_async, but
>                 also make the
>                              ground free to make more complex implementation like
>                 Futures in
>                              another round on top of this one.
> 
>                              This 'async T' can be a real type in the future? Maybe
>                 will... But
>                              doesn't matter now! Now we only need to is some kind of
>                 type which
>                              need to be unwrapped using await before use. Maybe this
>                              intermediary/virtual type can be a real thing and gain
>                 some abilities
>                              at some point! Maybe a full Future type, why not?
> 
>                              Em seg, 28 de ago de 2017 às 17:33, Adam Kemp
>                 <adam.kemp at apple.com <mailto:adam.kemp at apple.com>
>                              <mailto:adam.kemp at apple.com
>                 <mailto:adam.kemp at apple.com>>> escreveu:
> 
>                                  How would these anonymous types get composed? If I
>                 wanted to
>                                  implement a function that takes a collection of
>                 futures and wait
>                                  on it, how would I do that? That is, how would I
>                 implement the
>                                  equivalent of C#’s Task.WhenAll and Task.WhenAny
>                 methods?
> 
>                                  More generally, how do you pass one of these
>                 typeless futures to
>                                  some other function so that we can do the waiting there?
> 
> 
>                                      On Aug 28, 2017, at 1:23 PM, Wallacy
>                     <wallacyf at gmail.com <mailto:wallacyf at gmail.com>
>                                      <mailto:wallacyf at gmail.com
>                     <mailto:wallacyf at gmail.com>>> wrote:
> 
>                                      And that's why I (and others) are suggesting:
> 
>                                      func processImageData1a() async -> Image {
>                                        let dataResource  = async
>                     loadWebResource("dataprofile.txt") //
>                                      No future type here... Just another way to call
>                     dispatch_async
>                                      under the hood.
>                                        let imageResource = async
>                     loadWebResource("imagedata.dat")
>                                        // ... other stuff can go here to cover load
>                     latency...
>                                        let imageTmp    = await decodeImage(dataResource,
>                                      imageResource) // Compiles force await call here...
>                                        let imageResult = await
>                     dewarpAndCleanupImage(imageTmp)
>                                        return imageResult
>                                      }
> 
>                                      And now we gain all advantages of async/await
>                     again without to
>                                      handle with one more type.
> 
>                                      Em seg, 28 de ago de 2017 às 17:07, Adam Kemp
>                     via swift-evolution
>                                      <swift-evolution at swift.org
>                     <mailto:swift-evolution at swift.org>
>                     <mailto:swift-evolution at swift.org
>                     <mailto:swift-evolution at swift.org>>>
> 
>                                      escreveu:
> 
>                                          I think the biggest tradeoff is clearer when
>                     you look at the
>                                          examples from the proposal where futures are
>                     built on top of
>                                          async/await:
> 
>                                              func processImageData1a() async -> Image {
>                                                let dataResource  = Future { await
>                                              loadWebResource("dataprofile.txt") }
>                                                let imageResource = Future { await
>                                              loadWebResource("imagedata.dat") }
>                                                // ... other stuff can go here to
>                     cover load latency...
>                                                let imageTmp    = await
>                     decodeImage(dataResource.get(),
>                                              imageResource.get())
>                                                let imageResult = await
>                     dewarpAndCleanupImage(imageTmp)
>                                                return imageResult
>                                              }
> 
> 
>                                          With this approach you have to wrap each
>                     call site to create
>                                          a future. Compare to this:
> 
>                                              func processImageData1a() -> Future<Image> {
>                                                let dataResourceFuture  =
>                                              loadWebResource("dataprofile.txt”);
>                                                let imageResourceFuture =
>                     loadWebResource("imagedata.dat”);
>                                                // ... other stuff can go here to
>                     cover load latency...
>                                                let imageTmp    = await decodeImage(await
>                                              dataResourceFuture, await
>                     imageResourceFuture)
>                                                let imageResult = await
>                     dewarpAndCleanupImage(imageTmp)
>                                                return imageResult
>                                              }
> 
> 
>                                          Here, not only are the explicit wrappers
>                     gone, but this
>                                          function itself can be used with either
>                     await or as a future.
>                                          You get both options with one implementation.
> 
>                                          As I’ve mentioned before, C#’s
>                     implementation is not tied to
>                                          any one particular futures implementation.
>                     The Task type is
>                                          commonly used, but async/await does not
>                     directly depend on
>                                          Task. Instead it works with any return type
>                     that meets
>                                          certain requirements (detailed here:
>                     https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-anything/
>                     <https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-anything/>).
>                                          Swift could do this using a protocol, which
>                     can be
>                                          retroactively applied using an extension.
> 
>                                          Obviously for this to be useful we would
>                     need some kind of
>                                          existing future implementation, but at least
>                     we wouldn’t be
>                                          tied to any particular one. That would mean
>                     library
>                                          maintainers who have already been using
>                     their own futures
>                                          implementations could quickly adopt
>                     async/await in their code
>                                          without having to rewrite their futures
>                     library or throw
>                                          wrappers around every usage of async/await.
>                     They could just
>                                          adopt a protocol (using an extension, even)
>                     and get
>                                          async/await support for free.
> 
>                                          The downside is that this feature would be
>                     specific to the
>                                          async/await use case rather than a generic
>                     coroutine
>                                          implementation (i.e., there would have to be
>                     a separate
>                                          compiler transform for yield return). It’s
>                     not clear to me
>                                          why it should be a goal to have just one
>                     generic coroutine
>                                          feature. The real-world usages of
>                     async/await and yield
>                                          return are different enough that I’m not
>                     convinced we could
>                                          have a single compiler feature that meets
>                     the needs of both
>                                          cleanly.
> 
>                                              On Aug 27, 2017, at 7:35 PM, Florent Vilmart
>                                              <florent at flovilmart.com
>                         <mailto:florent at flovilmart.com>
>                         <mailto:florent at flovilmart.com
>                         <mailto:florent at flovilmart.com>>> wrote:
> 
>                                              Adam, you’re completely right, languages
>                         as c# and JS have
>                                              been through the path before, (callback,
>                         Promises ,
>                                              async/await) I believe Chris’s goal it
>                         to avoid building a
>                                              promise implementation and go straight
>                         to a coroutines
>                                              model, which is more deeply integrated
>                         with the compiler. I
>                                              don’t see a particular trade off,
>                         pursuing that route, and
>                                              the main benefit is that coroutines can
>                         power any
>                                              asynchronous metaphor (Signals, Streams,
>                         Futures, Promises
>                                              etc...) which is not true of Futures so
>                         i would tend to
>                                              think that for the long run, and to
>                         maximize usability,
>                                              async/await/yield would probably be the
>                         way to go.
> 
>                                              On Aug 27, 2017, 22:22 -0400, Adam Kemp
>                         <adam.kemp at apple.com <mailto:adam.kemp at apple.com>
>                                              <mailto:adam.kemp at apple.com
>                         <mailto:adam.kemp at apple.com>>>, wrote:
> 
>                                                  As has been explained, futures can
>                             be built on top of
>                                                  async/await (or the other way
>                             around). You can have the
>                                                  best of both worlds. We are not
>                             losing anything by having
>                                                  this feature. It would be a huge
>                             improvement to have this
>                                                  as an option.
> 
>                                                  However, using futures correctly
>                             requires more nested
>                                                  closures than you have shown in your
>                             examples to avoid
>                                                  blocking any threads. That's why
>                             you're not seeing the
>                                                  advantage to async/await. You're
>                             comparing examples that
>                                                  have very different behaviors.
> 
>                                                  That said, I have also expressed my
>                             opinion that it is
>                                                  better to build async/await on top
>                             of futures rather than
>                                                  the other way around. I believe it
>                             is more powerful and
>                                                  cleaner to make async/await work
>                             with any arbitrary future
>                                                  type (via a protocol). The
>                             alternative (building futures on
>                                                  top of async/await) requires more
>                             code when the two are
>                                                  mixed. I very much prefer how it's
>                             done in C#, where you
>                                                  can freely mix the two models
>                             without having to resort to
>                                                  ad-hoc wrappers, and you can use
>                             async/await with any
>                                                  futures implementation you might
>                             already be using.
> 
>                                                  I really think we should be having
>                             more discussion about
>                                                  the tradeoffs between those two
>                             approaches, and I'm
>                                                  concerned that some of the opinions
>                             about how C# does it
>                                                  are not based on a clear and
>                             accurate understanding of how
>                                                  it actually works in that language.
> 
>                                                  --                     Adam Kemp
> 
>                                                  On Aug 27, 2017, at 6:02 PM, Howard
>                             Lovatt
>                                                  <howard.lovatt at gmail.com
>                             <mailto:howard.lovatt at gmail.com>
>                             <mailto:howard.lovatt at gmail.com
>                             <mailto:howard.lovatt at gmail.com>>>
>                                                  wrote:
> 
>                                                      The async/await is very similar
>                                 to the proposed Future (as
>                                                      I posed earlier) with regard to
>                                 completion-handler code,
>                                                      they both re-write the imported
>                                 completion-handler
>                                                      function using a closure, the
>                                 relevant sentence from the
>                                                      Async Proposal is:
> 
>                                                          "Under the hood, the
>                                 compiler rewrites this code using
>                                                          nested closures ..."
> 
> 
>                                                      Unlike the proposed future code
>                                 the async code is not
>                                                      naturally parallel, in the
>                                 running example the following
>                                                      lines from the async code are
>                                 run in series, i.e. await
>                                                      blocks:
> 
>                                                         let  dataResource= 
>                                 awaitloadWebResource("dataprofile.txt")
>                                                         let  imageResource= 
>                                 awaitloadWebResource("imagedata.dat")
>                                                      The equivalent lines using the
>                                 proposed Future:
>                                                         let  dataResource= 
>                                 loadWebResource("dataprofile.txt")
>                                                         let  imageResource= 
>                                 loadWebResource("imagedata.dat")
>                                                      Run in parallel and therefore
>                                 are potentially faster
>                                                      assuming that resources, like
>                                 cores and IO, are available.
> 
>                                                      Therefore you would be better
>                                 using a Future than an
>                                                      async, so why provide an async
>                                 unless you can make a
>                                                      convincing argument that it
>                                 allows you to write a better
>                                                      future?
> 
>                                                        -- Howard.
> 
>                                                      On 28 August 2017 at 09:59, Adam
>                                 Kemp <adam.kemp at apple.com <mailto:adam.kemp at apple.com>
>                                                      <mailto:adam.kemp at apple.com
>                                 <mailto:adam.kemp at apple.com>>> wrote:
> 
>                                                          This example still has
>                                 nested closures (to create a
>                                                          Future), and still relies on
>                                 a synchronous get method
>                                                          that will block a thread.
>                                 Async/await does not require
>                                                          blocking any threads.
> 
>                                                          I’m definitely a fan of
>                                 futures, but this example
>                                                          isn’t even a good example of
>                                 using futures. If you’re
>                                                          using a synchronous get
>                                 method then you’re not using
>                                                          futures properly. They’re
>                                 supposed to make it easy to
>                                                          avoid writing blocking code.
>                                 This example just does
>                                                          the blocking call on some
>                                 other thread.
> 
>                                                          Doing it properly would show
>                                 the benefits of
>                                                          async/await because it would
>                                 require more nesting and
>                                                          more complex error handling.
>                                 By simplifying the code
>                                                          you’ve made a comparison
>                                 between proper asynchronous
>                                                          code (with async/await) and
>                                 improper asynchronous code
>                                                          (your example).
> 
>                                                          That tendency to want to
>                                 just block a thread to make
>                                                          it easier is exactly why
>                                 async/await is so valuable.
>                                                          You get simple code while
>                                 still doing it correctly.
> 
>                                                          --                       
>                                   Adam Kemp
> 
>                                                          On Aug 27, 2017, at 4:00 PM,
>                                 Howard Lovatt via
>                                                          swift-evolution
>                                 <swift-evolution at swift.org
>                                 <mailto:swift-evolution at swift.org>
>                                                         
>                                 <mailto:swift-evolution at swift.org
>                                 <mailto:swift-evolution at swift.org>>> wrote:
> 
>                                                              The running example used
>                                     in the white paper coded
>                                                              using a Future is:
> 
>                                                              func processImageData1()
>                                     -> Future<Image> {
>                                                                  return
>                                     AsynchronousFuture { _ -> Image in
>                                                                      let dataResource  =
>                                                             
>                                     loadWebResource("dataprofile.txt") // dataResource
>                                                              and imageResource run in
>                                     parallel.
>                                                                      let imageResource =
>                                                             
>                                     loadWebResource("imagedata.dat")
>                                                                      let imageTmp      =
>                                                             
>                                     decodeImage(dataResource.get ?? Resource(path:
>                                                              "Default data resource
>                                     or prompt user"),
>                                                              imageResource.get ??
>                                     Resource(path: "Default image
>                                                              resource or prompt user"))
>                                                                      let imageResult   =
>                                                             
>                                       dewarpAndCleanupImage(imageTmp.get ??
>                                                              Image(dataPath: "Default
>                                     image or prompt user",
>                                                              imagePath: "Default
>                                     image or prompt user"))
>                                                                      return
>                                     imageResult.get ?? Image(dataPath:
>                                                              "Default image or prompt
>                                     user", imagePath: "Default
>                                                              image or prompt user")
>                                                                  }
>                                                              }
> 
>                                                              This also avoids the
>                                     pyramid of doom; the pyramid is
>                                                              avoided by converting
>                                     continuation-handlers into
>                                                              either a sync or future,
>                                     i.e. it is the importer that
>                                                              eliminates the nesting
>                                     by translating the code
>                                                              automatically.
> 
>                                                              This example using
>                                     Future also demonstrates three
>                                                              advantages of Future:
>                                     they are naturally parallel
>                                                              (dataResource and
>                                     imageResource lines run in
>                                                              parallel), they timeout
>                                     automatically (get returns
>                                                              nil if the Future has
>                                     taken too long), and if there
>                                                              is a failure (for any
>                                     reason including timeout) it
>                                                              provides a method of
>                                     either detecting the failure or
>                                                              providing a default (get
>                                     returns nil on failure).
> 
>                                                              There are a three of
>                                     other advantages a Future has
>                                                              that this example
>                                     doesn’t show: control over which
>                                                              thread the Future runs
>                                     on, Futures can be cancelled,
>                                                              and debugging
>                                     information is available.
> 
>                                                              You could imagine
>                                     `async` as a syntax sugar for
>                                                              Future, e.g. the above
>                                     Future example could be:
> 
>                                                              func processImageData1()
>                                     async -> Image {
>                                                                  let dataResource  =
>                                                             
>                                     loadWebResource("dataprofile.txt") // dataResource
>                                                              and imageResource run in
>                                     parallel.
>                                                                  let imageResource =
>                                     loadWebResource("imagedata.dat")
>                                                                  let imageTmp      =
>                                     decodeImage(dataResource.get
>                                                              ?? Resource(path:
>                                     "Default data resource or prompt
>                                                              user"),
>                                     imageResource.get ?? Resource(path: "Default
>                                                              image resource or prompt
>                                     user"))
>                                                                  let imageResult   =
>                                                             
>                                       dewarpAndCleanupImage(imageTmp.get ??
>                                                              Image(dataPath: "Default
>                                     image or prompt user",
>                                                              imagePath: "Default
>                                     image or prompt user"))
>                                                                  return
>                                     imageResult.get ?? Image(dataPath:
>                                                              "Default image or prompt
>                                     user", imagePath: "Default
>                                                              image or prompt user")
>                                                              }
> 
>                                                              Since an async is sugar
>                                     for Future the async runs as
>                                                              soon as it is created
>                                     (as soon as the underlying
>                                                              Future is created) and
>                                     get returns an optional (also
>                                                              cancel and status would
>                                     be still be present). Then if
>                                                              you want control over
>                                     threads and timeout they could
>                                                              be arguments to async:
> 
>                                                              func processImageData1()
>                                     async(queue:
>                                                              DispatchQueue.main,
>                                     timeout: .seconds(5)) -> Image {
>                                                              ... }
> 
>                                                              On Sat, 26 Aug 2017 at
>                                     11:00 pm, Florent Vilmart
>                                                              <florent at flovilmart.com
>                                     <mailto:florent at flovilmart.com>
>                                                             
>                                     <mailto:florent at flovilmart.com
>                                     <mailto:florent at flovilmart.com>>> wrote:
> 
>                                                                  Howard, with async /
>                                     await, the code is flat and
>                                                                  you don’t have to
>                                     unowned/weak self to prevent
>                                                                  hideous cycles in
>                                     the callbacks.
>                                                                  Futures can’t do that
> 
>                                                                  On Aug 26, 2017,
>                                     04:37 -0400, Goffredo Marocchi
>                                                                  via swift-evolution
>                                     <swift-evolution at swift.org
>                                     <mailto:swift-evolution at swift.org>
>                                                                 
>                                     <mailto:swift-evolution at swift.org
>                                     <mailto:swift-evolution at swift.org>>>, wrote:
> 
>                                                                      With both he now
>                                         built in promises in Node8 as
>                                                                      well as
>                                         libraries like Bluebird there was ample
>                                                                      time to evaluate
>                                         them and convert/auto convert
>                                                                      at times
>                                         libraries that loved callback pyramids
>                                                                      of doom when the
>                                         flow grows complex into promise
>                                                                      based chains.
>                                         Converting to Promises seems
>                                                                      magical for the
>                                         simple case, but can quickly
>                                                                      descend in hard
>                                         to follow flows and hard to
>                                                                      debug errors
>                                         when you move to non trivial multi
>                                                                      path scenarios.
>                                         JS is now solving it with their
>                                                                      implementation
>                                         of async/await, but the point is
>                                                                      that without the
>                                         full picture any single
>                                                                      solution would
>                                         break horribly in real life
>                                                                      scenarios.
> 
>                                                                      Sent from my iPhone
> 
>                                                                      On 26 Aug 2017,
>                                         at 06:27, Howard Lovatt via
>                                                                      swift-evolution
>                                         <swift-evolution at swift.org
>                                         <mailto:swift-evolution at swift.org>
>                                                                     
>                                         <mailto:swift-evolution at swift.org
>                                         <mailto:swift-evolution at swift.org>>> wrote:
> 
>                                                                          My argument
>                                             goes like this:
> 
>                                                                            1. You
>                                             don't need async/await to write a
>                                                                          powerful
>                                             future type; you can use the
>                                                                          underlying
>                                             threads just as well, i.e. future
>                                                                          with
>                                             async/await is no better than future without.
> 
>                                                                            2. Since
>                                             future is more powerful, thread
>                                                                          control,
>                                             cancel, and timeout, people should be
>                                                                          encouraged
>                                             to use this; instead because
>                                                                          async/await
>                                             are language features they will be
>                                                                          presumed,
>                                             incorrectly, to be the best way,
>                                                                          consequently
>                                             people will get into trouble with
>                                                                          deadlocks
>                                             because they don't have control.
> 
>                                                                            3.
>                                             async/await will require some engineering
>                                                                          work and
>                                             will at best make a mild syntax
>                                                                          improvement
>                                             and at worst lead to deadlocks,
>                                                                          therefore
>                                             they just don't carry their weight in
>                                                                          terms of
>                                             useful additions to Swift.
> 
>                                                                          Therefore,
>                                             save some engineering effort and
>                                                                          just provide
>                                             a future library.
> 
>                                                                          To turn the
>                                             question round another way, in two
>                                                                          forms:
> 
>                                                                            1. What
>                                             can async/wait do that a future can't?
> 
>                                                                            2. How
>                                             will future be improved if async/await
>                                                                          is added?
> 
> 
>                                                                            -- Howard.
> 
>                                                                          On 26 August
>                                             2017 at 02:23, Joe Groff
>                                                                         
>                                             <jgroff at apple.com
>                                             <mailto:jgroff at apple.com>
>                                             <mailto:jgroff at apple.com
>                                             <mailto:jgroff at apple.com>>> wrote:
> 
> 
>                                                                                  On
>                                                 Aug 25, 2017, at 12:34 AM, Howard
>                                                                                 
>                                                 Lovatt <howard.lovatt at gmail.com
>                                                 <mailto:howard.lovatt at gmail.com>
>                                                                                 
>                                                 <mailto:howard.lovatt at gmail.com
>                                                 <mailto:howard.lovatt at gmail.com>>> wrote:
> 
>                                                                                  In
>                                                 particular a future that is cancellable
>                                                                                  is
>                                                 more powerful that the proposed
>                                                                                 
>                                                 async/await.
> 
> 
>                                                                              It's not
>                                             more powerful; the features are to
>                                                                              some
>                                             degree disjoint. You can build a
>                                                                              Future
>                                             abstraction and then use async/await
>                                                                              to sugar
>                                             code that threads computation
>                                                                              through
>                                             futures. Getting back to Jakob's
>                                                                              example,
>                                             someone (maybe the Clang importer,
>                                                                              maybe
>                                             Apple's framework developers in an
>                                                                              overlay)
>                                             will still need to build
>                                                                             
>                                             infrastructure on top of IBActions and
>                                                                              other
>                                             currently ad-hoc signalling
>                                                                             
>                                             mechanisms to integrate them into a more
>                                                                             
>                                             expressive coordination framework.
> 
>                                                                              -Joe
> 
> 
>                                                                         
>                                             _______________________________________________
>                                                                         
>                                             swift-evolution mailing list
>                                             swift-evolution at swift.org
>                                             <mailto:swift-evolution at swift.org>
>                                                                         
>                                             <mailto: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>
> 
> 
>                                                              --
>                                                              -- Howard.
>                                                             
>                                     _______________________________________________
>                                                              swift-evolution mailing list
>                                     swift-evolution at swift.org
>                                     <mailto:swift-evolution at swift.org>
>                                                             
>                                     <mailto: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>
> 
> 
> 
> 
>                                          _______________________________________________
>                                          swift-evolution mailing list
>                     swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>                     <mailto: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>
> 
> 
> 
>                          _______________________________________________
>                          swift-evolution mailing list
>             swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>             <mailto: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>
> 
>                      _______________________________________________
>                      swift-evolution mailing list
>             swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>             <mailto: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>
> 
> 
> 
>                  _______________________________________________
>                  swift-evolution mailing list
>         swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>         <mailto: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>
> 
> 
>              _______________________________________________
>              swift-evolution mailing list
>         swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>         <mailto: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>
> 
> 
> 
>         _______________________________________________
>         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>
> 
>     _______________________________________________
>     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>
> 
> 


More information about the swift-evolution mailing list