Skip to content

Initial Task Executor implementation Task(on:), addTask(on:) etc. #68793

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 53 commits into from
Dec 12, 2023

Conversation

ktoso
Copy link
Contributor

@ktoso ktoso commented Sep 27, 2023

Pending proposal and Swift Evolution process, do not merge yet.

This generally will allow tasks to be launched/spawned immediately on a specific executor or actor, and handle all the associated isolation.

Resolves rdar://107072140

@ktoso ktoso added concurrency Feature: umbrella label for concurrency language features concurrency runtime Feature: umbrella label for concurrency runtime features labels Sep 27, 2023
@ktoso ktoso force-pushed the wip-task-executors branch from 0536cc0 to 887f9f6 Compare September 27, 2023 07:54
@ktoso ktoso force-pushed the wip-task-executors branch from 887f9f6 to c0f8daf Compare October 5, 2023 07:58
@ktoso ktoso marked this pull request as draft October 6, 2023 08:10
@ktoso ktoso force-pushed the wip-task-executors branch 2 times, most recently from f18f19d to e6ad086 Compare October 17, 2023 13:26
@ktoso ktoso force-pushed the wip-task-executors branch 2 times, most recently from 8d7549b to 5bcff28 Compare November 10, 2023 08:45
@ktoso
Copy link
Contributor Author

ktoso commented Nov 10, 2023

@swift-ci please build toolchain

@ktoso ktoso force-pushed the wip-task-executors branch from 5bcff28 to 77371a9 Compare November 10, 2023 09:56
@ktoso
Copy link
Contributor Author

ktoso commented Nov 13, 2023

@swift-ci please build toolchain macOS

@ktoso ktoso force-pushed the wip-task-executors branch 2 times, most recently from 313a0bc to 16e138e Compare November 14, 2023 14:29
@ktoso
Copy link
Contributor Author

ktoso commented Nov 14, 2023

@swift-ci please smoke test

@ktoso
Copy link
Contributor Author

ktoso commented Nov 14, 2023

@swift-ci please build toolchain macOS

@ktoso ktoso changed the title [WIP] Initial Task Executor implementation Task(on:), addTask(on:) etc. Initial Task Executor implementation Task(on:), addTask(on:) etc. Nov 15, 2023
@ktoso ktoso force-pushed the wip-task-executors branch from 16e138e to c164dc1 Compare November 16, 2023 09:53
@ktoso
Copy link
Contributor Author

ktoso commented Nov 17, 2023

@swift-ci please smoke test

@ktoso ktoso marked this pull request as ready for review November 17, 2023 09:40
@ktoso ktoso requested a review from a team as a code owner November 17, 2023 09:40
Copy link
Contributor

@rjmccall rjmccall left a comment

Choose a reason for hiding this comment

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

Leaving off there for now

/// setting it during creation (`Task(on:...)`).
///
/// This means that during task tear down the record should be deallocated
/// because it was not set with a
Copy link
Contributor

Choose a reason for hiding this comment

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

Another unfinished comme

Copy link
Contributor Author

@ktoso ktoso Nov 20, 2023

Choose a reason for hiding this comment

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

Thanks, fixed in 63c8f01 and looked at all other comments as well.

/// Build a Builtin.Executor value from an "ordinary" task executor
/// reference.
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildOrdinaryTaskExecutorRef,
"buildOrdinaryTaskExecutorRef", "n", Special)
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you end up needing these builtins for some reason?

Copy link
Contributor Author

@ktoso ktoso Nov 20, 2023

Choose a reason for hiding this comment

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

edit; Yes we need those because:

struct UnownedTaskExecutor {
  // ...
  @inlinable
  public init<E: TaskExecutor>(ordinary executor: __shared E) {
    // ...
    self.executor = Builtin.buildOrdinaryTaskExecutorRef(executor)

which is different from the UnownedSerialExecutor; even though they both just store the "...Ref" style reference that's opaque in Swift. If we had different flags for Task executor than for Serial executor or something this entry points matters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Github seems to have lost my comment -- yes, we need these because:

struct UnownedTaskExecutor {

  @inlinable
  public init<E: TaskExecutor>(ordinary executor: __shared E) {
    #if $BuiltinBuildTaskExecutor
    self.executor = Builtin.buildOrdinaryTaskExecutorRef(executor)
    #else
    fatalError("Swift compiler is incompatible with this SDK version")
    #endif
  }
}

We arguably could "wing it" and use the buildOrdinaryExecutorRef though I'm unsure about the proliferation of pretending as if they're the same... Internally the representation is the same though, that is true -- the memory layout of SerialExecutorRef and TaskExecutorRef is the same, at least currently.

@@ -900,6 +918,20 @@ SerialExecutorRef swift_task_getCurrentExecutor(void);
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
SerialExecutorRef swift_task_getMainExecutor(void);

/// Return the generic (default global concurrent) executor reference.
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
SerialExecutorRef swift_task_getGenericExecutor(void);
Copy link
Contributor

Choose a reason for hiding this comment

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

If you're adding these new functions to the runtime ABI, please note which Swift release added them.

But this function in particular I think we don't need — there's an ABI-guaranteed way of constructing this already (IIRC it's the all-zeroes value).

Copy link
Contributor Author

@ktoso ktoso Nov 20, 2023

Choose a reason for hiding this comment

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

Okey, yeah I wasn't sure if we want to hardcode this assumption here -- you are right that it is guaranteed currently to be a {0, 0} basically (SerialExecutorRef), so okey if we want to assume this I removed the function and replaced it with:

@available(SwiftStdlib 9999, *)
@usableFromInline
internal func _getGenericSerialExecutor() -> Builtin.Executor {
  // The `SerialExecutorRef` to "default generic executor" is guaranteed
  // to be a zero value;
  //
  // As the runtime relies on this in multiple places,
  // so instead of a runtime call to get this executor ref, we bitcast a "zero"
  // of expected size to the builtin executor type.
  unsafeBitCast((UInt(0), UInt(0)), to: Builtin.Executor.self)
}

Is that the right UInt to use here...? In C++ it is:

  HeapObject *Identity; // Not necessarily Swift reference-countable
  uintptr_t Implementation;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did the same for _getUndefinedTaskExecutor as well, to avoid runtime calls: 1318d3e

/// It can be used used to store a record indicating that
/// there is no task executor preference in the current scope.
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
TaskExecutorRef swift_task_getUndefinedTaskExecutor(void);
Copy link
Contributor

Choose a reason for hiding this comment

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

Similarly, I don't think we need a function for this, because we really want this to be guaranteed to be the all-zeroes value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okey gotcha so I'll just bitcast zeroes and avoid the runtime call. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, and removed the runtime func -- explained more here: #68793 (comment)

TaskExecutorRef swift_task_getUndefinedTaskExecutor(void);

SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
TaskExecutorRef swift_task_getPreferredTaskExecutor(void);
Copy link
Contributor

Choose a reason for hiding this comment

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

This really needs documentation explaining the constraints on how it can be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added in: 10cadfa I think that covers the "be careful" side of things. Anything more we should add?

@ktoso ktoso force-pushed the wip-task-executors branch from 53ef9d7 to 43a8924 Compare December 11, 2023 10:59
@ktoso ktoso force-pushed the wip-task-executors branch from 43a8924 to 907b0e6 Compare December 11, 2023 11:00
@ktoso
Copy link
Contributor Author

ktoso commented Dec 11, 2023

  • Added _ to all APIs exposing the new features.
  • added Task._detached(on:) that we missed earlier.

@ktoso
Copy link
Contributor Author

ktoso commented Dec 11, 2023

@swift-ci please smoke test

@ktoso
Copy link
Contributor Author

ktoso commented Dec 12, 2023

@swift-ci please smoke test macOS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
concurrency runtime Feature: umbrella label for concurrency runtime features concurrency Feature: umbrella label for concurrency language features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants