@@ -123,6 +123,40 @@ extension DispatchWallTime {
123
123
}
124
124
}
125
125
126
+ // Returns m1 * m2, clamped to the range [Int64.min, Int64.max].
127
+ // Because of the way this function is used, we can always assume
128
+ // that m2 > 0.
129
+ private func clampedInt64Product( _ m1: Int64 , _ m2: Int64 ) -> Int64 {
130
+ assert ( m2 > 0 , " multiplier must be positive " )
131
+ let ( result, overflow) = m1. multipliedReportingOverflow ( by: m2)
132
+ if overflow {
133
+ return m1 > 0 ? Int64 . max : Int64 . min
134
+ }
135
+ return result
136
+ }
137
+
138
+ // Returns its argument clamped to the range [Int64.min, Int64.max].
139
+ private func toInt64Clamped( _ value: Double ) -> Int64 {
140
+ if value. isNaN { return Int64 . max }
141
+ if value >= Double ( Int64 . max) { return Int64 . max }
142
+ if value <= Double ( Int64 . min) { return Int64 . min }
143
+ return Int64 ( value)
144
+ }
145
+
146
+ /// Represents a time interval that can be used as an offset from a `DispatchTime`
147
+ /// or `DispatchWallTime`.
148
+ ///
149
+ /// For example:
150
+ /// let inOneSecond = DispatchTime.now() + DispatchTimeInterval.seconds(1)
151
+ ///
152
+ /// If the requested time interval is larger then the internal representation
153
+ /// permits, the result of adding it to a `DispatchTime` or `DispatchWallTime`
154
+ /// is `DispatchTime.distantFuture` and `DispatchWallTime.distantFuture`
155
+ /// respectively. Such time intervals compare as equal:
156
+ ///
157
+ /// let t1 = DispatchTimeInterval.seconds(Int.max)
158
+ /// let t2 = DispatchTimeInterval.milliseconds(Int.max)
159
+ /// let result = t1 == t2 // true
126
160
public enum DispatchTimeInterval {
127
161
case seconds( Int )
128
162
case milliseconds( Int )
@@ -133,9 +167,9 @@ public enum DispatchTimeInterval {
133
167
134
168
internal var rawValue : Int64 {
135
169
switch self {
136
- case . seconds( let s) : return Int64 ( s) * Int64( NSEC_PER_SEC)
137
- case . milliseconds( let ms) : return Int64 ( ms) * Int64( NSEC_PER_MSEC)
138
- case . microseconds( let us) : return Int64 ( us) * Int64( NSEC_PER_USEC)
170
+ case . seconds( let s) : return clampedInt64Product ( Int64 ( s) , Int64 ( NSEC_PER_SEC) )
171
+ case . milliseconds( let ms) : return clampedInt64Product ( Int64 ( ms) , Int64 ( NSEC_PER_MSEC) )
172
+ case . microseconds( let us) : return clampedInt64Product ( Int64 ( us) , Int64 ( NSEC_PER_USEC) )
139
173
case . nanoseconds( let ns) : return Int64 ( ns)
140
174
case . never: return Int64 . max
141
175
}
@@ -162,16 +196,12 @@ public func -(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTim
162
196
}
163
197
164
198
public func + ( time: DispatchTime , seconds: Double ) -> DispatchTime {
165
- let interval = seconds * Double( NSEC_PER_SEC)
166
- let t = CDispatch . dispatch_time ( time. rawValue,
167
- interval. isInfinite || interval. isNaN ? Int64 . max : Int64 ( interval) )
199
+ let t = CDispatch . dispatch_time ( time. rawValue, toInt64Clamped ( seconds * Double( NSEC_PER_SEC) ) ) ;
168
200
return DispatchTime ( rawValue: t)
169
201
}
170
202
171
203
public func - ( time: DispatchTime , seconds: Double ) -> DispatchTime {
172
- let interval = - seconds * Double( NSEC_PER_SEC)
173
- let t = CDispatch . dispatch_time ( time. rawValue,
174
- interval. isInfinite || interval. isNaN ? Int64 . min : Int64 ( interval) )
204
+ let t = CDispatch . dispatch_time ( time. rawValue, toInt64Clamped ( - seconds * Double( NSEC_PER_SEC) ) ) ;
175
205
return DispatchTime ( rawValue: t)
176
206
}
177
207
@@ -186,15 +216,11 @@ public func -(time: DispatchWallTime, interval: DispatchTimeInterval) -> Dispatc
186
216
}
187
217
188
218
public func + ( time: DispatchWallTime , seconds: Double ) -> DispatchWallTime {
189
- let interval = seconds * Double( NSEC_PER_SEC)
190
- let t = CDispatch . dispatch_time ( time. rawValue,
191
- interval. isInfinite || interval. isNaN ? Int64 . max : Int64 ( interval) )
219
+ let t = CDispatch . dispatch_time ( time. rawValue, toInt64Clamped ( seconds * Double( NSEC_PER_SEC) ) ) ;
192
220
return DispatchWallTime ( rawValue: t)
193
221
}
194
222
195
223
public func - ( time: DispatchWallTime , seconds: Double ) -> DispatchWallTime {
196
- let interval = - seconds * Double( NSEC_PER_SEC)
197
- let t = CDispatch . dispatch_time ( time. rawValue,
198
- interval. isInfinite || interval. isNaN ? Int64 . min : Int64 ( interval) )
224
+ let t = CDispatch . dispatch_time ( time. rawValue, toInt64Clamped ( - seconds * Double( NSEC_PER_SEC) ) ) ;
199
225
return DispatchWallTime ( rawValue: t)
200
226
}
0 commit comments