[swift-evolution] Contextualizing async coroutines

Pierre Habouzit phabouzit at apple.com
Sat Sep 2 04:56:36 CDT 2017


> On Sep 2, 2017, at 1:58 AM, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>> On Aug 31, 2017, at 11:35 AM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
>> # Coroutine context
>> # `onResume` hooks
> `onResume` hooks seem like a really good way to, essentially, allow arbitrary concurrency primitives to be passed into `async` functions. My main question is, if we have it, why do we need coroutine contexts? It seems to me that anything the coroutine might do with the context could either be passed into its parameters, or encapsulated in its `onResume` hook.

No it's not the same. Arbitrary code is this: arbitrary code and data.

Please read the few mails I sent recently about this, but to recap here quickly:

It is needed for the runtime (in a broad sense, from language to the operating system) to be able to introspect these:
- priority attributes
- dependencies
- execution contexts (thread/queue/runloop/...)
- ownership

Without this info, the scheduling of these coroutines will essentially be random, subject to priority inversions and other similar issues.

>> and also prevents writing APIs that intentionally change context across an `await`, like a theoretical "goToMainThread()" function
> You say that like it's a bad thing. :^)
> (Seriously, I feel like that makes it *way* too easy to jump to another thread in the middle of a function using what looks like an ordinary line of code. A `let result = await someQueue.async { … }` syntax is a lot clearer that you're hopping to another thread and about what code will run on it, but can get around our current "pyramid of doom" problem. If the async syntax guarantees that the code before and after the `await` runs in the same "environment"—whatever environment is set up by the onResume hook—then that makes async functions much safer and easier for programmers to reason about, while only restricting their power slightly.)

I do agree that an explicit syntax that spells out the context when it changes is really preferable, and if no context is provided it should mean "the current one".
The context doesn't necessarily need to be a dispatch queue.

Ideally API surface that provide similar things could be annotated for Swift to reason about, e.g. to take a realatively obvious example:

	void xpc_connection_send_message_with_reply(xpc_connection_t conn, xpc_object_t msg, dispatch_queue_t queue, void (^handler)(xpc_object_t reply))

Could provided sufficient overlay, could be understood by Swift and provide something like this (completely random syntax, I barely do any Swift, so bear with me):

	let reply = await(queue) connection.sendQuery(message: msg)

Because the API could be annotated with `queue` in that function is the execution context for the coroutine, and `handler` is the said coroutine.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170902/75247124/attachment.html>

More information about the swift-evolution mailing list