Skip to content

[Concurrency] Updates after second SE pitch. #82456

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

al45tair
Copy link
Contributor

@al45tair al45tair commented Jun 24, 2025

We're changing our approach to Clock support in executors such that a clock that isn't recognised by an executor will result in a call to an enqueue method on Clock itself; this will allow clocks to have control over exactly how they schedule jobs in cases where the executor doesn't already know what to do.

Also includes a small bug fix for CooperativeExecutor and some updated comments.

rdar://154191435

@al45tair al45tair requested review from a team and ktoso as code owners June 24, 2025 14:07
@al45tair al45tair requested a review from rjmccall June 24, 2025 14:09
@al45tair
Copy link
Contributor Author

@swift-ci Please smoke test

@al45tair al45tair force-pushed the concurrency-updates branch from 2a19c34 to 8c00ea0 Compare June 26, 2025 10:32
@al45tair
Copy link
Contributor Author

@swift-ci Please smoke test

///
/// Parameters:
///
/// - from duration: The `Duration` to convert
/// - job: The job we wish to run
/// - at instant: The time at which we would like it to run.
Copy link
Contributor

Choose a reason for hiding this comment

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

does spelling params like this actually parse well in docc? I thought one has to put only the second name 🤔

/// given instant.
///
/// The default implementation uses the `run` method to trigger a job that
/// does `executor.enqueue(job)`. If a particular `Clock` knows that the
Copy link
Contributor

Choose a reason for hiding this comment

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

minor

Suggested change
/// does `executor.enqueue(job)`. If a particular `Clock` knows that the
/// does `executor.enqueue(job)`. If a particular ``Clock`` knows that the

maybe worth ref like that?

run(trampoline, at: instant, tolerance: tolerance)
}

// Clocks that do not implement run will fatalError() if you try to use
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Clocks that do not implement run will fatalError() if you try to use
// Clocks that do not implement this method will fatalError() if you try to use

maybe? "implement run" sounds a bit weird mid-sentence

// Convert to `Swift.Duration`
let duration = clock.convert(from: delay)!
let duration = delay as! Swift.Duration
Copy link
Contributor

Choose a reason for hiding this comment

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

can we put a comment here discussing the as!'s risk, could it ever fail?

// executor.
extension ExecutorJob {

/// Create a trampoline to enqueue the specified job on the specified
Copy link
Contributor

Choose a reason for hiding this comment

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

minor?

Suggested change
/// Create a trampoline to enqueue the specified job on the specified
/// Create a trampoline to enqueue this job on the specified

/// Create a trampoline to enqueue the specified job on the specified
/// executor.
///
/// This is useful in conjunction with the `Clock.run()` API, which
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this'll link well:

Suggested change
/// This is useful in conjunction with the `Clock.run()` API, which
/// This is useful in conjunction with the ``Clock.run(_:at:tolerance:)`` API, which

///
/// Returns:
///
/// A new ExecutorJob that will enqueue the specified job on the specified
Copy link
Contributor

@ktoso ktoso Jun 27, 2025

Choose a reason for hiding this comment

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

Suggested change
/// A new ExecutorJob that will enqueue the specified job on the specified
// - Returns: A new ExecutorJob that will enqueue the specified job on the specified

needs the - I think?

/// This is useful in conjunction with the `Clock.run()` API, which
/// runs a job on an unspecified executor.
///
/// Parameters:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Parameters:
/// - Parameters:

Needs the - I think?

Copy link
Contributor

@ktoso ktoso left a comment

Choose a reason for hiding this comment

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

lgtm, sorry about the docs nitpicks! I don't actually have a great way to preview those in tree I guess 🤔

@al45tair
Copy link
Contributor Author

lgtm, sorry about the docs nitpicks! I don't actually have a great way to preview those in tree I guess 🤔

No worries. I think you're right about the doc comments; I'll go and update them all.

@al45tair al45tair requested a review from jckarter as a code owner July 2, 2025 13:25
al45tair added 7 commits July 2, 2025 15:13
We no longer attempt to convert timestamps from the passed-in `Clock`
in order to allow any clock to work with any executor.  Instead,
executors that do not recognise a clock should call the `enqueue`
function on that `Clock`, which lets the `Clock` itself decide how
to proceed.

Additionally, rename `SchedulableExecutor` to `SchedulingExecutor`.
…cks.

The built-in clocks should have implementations of `run` and `enqueue`,
to allow derived clocks to call those implementations.
I don't think we actually need this.  If you have a non-canonical
(i.e. derived) clock, you can just implement `enqueue` and/or `run`
and call those methods on the clock you're wrapping.
If a job enqueues another job on the executor, we might never leave
the inner `while` loop in the `run()` method.  Fix this by taking
the contents of the run queue and only running those jobs in the
queue at the time we enter the inner loop.
Add some documentation comments to the Dispatch and CF executors,
and update the comments for the allocation and private data APIs.
Rather than just looking at top level in the module, start by searching
the type marked as `@main`.  This means that a library that provides a
protocol or superclass that the `@main` type can conform to can specify
an executor in a reasonable manner.
Also add `final` to the `CooperativeExecutor` declaration.
@al45tair al45tair force-pushed the concurrency-updates branch from 38ead6d to 262f07a Compare July 2, 2025 14:13
@al45tair
Copy link
Contributor Author

al45tair commented Jul 2, 2025

(Haven't updated doc comments yet; that's the next job…)

Some formatting fixes for the doc comments.
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.

2 participants