@@ -40,52 +40,64 @@ public protocol Clock<Duration>: Sendable {
4040
4141#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
4242 func sleep( until deadline: Instant , tolerance: Instant . Duration ? ) async throws
43- #endif
44-
45- /// The traits associated with this clock instance.
46- @available ( StdlibDeploymentTarget 6 . 2 , * )
47- var traits : ClockTraits { get }
4843
49- /// Convert a Clock-specific Duration to a Swift Duration
50- ///
51- /// Some clocks may define `C.Duration` to be something other than a
52- /// `Swift.Duration`, but that makes it tricky to convert timestamps
53- /// between clocks, which is something we want to be able to support.
54- /// This method will convert whatever `C.Duration` is to a `Swift.Duration`.
44+ /// Run the given job on an unspecified executor at some point
45+ /// after the given instant.
5546 ///
5647 /// Parameters:
5748 ///
58- /// - from duration: The `Duration` to convert
49+ /// - job: The job we wish to run
50+ /// - at instant: The time at which we would like it to run.
51+ /// - tolerance: The ideal maximum delay we are willing to tolerate.
5952 ///
60- /// Returns: A `Swift.Duration` representing the equivalent duration, or
61- /// `nil` if this function is not supported.
6253 @available ( StdlibDeploymentTarget 6 . 2 , * )
63- func convert( from duration: Duration ) -> Swift . Duration ?
54+ func run( _ job: consuming ExecutorJob ,
55+ at instant: Instant , tolerance: Duration ? )
6456
65- /// Convert a Swift Duration to a Clock-specific Duration
57+ /// Enqueue the given job on the specified executor at some point after the
58+ /// given instant.
59+ ///
60+ /// The default implementation uses the `run` method to trigger a job that
61+ /// does `executor.enqueue(job)`. If a particular `Clock` knows that the
62+ /// executor it has been asked to use is the same one that it will run jobs
63+ /// on, it can short-circuit this behaviour and directly use `run` with
64+ /// the original job.
6665 ///
6766 /// Parameters:
6867 ///
69- /// - from duration: The `Swift.Duration` to convert.
68+ /// - job: The job we wish to run
69+ /// - on executor: The executor on which we would like it to run.
70+ /// - at instant: The time at which we would like it to run.
71+ /// - tolerance: The ideal maximum delay we are willing to tolerate.
7072 ///
71- /// Returns: A `Duration` representing the equivalent duration, or
72- /// `nil` if this function is not supported.
7373 @available ( StdlibDeploymentTarget 6 . 2 , * )
74- func convert( from duration: Swift . Duration ) -> Duration ?
74+ func enqueue( _ job: consuming ExecutorJob ,
75+ on executor: some Executor ,
76+ at instant: Instant , tolerance: Duration ? )
77+ #endif
78+ }
7579
76- /// Convert an `Instant` from some other clock's `Instant`
77- ///
78- /// Parameters:
79- ///
80- /// - instant: The instant to convert.
81- // - from clock: The clock to convert from.
82- ///
83- /// Returns: An `Instant` representing the equivalent instant, or
84- /// `nil` if this function is not supported.
80+ #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
81+ extension Clock {
82+ // The default implementation works by creating a trampoline and calling
83+ // the run() method.
8584 @available ( StdlibDeploymentTarget 6 . 2 , * )
86- func convert< OtherClock: Clock > ( instant: OtherClock . Instant ,
87- from clock: OtherClock ) -> Instant ?
85+ public func enqueue( _ job: consuming ExecutorJob ,
86+ on executor: some Executor ,
87+ at instant: Instant , tolerance: Duration ? ) {
88+ let trampoline = job. createTrampoline ( to: executor)
89+ run ( trampoline, at: instant, tolerance: tolerance)
90+ }
91+
92+ // Clocks that do not implement run will fatalError() if you try to use
93+ // them with an executor that does not understand them.
94+ @available ( StdlibDeploymentTarget 6 . 2 , * )
95+ public func run( _ job: consuming ExecutorJob ,
96+ at instant: Instant , tolerance: Duration ? ) {
97+ fatalError ( " \( Self . self) does not implement run(_:at:tolerance:). " )
98+ }
8899}
100+ #endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
89101
90102@available ( StdlibDeploymentTarget 5 . 7 , * )
91103extension Clock {
@@ -140,44 +152,6 @@ extension Clock {
140152 }
141153}
142154
143- @available ( StdlibDeploymentTarget 6 . 2 , * )
144- extension Clock {
145- // For compatibility, return `nil` if this is not implemented
146- public func convert( from duration: Duration ) -> Swift . Duration ? {
147- return nil
148- }
149-
150- public func convert( from duration: Swift . Duration ) -> Duration ? {
151- return nil
152- }
153-
154- public func convert< OtherClock: Clock > ( instant: OtherClock . Instant ,
155- from clock: OtherClock ) -> Instant ? {
156- let ourNow = now
157- let otherNow = clock. now
158- let otherDuration = otherNow. duration ( to: instant)
159-
160- // Convert to `Swift.Duration`
161- guard let duration = clock. convert ( from: otherDuration) else {
162- return nil
163- }
164-
165- // Convert from `Swift.Duration`
166- guard let ourDuration = convert ( from: duration) else {
167- return nil
168- }
169-
170- return ourNow. advanced ( by: ourDuration)
171- }
172- }
173-
174- @available ( StdlibDeploymentTarget 6 . 2 , * )
175- extension Clock where Duration == Swift . Duration {
176- public func convert( from duration: Duration ) -> Duration ? {
177- return duration
178- }
179- }
180-
181155#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
182156@available ( StdlibDeploymentTarget 5 . 7 , * )
183157extension Clock {
@@ -196,47 +170,10 @@ extension Clock {
196170}
197171#endif
198172
199- /// Represents traits of a particular Clock implementation.
200- ///
201- /// Clocks may be of a number of different varieties; executors will likely
202- /// have specific clocks that they can use to schedule jobs, and will
203- /// therefore need to be able to convert timestamps to an appropriate clock
204- /// when asked to enqueue a job with a delay or deadline.
205- ///
206- /// Choosing a clock in general requires the ability to tell which of their
207- /// clocks best matches the clock that the user is trying to specify a
208- /// time or delay in. Executors are expected to do this on a best effort
209- /// basis.
210- @available ( StdlibDeploymentTarget 6 . 2 , * )
211- public struct ClockTraits : OptionSet {
212- public let rawValue : UInt32
213-
214- public init ( rawValue: UInt32 ) {
215- self . rawValue = rawValue
216- }
217-
218- /// Clocks with this trait continue running while the machine is asleep.
219- public static let continuous = ClockTraits ( rawValue: 1 << 0 )
220-
221- /// Indicates that a clock's time will only ever increase.
222- public static let monotonic = ClockTraits ( rawValue: 1 << 1 )
223-
224- /// Clocks with this trait are tied to "wall time".
225- public static let wallTime = ClockTraits ( rawValue: 1 << 2 )
226- }
227-
228- @available ( StdlibDeploymentTarget 6 . 2 , * )
229- extension Clock {
230- /// The traits associated with this clock instance.
231- @available ( StdlibDeploymentTarget 6 . 2 , * )
232- public var traits : ClockTraits {
233- return [ ]
234- }
235- }
236-
237173enum _ClockID : Int32 {
238174 case continuous = 1
239175 case suspending = 2
176+ case walltime = 3
240177}
241178
242179@available ( StdlibDeploymentTarget 5 . 7 , * )
0 commit comments