SE-0300 (Second review): Continuations for interfacing async tasks with synchronous code

Hi Swift Evolution!

The second review of SE-0300 — Continuations for interfacing async tasks with synchronous code begins now and runs through February 11, 2021.

Following the first review of this proposal, the core team feels that this is a good addition to the language, and is an important feature as part of Swift's concurrency roadmap. However, a number of clarifications to the proposal resulted from the first review, and so a second review of this clarified proposal is being conducted.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager (via email or direct message in the Swift forums).

What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thanks,
Ben Cohen
Review Manager

10 Likes

Is there a diff or summary of the changes?

1 Like

It was done in a couple of commits but you can see the history on GitHub.

Just to clarify, the task (may) suspend at the end of operation, and it resumes after resume is call or operation finishes whichever comes later, right? Given that operation is called using the task context, we can't have them resumed when it is still running, esp. in case we use concurrent/custom executors.


I don't remember if this has been brought up before, but I think this would be the first unsafe function when its meaning is outside of memory safety. Are we embracing a broader meaning of unsafe or should we add another "keyword"?

The task always suspends until resume is called. Once operation returns, the task stops executing, and the executor is free to schedule another task on the same thread.

It is absolutely memory-unsafe to misuse a continuation.

Ok, I've been having a hard time understanding the semantic of this function, even after re-reading it a few times:

withUnsafe*Continuation will run its operation argument immediately in the task's current context, passing in a continuation value that can be used to resume the task. [...] after the operation function returns, the task is suspended. The task must then be brought out of the suspended state by invoking one of the continuation's resume methods.

From what you said:

  1. A caller on TaskA calls withUnsafe*Continuation,
  2. TaskA immediately suspends,
  3. operation is executed not on TaskA,
    3a. TaskA is enqueued to the appropriate executer when resume is called.

If that is the case, would these two be correct?:

  • operation can run concurrently with TaskA if resume is not the last thing it does.
  • Given that there's a chance TaskLocal can be called from sync functions, this would treat operation as non-Task function environment.

operation does not run concurrently with TaskA. The task stops running async code, runs the operation, then suspends.

Ok, so

  1. A caller on TaskA calls withUnsafe*Continuation,
  2. operation is immediately executed on TaskA ,
  3. After operation finishes execution, TaskA immediately suspends,
    3a. If resume is called before operation finishes execution, TaskA is enqueued (to the executor) after operation finishes execution,
    3b. If resume is called after operation finished execution, TaskA is enqueued after resume is called.

Sorry to bother, but it's just not so clear to me.

1 Like

A contributor suggested we add a resume() method for cases where the continuation resume type is Void, as shorthand for resume(returning: ()), which I've adopted into the proposal text:

5 Likes

Review Conclusion

The core team reviewed the feedback, as well as some feedback received off-thread. We believe this proposal is close to acceptance, but a final revision is being put out for re-review.