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

Howard Lovatt howard.lovatt at gmail.com
Thu Sep 7 03:03:53 CDT 2017


I would argue that given:

    foo()
    await bar()
    baz()

That foo and baz should run on the same queue (using queue in the GCD
sense) but bar should determine which queue it runs on. I say this because:

   1. foo and baz are running synchronously with respect to each other
   (though they could be running asynchronously with respect to some other
   process if all the lines shown are inside an async function).
   2. bar is running asynchronously relative to foo and baz, potentially on
   a different queue.

I say bar is potentially on a different queue because the user of bar, the
person who wrote these 3 lines above, cannot be presumed to be the writer
of foo, baz, and particularly not bar and therefore have no detailed
knowledge about which queue is appropriate.

Therefore I would suggest either using a Future or expanding async so that
you can say:

    func bar() async(qos: .userInitiated) { ... }

You also probably need the ability to specify a timeout and queue type,
e.g.:

   func bar() async(type: .serial, qos: .utility, timeout: .seconds(10))
throws { ... }

If a timeout is specified then await would have to throw to enable the
timeout, i.e. call would become:

   try await bar()

Defaults could be provided for qos (.default works well), timeout (1 second
works well), and type (.concurrent works well).

However a Future does all this already :).

  -- Howard.

On 7 September 2017 at 15:13, David Hart via swift-evolution <
swift-evolution at swift.org> wrote:

>
>
> > On 7 Sep 2017, at 07:05, Chris Lattner via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> >
> >> On Sep 5, 2017, at 7:31 PM, Eagle Offshore via swift-evolution <
> swift-evolution at swift.org> wrote:
> >>
> >> OK, I've been watching this thing for a couple weeks.
> >>
> >> I've done a lot of GCD network code.  Invariably my completion method
> starts with
> >>
> >> dispatch_async(queue_want_to_handle_this_on,....)
> >>
> >> Replying on the same queue would be nice I guess, only often all I need
> to do is update the UI in the completion code.
> >>
> >> OTOH, I have situations where the reply is complicated and I need to
> persist a lot of data, then update the UI.
> >>
> >> So honestly, any assumption you make about how this is supposed to work
> is going to be wrong about half the time unless....
> >>
> >> you let me specify the reply queue directly.
> >>
> >> That is the only thing that works all the time.  Even then, I'm very
> apt to make the choice to do some of the work off the main thread and then
> queue up the minimal amount of work onto the main thread.
> >
> > I (think that I) understand what you’re saying here, but I don’t think
> that we’re talking about the same thing.
> >
> > You seem to be making an argument about what is most *useful* (being
> able to vector a completion handler to a specific queue), but I’m
> personally concerned about what is most *surprising* and therefore
> unnatural and prone to introduce bugs and misunderstandings by people who
> haven’t written the code.  To make this more concrete, shift from the
> “person who writes to code” to the “person who has to maintain someone
> else's code”:
> >
> > Imagine you are maintaining a large codebase, and you come across this
> (intentionally abstract) code:
> >
> >    foo()
> >    await bar()
> >    baz()
> >
> > Regardless of what is the most useful, I’d argue that it is only natural
> to expect baz() to run on the same queue/thread/execution-context as foo
> and bar.  If, in the same model, you see something like:
> >
> >    foo()
> >    await bar()
> >    anotherQueue.async {
> >        baz()
> >    }
>
> Couldn’t it end up being:
>
> foo()
> await bar()
> await anotherQueue.async()
> // on another queue
>
> > Then it is super clear what is going on: an intentional queue hop from
> whatever foo/bar are run on to anotherQueue.
> >
> > I interpret your email as arguing for something like this:
> >
> >    foo()
> >    await(anotherQueue) bar()
> >    baz()
> >
> > I’m not sure if that’s exactly the syntax you’re arguing for, but
> anything like this presents a number of challenges:
> >
> > 1) it is “just sugar” over the basic model, so we could argue to add it
> at any time (and would argue strongly to defer it out of this round of
> discussions).
> >
> > 2) We’d have to find a syntax that implies that baz() runs on
> anotherQueue, but bar() runs on the existing queue.  The syntax I sketched
> above does NOT provide this indication.
> >
> > -Chris
> >
> >
> > _______________________________________________
> > 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/20170907/a0752943/attachment.html>


More information about the swift-evolution mailing list