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