Skip to content

[Concurrency] Add API stubs for Task #34391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 27, 2020

Conversation

ktoso
Copy link
Contributor

@ktoso ktoso commented Oct 22, 2020

Introduce minimal placeholders for Task and UnsafeContinuation to enable prototyping usage of the concurrency APIs.

edit: crasher resolved 👍


This currently crashes with: Assertion failed: (empty() && "explosion had values remaining when destroyed!"), function ~Explosion, file /Users/ktoso/code/swift-project/swift/lib/IRGen/Explosion.h, line 65., partial stack:

@DougGregor suggests the crash may be related to missing functionality that @nate-chandler is working on?

@ktoso
Copy link
Contributor Author

ktoso commented Oct 22, 2020

@swift-ci please smoke test

@ktoso ktoso changed the title [Concurrency] Add minimal placeholders for Task and UnsasfeContinuation [Concurrency] Add minimal placeholders for Task and UnsafeContinuation Oct 22, 2020
@ktoso
Copy link
Contributor Author

ktoso commented Oct 22, 2020

Will be unblocked by #34370

@ktoso ktoso force-pushed the wip-concurrency-tasks branch 2 times, most recently from f030e3e to 89763f6 Compare October 23, 2020 03:37
@ktoso
Copy link
Contributor Author

ktoso commented Oct 23, 2020

@swift-ci please test

@ktoso
Copy link
Contributor Author

ktoso commented Oct 23, 2020

@swift-ci please smoke test

@ktoso
Copy link
Contributor Author

ktoso commented Oct 23, 2020

And we're green; I also added some small tests... nothing very exciting but better doc the expected look of the API via such anyway.

Please review and merge at will @DougGregor (I don't have merge powers btw, not sure if that's expected I think Dario from my team did have those powers hm 🤔)

@ktoso
Copy link
Contributor Author

ktoso commented Oct 23, 2020

@swift-ci please test

@ktoso ktoso force-pushed the wip-concurrency-tasks branch from 3f68495 to 3a4ead6 Compare October 26, 2020 05:52
@ktoso ktoso changed the title [Concurrency] Add minimal placeholders for Task and UnsafeContinuation [Concurrency] Add API stubs for Task Oct 26, 2020
@ktoso ktoso force-pushed the wip-concurrency-tasks branch from 3b87b8f to 579c89c Compare October 26, 2020 10:02
@ktoso
Copy link
Contributor Author

ktoso commented Oct 26, 2020

Also added runDetached, priority and task handles. This mostly reuses existing wording, but puts it into API docs.

Please have a look @DougGregor

More things coming soon -- was thinking in a separate PR tbh, but I can keep adding here if we want all the Task core primitives in one PR.

@ktoso
Copy link
Contributor Author

ktoso commented Oct 26, 2020

@swift-ci please test

Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. My few comments can be addressed in a follow-up.

/// These partial periods towards the task's completion are `PartialAsyncTask`.
/// Partial tasks are generally not interacted with by end-users directly,
/// unless implementing a scheduler.
public struct Task {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably put an OpaquePointer or perhaps an AnyObject in here and make it frozen, because Task is a thin wrapper around a pointer to a task, which is a ref-counted entity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah true, will address in next PR 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's swift ref-counted, you should use Builtin.NativeObject.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the proposal this was just a namespace. If we're going to make it a type that's a generic reference to a task, I think that's useful, but we need to think about how this interacts with Handle. Maybe it's a class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposal indeed at first declared enum Task but also has a few struct Task but I guess those were always meant to be extension Task -- I guess it boils down to the primary question if one should be able to "touch" someone else's task ever at all.

We mentioned that if we allow Task.current one could potentially store or send it around; This interacts with things like task local storage and the deadline/timeout APIs...

Or should we stick to "task is a concept" and all interaction with it is via static functions? It is more correct I guess, i.e. we can then easily disallow any other task being able to set/get task local storage (if it was an API on the task object it could be abused).

So... back to namespace or there's reason to have it a class?

/// If the task has not completed yet, its priority will be elevated to the
/// priority of the current task. Note that this may not be as effective as
/// creating the task with the "right" priority to in the first place.
public func get() async -> Success {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this go away?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah damn, forgot cancelation!

Thanks Doug, will remove

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually... that's not clear yet!

The more I dug into this while writing up the proposal the more second thoughts I was having.

Pasing example semantics comparison for reference:

  let neverChecks: Task.Handle<String, Never> = Task.runDetached {
    // never checks cancellation
    // Task.sleep(.seconds(60)) // pretend being slow
    "ok"
  }
​
  // ----
​
  // Semantics A) Cancellation truly is only co-operative
  //              These semantics would argue FOR the existence of the non-throwing get()
  neverChecks.cancel() // we cancel immediately
  // get ALWAYS throws, i.e. we're expecting this to throw a CancellationError
  // but under Semantics A won't -- we're truly cooperative, and the task never
  // checked cancellation so in reality it is as if it wasn't cancelled.
  await try neverChecks.get()
  // because the task never checked cancellation, we get "ok here"
  // Semantics A conclusion: we should offer a non throwing get()
​
  // ----
​
  // Semantics B) Cancellation is eager on handles, hard and does NOT guarantee emitting the same error
  //              These semantics would argue AGAINST the existence of the non throwing get()
  neverChecks.cancel() // we cancel immediately
  await try neverChecks.get() // under "eager" B cancellation semantics this will immediately throw
  // even if the task still executed and completed successfully (because it never checked for cancellation!)
  // this would throw a CancellationError under Semantics B

I would argue semantics A is what people are meaningfully after, and it allows building more predictably on the tasks / handles. This would imply that we do need the non throwing get.

@ktoso
Copy link
Contributor Author

ktoso commented Oct 27, 2020

Ended up addressing in here some of the comments @DougGregor mentioned.

@ktoso
Copy link
Contributor Author

ktoso commented Oct 27, 2020

@swift-ci please test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants