# \[Pitch 2\] Custom Main and Global Executors

**URL:** <https://forums.swift.org/t/pitch-2-custom-main-and-global-executors/78437>\
**Category:** Pitches\
**Created:** [March 11, 2025, 4:33pm UTC](https://forums.swift.org/t/pitch-2-custom-main-and-global-executors/78437 "2025-03-11T16:33:23Z")\
**Posts on this page:** 1\
**Showing post:** 41

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [April 9, 2025, 2:05am UTC](https://forums.swift.org/t/pitch-2-custom-main-and-global-executors/78437/41 "2025-04-09T02:05:33Z")

</div>

There is a _lot_ in this proposal; at least two distinct features. it might be difficult to review as a single piece.

> [@al45tair](#):
>
> We do want to support arbitrary `Clock`s here, yes. Part of the point here is that you can make your own e.g. `UTCClock` and then use it with `Task.sleep()`. Executors will very likely be constrained in how they can actually sleep, but that doesn't stop us from converting the timestamps or delays to a clock they know how to sleep on.

How is that supposed to happen, though? I see that you're adding a `convert` operation to `Clock` that converts an arbitrary instant of an arbitrary other clock into this clock, but it's really unclear how that could possibly work for a truly arbitrary clock. The idea seems to be that it looks at the clock traits and picks one of the system implementations, but that's effectively requiring all useful implementations of `Clock` to be essentially like one of the system clocks. And as an abstract operation on clocks, it doesn't really make much sense — there's no meaningful way to turn a future instant of a suspending clock into any other measure of time.

Rather than asking executors to do this somewhat heroic recognition of different kinds of clocks, it might make sense to add a new primitive scheduling operation to `Clock`. `Clock.sleep()` is already a scheduling operation, so this wouldn't be crossing any surprising boundaries. The only problem with `Clock.sleep()` as a scheduling operation is that it's so high-level that it doesn't give you primitive control, but that's fixable with a new operation, and of course the new operation can be (inefficiently) implemented in terms of the old.

I would suggest this:

```swift
protocol Clock {
  /// Run the given job on an unspecified executor at some point
  /// after the given instant.
  func run(_ job: consuming ExecutorJob,
           after: Instant, tolerance: Duration?)
}

```

`SchedulableExecutor.enqueue` can try to recognize specific clocks, but if it sees one it doesn't recognize, it can fall back on the above, passing a new job that immediately enqueues the original job on `self`. This is basically always fine as a fallback, and it'll usually be necessary anyway, since systems do not have a general ability to trigger timers on an arbitrary executor, and any optimized path for a particular clock + executor that does exist is necessarily specific to the pair.

Why does `SchedulableExecutor` offer both `enqueue(_:after:tolerance:clock:)` and `enqueue(_:at:tolerance:clock)` as requirements? Are there different clocks that prefer each of these for some reason? My perhaps-ignorant expectation is that allowing a duration to be specified is a user-facing convenience — a perfectly reasonable thing to offer as a protocol extension method — but that in the core implementation (and thus the generic entry-points) we'd always want to derive the target instant ASAP and then wait for that rather than passing the duration around.

Also, is it important to distinguish `SchedulableExecutor` from `Executor`? It seems to me that pulling this up to `Executor` and giving it a default implementation that does a double-dispatch would be perfectly fine.

I think if you do all this, you don't need clock instant/duration conversion or the clock traits.

---

_[View the full topic](https://forums.swift.org/t/pitch-2-custom-main-and-global-executors/78437)._
