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