Question about async await

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"
2) Here (with async bar function), if bar() takes some time to execute, control is directly given back to the function calling foo() and, when bar() returns, print("How are you") will be executed.

Second question about why async/await are needed:
Since calling await must be done in an async function and since async function can only be called, then if we have :
func baz() async {
  await foo()
  print("Something else")
}

Does this mean that "print("Something else")" will actually be waiting for bar() (and foo()) to complete ?
If this is right, then, what surprises me a little is that in this specific case, if all functions hadn't been async, then the execution order would have exactly been the same, am I right ?
So why are async/await needed ? Except for clarity, what do they enable that wouldn't have been possible otherwise ? It's not exactly clear to me sometimes because even things like futures wouldn't seem impossible to build without async await.

About beginAsync, say that we do that on the main thread :
beginAsync {
  await someAsyncFunction()
}

Will someAsyncFunction() still be executed on the main thread if it was defined this way ?
func someAsyncFunction() async {
  for element in manyElements {
    doSomethingLong(element)
  }
}

In this case, when will the main "choose" to execute those instructions ?

Thank you !

Trevör

1 Like

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

···

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org> wrote:

control is directly given back to the function calling foo() and, when bar() returns, print("How are you") will be executed.

Second question about why async/await are needed:
Since calling await must be done in an async function and since async function can only be called, then if we have :
func baz() async {
  await foo()
  print("Something else")
}

Does this mean that "print("Something else")" will actually be waiting for bar() (and foo()) to complete ?
If this is right, then, what surprises me a little is that in this specific case, if all functions hadn't been async, then the execution order would have exactly been the same, am I right ?
So why are async/await needed ? Except for clarity, what do they enable that wouldn't have been possible otherwise ? It's not exactly clear to me sometimes because even things like futures wouldn't seem impossible to build without async await.

About beginAsync, say that we do that on the main thread :
beginAsync {
  await someAsyncFunction()
}

Will someAsyncFunction() still be executed on the main thread if it was defined this way ?
func someAsyncFunction() async {
  for element in manyElements {
    doSomethingLong(element)
  }
}

In this case, when will the main "choose" to execute those instructions ?

Thank you !

Trevör

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

Trevör

···

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

control is directly given back to the function calling foo() and, when bar() returns, print("How are you") will be executed.

Second question about why async/await are needed:
Since calling await must be done in an async function and since async function can only be called, then if we have :
func baz() async {
  await foo()
  print("Something else")
}

Does this mean that "print("Something else")" will actually be waiting for bar() (and foo()) to complete ?
If this is right, then, what surprises me a little is that in this specific case, if all functions hadn't been async, then the execution order would have exactly been the same, am I right ?
So why are async/await needed ? Except for clarity, what do they enable that wouldn't have been possible otherwise ? It's not exactly clear to me sometimes because even things like futures wouldn't seem impossible to build without async await.

About beginAsync, say that we do that on the main thread :
beginAsync {
  await someAsyncFunction()
}

Will someAsyncFunction() still be executed on the main thread if it was defined this way ?
func someAsyncFunction() async {
  for element in manyElements {
    doSomethingLong(element)
  }
}

In this case, when will the main "choose" to execute those instructions ?

Thank you !

Trevör

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

-Pierre

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

···

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Trevör

control is directly given back to the function calling foo() and, when bar() returns, print("How are you") will be executed.

Second question about why async/await are needed:
Since calling await must be done in an async function and since async function can only be called, then if we have :
func baz() async {
  await foo()
  print("Something else")
}

Does this mean that "print("Something else")" will actually be waiting for bar() (and foo()) to complete ?
If this is right, then, what surprises me a little is that in this specific case, if all functions hadn't been async, then the execution order would have exactly been the same, am I right ?
So why are async/await needed ? Except for clarity, what do they enable that wouldn't have been possible otherwise ? It's not exactly clear to me sometimes because even things like futures wouldn't seem impossible to build without async await.

About beginAsync, say that we do that on the main thread :
beginAsync {
  await someAsyncFunction()
}

Will someAsyncFunction() still be executed on the main thread if it was defined this way ?
func someAsyncFunction() async {
  for element in manyElements {
    doSomethingLong(element)
  }
}

In this case, when will the main "choose" to execute those instructions ?

Thank you !

Trevör

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

-Pierre

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

Trevör

···

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net> a écrit :

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

async/await doesn’t automatically make things run on another queue/thread. The code you wrote would execute synchronously on the original thread.

···

--
Adam Kemp

On Sep 19, 2017, at 11:36 PM, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> wrote:

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

Trevör

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

···

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

Here’s more stuff I found on how this could work. It’s slowly becoming less murky to me.

-Kenny

···

On Sep 20, 2017, at 7:19 AM, Adam Kemp via swift-evolution <swift-evolution@swift.org> wrote:

async/await doesn’t automatically make things run on another queue/thread. The code you wrote would execute synchronously on the original thread.

--
Adam Kemp

On Sep 19, 2017, at 11:36 PM, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

Trevör

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Good article. Thanks.

···

Em sex, 22 de set de 2017 às 14:24, Kenny Leung via swift-evolution < swift-evolution@swift.org> escreveu:

Here’s more stuff I found on how this could work. It’s slowly becoming
less murky to me.

There Is No Thread

-Kenny

On Sep 20, 2017, at 7:19 AM, Adam Kemp via swift-evolution < > swift-evolution@swift.org> wrote:

async/await doesn’t automatically make things run on another queue/thread.
The code you wrote would execute synchronously on the original thread.

--
Adam Kemp

On Sep 19, 2017, at 11:36 PM, Trevör Anne Denise via swift-evolution < > swift-evolution@swift.org> wrote:

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise < > trevor.annedenise@icloud.com> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution < > swift-evolution@swift.org> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
print("Hey")
await bar()
print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be
blocked until bar returns, at this point print("How are you ?") would be
executed and its only after that that the function calling foo() would get
back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it
wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it
for you. bar itself will be marked async and will handle its asynchronous
nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned
in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are
problematic because their syntax suggests that they will be called on the
current queue, but that is not always the case. For example, one of the top
recommendations on Stack Overflow is to implement your own custom async
operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or
any library-level usage of it.

So since async await don't have any impact on where things are executed,
what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
var results = [Int]()
for element in input {
results += [someLongComputation(with: element)]
}
return results
}

beginAsync {
await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so
what would happen ? Would beginAsync block until slowFunction completes ?

Trevör

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

Thank you !

Trevör

···

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

The high level stuff is not designed yet, and how to specify the continuation target queue/thread is not defined at this point.

Your code will probably be something like

Dispatch.startAync {
  val stuff = await downloadStuff()
  // do something with stuff once it is done.
}

···

Le 23 sept. 2017 à 12:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> a écrit :

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

Do you mean that the API to execute the continuation back on its original thread ? (avoiding shared mutable state)

Trevör

···

Le 24 sept. 2017 à 12:00, Jean-Daniel <mailing@xenonium.com> a écrit :

Le 23 sept. 2017 à 12:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

The high level stuff is not designed yet, and how to specify the continuation target queue/thread is not defined at this point.

Your code will probably be something like

Dispatch.startAync {
  val stuff = await downloadStuff()
  // do something with stuff once it is done.
}

I think you have to do something like this:

func async doSomethingInBackground(callbackQueue: DispatchQueue) -> SomeResult {
  await someBackgroundQueue.asyncCorountine()
  
  // Here I would put my (potentially lengthy) background code.
  
  // Jump on the requested callback queue.
  await callbackQueue.asyncCoroutine()
  
  // Return result (if any).
  return result
}

Thomas

···

On 25 Sep 2017, at 10:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> wrote:

Le 24 sept. 2017 à 12:00, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 23 sept. 2017 à 12:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

The high level stuff is not designed yet, and how to specify the continuation target queue/thread is not defined at this point.

Your code will probably be something like

Dispatch.startAync {
  val stuff = await downloadStuff()
  // do something with stuff once it is done.
}

Do you mean that the API to execute the continuation back on its original thread ? (avoiding shared mutable state)

I hope this will be handled automatically the compiler tough !

···

Le 25 sept. 2017 à 11:55, Thomas <tclementdev@free.fr> a écrit :

On 25 Sep 2017, at 10:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> wrote:

Le 24 sept. 2017 à 12:00, Jean-Daniel <mailing@xenonium.com> a écrit :

Le 23 sept. 2017 à 12:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> a écrit :

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

The high level stuff is not designed yet, and how to specify the continuation target queue/thread is not defined at this point.

Your code will probably be something like

Dispatch.startAync {
  val stuff = await downloadStuff()
  // do something with stuff once it is done.
}

Do you mean that the API to execute the continuation back on its original thread ? (avoiding shared mutable state)

I think you have to do something like this:

func async doSomethingInBackground(callbackQueue: DispatchQueue) -> SomeResult {
  await someBackgroundQueue.asyncCorountine()
  
  // Here I would put my (potentially lengthy) background code.
  
  // Jump on the requested callback queue.
  await callbackQueue.asyncCoroutine()
  
  // Return result (if any).
  return result
}

Thomas

Did anyone started to sketch a design for how giving back control to the calling queue will work ?

Would it make any sense to limit asyncCorountine() to the scope of the function where it gets called and implicitly "hop back" to the calling queue so that no shared mutable state issues arise ?

···

Le 25 sept. 2017 à 13:33, Trevör ANNE DENISE <trevor.annedenise@icloud.com> a écrit :

Le 25 sept. 2017 à 11:55, Thomas <tclementdev@free.fr <mailto:tclementdev@free.fr>> a écrit :

On 25 Sep 2017, at 10:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 24 sept. 2017 à 12:00, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 23 sept. 2017 à 12:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

The high level stuff is not designed yet, and how to specify the continuation target queue/thread is not defined at this point.

Your code will probably be something like

Dispatch.startAync {
  val stuff = await downloadStuff()
  // do something with stuff once it is done.
}

Do you mean that the API to execute the continuation back on its original thread ? (avoiding shared mutable state)

I think you have to do something like this:

func async doSomethingInBackground(callbackQueue: DispatchQueue) -> SomeResult {
  await someBackgroundQueue.asyncCorountine()
  
  // Here I would put my (potentially lengthy) background code.
  
  // Jump on the requested callback queue.
  await callbackQueue.asyncCoroutine()
  
  // Return result (if any).
  return result
}

Thomas

I hope this will be handled automatically the compiler tough !

Did anyone started to sketch a design for how giving back control to the calling queue will work ?

This thread had some ideas:

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170828/039349.html

C# uses the SynchronizationContext class <SynchronizationContext Class (System.Threading) | Microsoft Learn <Microsoft Learn: Build skills that open doors in your career. This class abstracts the concept of performing work synchronously or asynchronously using different threading models. For instance, there’s an implementation that posts messages to the UI thread and another that posts them to a thread pool. Each thread has a current context, which can be set with a static method.

The C# async/await feature itself doesn’t know anything about this, but its futures implementation (System.Threading.Tasks.Task) can be configured to run its continuation on the SynchronizationContext that was current when the task was started. If you use Task with async/await then it will “Just Work”. If you use some other futures implementation with async/await then it’s up to that implementation to decide what to do with the continuations.

I could imagine a concept like SynchronizationContext in Swift which captures the current queue and then can post work back to that same queue.

···

On Sep 25, 2017, at 9:54 AM, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> wrote:

Would it make any sense to limit asyncCorountine() to the scope of the function where it gets called and implicitly "hop back" to the calling queue so that no shared mutable state issues arise ?

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

No. Async methods are not require to be dispatched on a queue and all threads are not required to have a queue.

···

Le 25 sept. 2017 à 18:54, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org> a écrit :

Le 25 sept. 2017 à 13:33, Trevör ANNE DENISE <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> a écrit :

Le 25 sept. 2017 à 11:55, Thomas <tclementdev@free.fr <mailto:tclementdev@free.fr>> a écrit :

On 25 Sep 2017, at 10:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 24 sept. 2017 à 12:00, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 23 sept. 2017 à 12:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

The high level stuff is not designed yet, and how to specify the continuation target queue/thread is not defined at this point.

Your code will probably be something like

Dispatch.startAync {
  val stuff = await downloadStuff()
  // do something with stuff once it is done.
}

Do you mean that the API to execute the continuation back on its original thread ? (avoiding shared mutable state)

I think you have to do something like this:

func async doSomethingInBackground(callbackQueue: DispatchQueue) -> SomeResult {
  await someBackgroundQueue.asyncCorountine()
  
  // Here I would put my (potentially lengthy) background code.
  
  // Jump on the requested callback queue.
  await callbackQueue.asyncCoroutine()
  
  // Return result (if any).
  return result
}

Thomas

I hope this will be handled automatically the compiler tough !

Did anyone started to sketch a design for how giving back control to the calling queue will work ?

Would it make any sense to limit asyncCorountine() to the scope of the function where it gets called and implicitly "hop back" to the calling queue so that no shared mutable state issues arise ?

Thank you ! That's exactly what I was looking for !

Trevör

···

Le 25 sept. 2017 à 19:32, Adam Kemp <adam_kemp@apple.com> a écrit :

On Sep 25, 2017, at 9:54 AM, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Did anyone started to sketch a design for how giving back control to the calling queue will work ?

This thread had some ideas:

[swift-evolution] Contextualizing async coroutines

C# uses the SynchronizationContext class <SynchronizationContext Class (System.Threading) | Microsoft Learn <Microsoft Learn: Build skills that open doors in your career. This class abstracts the concept of performing work synchronously or asynchronously using different threading models. For instance, there’s an implementation that posts messages to the UI thread and another that posts them to a thread pool. Each thread has a current context, which can be set with a static method.

The C# async/await feature itself doesn’t know anything about this, but its futures implementation (System.Threading.Tasks.Task) can be configured to run its continuation on the SynchronizationContext that was current when the task was started. If you use Task with async/await then it will “Just Work”. If you use some other futures implementation with async/await then it’s up to that implementation to decide what to do with the continuations.

I could imagine a concept like SynchronizationContext in Swift which captures the current queue and then can post work back to that same queue.

Would it make any sense to limit asyncCorountine() to the scope of the function where it gets called and implicitly "hop back" to the calling queue so that no shared mutable state issues arise ?

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

This doesn't have to be the case, actually. The intrinsics as Chris described them wouldn't be sufficient, but you could require a "current queue" to be provided when kicking off an async function from scratch, as well as any other "async-local" context information you wanted (e.g. QoS and the other things that Dispatch tracks with attributes/flags that are generally supposed to persist across an entire async operation).

John.

···

On Sep 25, 2017, at 3:14 PM, Jean-Daniel via swift-evolution <swift-evolution@swift.org> wrote:

Le 25 sept. 2017 à 18:54, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 25 sept. 2017 à 13:33, Trevör ANNE DENISE <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> a écrit :

Le 25 sept. 2017 à 11:55, Thomas <tclementdev@free.fr <mailto:tclementdev@free.fr>> a écrit :

On 25 Sep 2017, at 10:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 24 sept. 2017 à 12:00, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 23 sept. 2017 à 12:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

The high level stuff is not designed yet, and how to specify the continuation target queue/thread is not defined at this point.

Your code will probably be something like

Dispatch.startAync {
  val stuff = await downloadStuff()
  // do something with stuff once it is done.
}

Do you mean that the API to execute the continuation back on its original thread ? (avoiding shared mutable state)

I think you have to do something like this:

func async doSomethingInBackground(callbackQueue: DispatchQueue) -> SomeResult {
  await someBackgroundQueue.asyncCorountine()
  
  // Here I would put my (potentially lengthy) background code.
  
  // Jump on the requested callback queue.
  await callbackQueue.asyncCoroutine()
  
  // Return result (if any).
  return result
}

Thomas

I hope this will be handled automatically the compiler tough !

Did anyone started to sketch a design for how giving back control to the calling queue will work ?

Would it make any sense to limit asyncCorountine() to the scope of the function where it gets called and implicitly "hop back" to the calling queue so that no shared mutable state issues arise ?

No. Async methods are not require to be dispatched on a queue

My response was about the ‘implicitly’ part. I hope we will get a rich API that let us specify return queue, QoS and more, but how do you plan to fulfill the « current queue » requirement implicitly ?

···

Le 25 sept. 2017 à 21:42, John McCall via swift-evolution <swift-evolution@swift.org> a écrit :

On Sep 25, 2017, at 3:14 PM, Jean-Daniel via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 25 sept. 2017 à 18:54, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 25 sept. 2017 à 13:33, Trevör ANNE DENISE <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> a écrit :

Le 25 sept. 2017 à 11:55, Thomas <tclementdev@free.fr <mailto:tclementdev@free.fr>> a écrit :

On 25 Sep 2017, at 10:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 24 sept. 2017 à 12:00, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 23 sept. 2017 à 12:23, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 20 sept. 2017 à 21:15, Jean-Daniel <mailing@xenonium.com <mailto:mailing@xenonium.com>> a écrit :

Le 20 sept. 2017 à 08:36, Trevör Anne Denise via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Le 18 sept. 2017 à 18:07, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

-Pierre

On Sep 18, 2017, at 2:04 AM, Trevör Anne Denise <trevor.annedenise@icloud.com <mailto:trevor.annedenise@icloud.com>> wrote:

Le 18 sept. 2017 à 07:57, Pierre Habouzit <pierre@habouzit.net <mailto:pierre@habouzit.net>> a écrit :

On Sep 17, 2017, at 3:52 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello everyone,

I have a few questions about async await in Swift.

Say that you have :

func foo() async {
  print("Hey")
  await bar()
  print("How are you ?")
}

First of all, am I right to say that :
1) If the bar function wasn't an async function, the thread would be blocked until bar returns, at this point print("How are you ?") would be executed and its only after that that the function calling foo() would get back "control"

I don't think you can quite call await without marking foo() as async (?).

Yes, that's what I meant, case one would call foo() without await if it wasn't async.

2) Here (with async bar function), if bar() takes some time to execute,

Not quite, `await bar()` is afaict syntactic sugar for:

bar {
    printf("How are you ?");
}

Where bar used to take a closure before, the compiler is just making it for you. bar itself will be marked async and will handle its asynchronous nature e.g. using dispatch or something else entirely.
This has nothing to do with "time".

If it's just syntactic sugar then how does this solve this issue mentioned in the concurrency manifesto ?
"Beyond being syntactically inconvenient, completion handlers are problematic because their syntax suggests that they will be called on the current queue, but that is not always the case. For example, one of the top recommendations on Stack Overflow is to implement your own custom async operations with code like this (Objective-C syntax):"

"where" things run is not addressed by async/await afaict, but Actors or any library-level usage of it.

So since async await don't have any impact on where things are executed, what would happen concretely with this code ?

func slowFunction(_ input: [Int]) async -> [Int] {
  var results = [Int]()
  for element in input {
    results += [someLongComputation(with: element)]
  }
  return results
}

beginAsync {
  await slowFunction(manyElements)
}

I didn't specified anything about which queue/thread runs this code, so what would happen ? Would beginAsync block until slowFunction completes ?

If I understand correctly, In real code you are not supposed to call beginAsync.
It should be wrapped by high level frameworks. GCD may provide a method that take an async lambda as parameter and dispatch it on a the global concurrent queue.
Other library may provide entry point that run the code in a private thread pool.

This is just a primitive used to support coroutine, but does not define how they are handled.

Thank you everyone, I understand it better now, I still have some questions tough.
Just to be sure that I am understanding this correctly, if you some async function and it suspends itself, then your current async function making this call will also suspend itself, right ?

Also, I understand how suspendAsync will be used to warp current callback based functions into async/await friendly functions and in this case :
func getStuff() async -> Stuff {
  return await suspendAsync { continuation in
    getStuff(completion: continuation)
  }
}

Here, I understand how the function controls where continuation is executed, but how would you write an API supporting async/await from scratch ?

Say that I want to build an async function that downloads data, with libdispatch I could do :
func dowloadSomething() {
  await someBackgroundQueue.asyncCorountine()
  // Here I would put my code for downloading data
  
  // But would I have to put anything after that to choose where to execute the continuation ? DispatchQueue.main.syncCorountine() maybe ?
}

The high level stuff is not designed yet, and how to specify the continuation target queue/thread is not defined at this point.

Your code will probably be something like

Dispatch.startAync {
  val stuff = await downloadStuff()
  // do something with stuff once it is done.
}

Do you mean that the API to execute the continuation back on its original thread ? (avoiding shared mutable state)

I think you have to do something like this:

func async doSomethingInBackground(callbackQueue: DispatchQueue) -> SomeResult {
  await someBackgroundQueue.asyncCorountine()
  
  // Here I would put my (potentially lengthy) background code.
  
  // Jump on the requested callback queue.
  await callbackQueue.asyncCoroutine()
  
  // Return result (if any).
  return result
}

Thomas

I hope this will be handled automatically the compiler tough !

Did anyone started to sketch a design for how giving back control to the calling queue will work ?

Would it make any sense to limit asyncCorountine() to the scope of the function where it gets called and implicitly "hop back" to the calling queue so that no shared mutable state issues arise ?

No. Async methods are not require to be dispatched on a queue

This doesn't have to be the case, actually. The intrinsics as Chris described them wouldn't be sufficient, but you could require a "current queue" to be provided when kicking off an async function from scratch, as well as any other "async-local" context information you wanted (e.g. QoS and the other things that Dispatch tracks with attributes/flags that are generally supposed to persist across an entire async operation).