@@ -40,52 +40,64 @@ public protocol Clock<Duration>: Sendable {
40
40
41
41
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
42
42
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 }
48
43
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.
55
46
///
56
47
/// Parameters:
57
48
///
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.
59
52
///
60
- /// Returns: A `Swift.Duration` representing the equivalent duration, or
61
- /// `nil` if this function is not supported.
62
53
@available ( StdlibDeploymentTarget 6 . 2 , * )
63
- func convert( from duration: Duration ) -> Swift . Duration ?
54
+ func run( _ job: consuming ExecutorJob ,
55
+ at instant: Instant , tolerance: Duration ? )
64
56
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.
66
65
///
67
66
/// Parameters:
68
67
///
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.
70
72
///
71
- /// Returns: A `Duration` representing the equivalent duration, or
72
- /// `nil` if this function is not supported.
73
73
@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
+ }
75
79
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.
85
84
@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
+ }
88
99
}
100
+ #endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
89
101
90
102
@available ( StdlibDeploymentTarget 5 . 7 , * )
91
103
extension Clock {
@@ -140,44 +152,6 @@ extension Clock {
140
152
}
141
153
}
142
154
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
-
181
155
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
182
156
@available ( StdlibDeploymentTarget 5 . 7 , * )
183
157
extension Clock {
@@ -196,47 +170,10 @@ extension Clock {
196
170
}
197
171
#endif
198
172
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
-
237
173
enum _ClockID : Int32 {
238
174
case continuous = 1
239
175
case suspending = 2
176
+ case walltime = 3
240
177
}
241
178
242
179
@available ( StdlibDeploymentTarget 5 . 7 , * )
0 commit comments