]> git.saurik.com Git - apple/libdispatch.git/blobdiff - src/swift/Time.swift
libdispatch-913.30.4.tar.gz
[apple/libdispatch.git] / src / swift / Time.swift
index a9559fd24a161bf0ea8398e09247d7836e50d023..d7d49c96b92f7e14d5a95f58097efca8b658cec5 100644 (file)
 import CDispatch
 
 public struct DispatchTime : Comparable {
+#if HAVE_MACH
+       private static let timebaseInfo: mach_timebase_info_data_t = {
+               var info = mach_timebase_info_data_t(numer: 1, denom: 1)
+               mach_timebase_info(&info)
+               return info
+       }()
+#endif
        public let rawValue: dispatch_time_t
 
        public static func now() -> DispatchTime {
@@ -37,12 +45,36 @@ public struct DispatchTime : Comparable {
        ///   - uptimeNanoseconds: The number of nanoseconds since boot, excluding
        ///                        time the system spent asleep
        /// - Returns: A new `DispatchTime`
+       /// - Discussion: This clock is the same as the value returned by
+       ///               `mach_absolute_time` when converted into nanoseconds.
+       ///               On some platforms, the nanosecond value is rounded up to a
+       ///               multiple of the Mach timebase, using the conversion factors
+       ///               returned by `mach_timebase_info()`. The nanosecond equivalent
+       ///               of the rounded result can be obtained by reading the
+       ///               `uptimeNanoseconds` property.
+       ///               Note that `DispatchTime(uptimeNanoseconds: 0)` is
+       ///               equivalent to `DispatchTime.now()`, that is, its value
+       ///               represents the number of nanoseconds since boot (excluding
+       ///               system sleep time), not zero nanoseconds since boot.
        public init(uptimeNanoseconds: UInt64) {
-               self.rawValue = dispatch_time_t(uptimeNanoseconds)
+               var rawValue = uptimeNanoseconds
+#if HAVE_MACH
+               if (DispatchTime.timebaseInfo.numer != DispatchTime.timebaseInfo.denom) {
+                       rawValue = (rawValue * UInt64(DispatchTime.timebaseInfo.denom) 
+                               + UInt64(DispatchTime.timebaseInfo.numer - 1)) / UInt64(DispatchTime.timebaseInfo.numer)
+               }
+#endif
+               self.rawValue = dispatch_time_t(rawValue)
        }
 
        public var uptimeNanoseconds: UInt64 {
-               return UInt64(self.rawValue)
+               var result = self.rawValue
+#if HAVE_MACH
+               if (DispatchTime.timebaseInfo.numer != DispatchTime.timebaseInfo.denom) {
+                       result = result * UInt64(DispatchTime.timebaseInfo.numer) / UInt64(DispatchTime.timebaseInfo.denom)
+               }
+#endif
+               return result
        }
 }
 
@@ -75,8 +107,12 @@ public struct DispatchWallTime : Comparable {
 }
 
 public func <(a: DispatchWallTime, b: DispatchWallTime) -> Bool {
-       if a.rawValue == ~0 || b.rawValue == ~0 { return false }
-       return -Int64(a.rawValue) < -Int64(b.rawValue)
+       if b.rawValue == ~0 {
+               return a.rawValue != ~0
+       } else if a.rawValue == ~0 {
+               return false
+       }
+       return -Int64(bitPattern: a.rawValue) < -Int64(bitPattern: b.rawValue)
 }
 
 public func ==(a: DispatchWallTime, b: DispatchWallTime) -> Bool {
@@ -88,6 +124,8 @@ public enum DispatchTimeInterval {
        case milliseconds(Int)
        case microseconds(Int)
        case nanoseconds(Int)
+       @_downgrade_exhaustivity_check
+       case never
 
        internal var rawValue: Int64 {
                switch self {
@@ -95,6 +133,16 @@ public enum DispatchTimeInterval {
                case .milliseconds(let ms): return Int64(ms) * Int64(NSEC_PER_MSEC)
                case .microseconds(let us): return Int64(us) * Int64(NSEC_PER_USEC)
                case .nanoseconds(let ns): return Int64(ns)
+               case .never: return Int64.max
+               }
+       }
+
+       public static func ==(lhs: DispatchTimeInterval, rhs: DispatchTimeInterval) -> Bool {
+               switch (lhs, rhs) {
+               case (.never, .never): return true
+               case (.never, _): return false
+               case (_, .never): return false
+               default: return lhs.rawValue == rhs.rawValue
                }
        }
 }
@@ -110,12 +158,16 @@ public func -(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTim
 }
 
 public func +(time: DispatchTime, seconds: Double) -> DispatchTime {
-       let t = CDispatch.dispatch_time(time.rawValue, Int64(seconds * Double(NSEC_PER_SEC)))
+       let interval = seconds * Double(NSEC_PER_SEC)
+       let t = CDispatch.dispatch_time(time.rawValue,
+               interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
        return DispatchTime(rawValue: t)
 }
 
 public func -(time: DispatchTime, seconds: Double) -> DispatchTime {
-       let t = CDispatch.dispatch_time(time.rawValue, Int64(-seconds * Double(NSEC_PER_SEC)))
+       let interval = -seconds * Double(NSEC_PER_SEC)
+       let t = CDispatch.dispatch_time(time.rawValue,
+               interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
        return DispatchTime(rawValue: t)
 }
 
@@ -130,11 +182,15 @@ public func -(time: DispatchWallTime, interval: DispatchTimeInterval) -> Dispatc
 }
 
 public func +(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
-       let t = CDispatch.dispatch_time(time.rawValue, Int64(seconds * Double(NSEC_PER_SEC)))
+       let interval = seconds * Double(NSEC_PER_SEC)
+       let t = CDispatch.dispatch_time(time.rawValue,
+               interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
        return DispatchWallTime(rawValue: t)
 }
 
 public func -(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
-       let t = CDispatch.dispatch_time(time.rawValue, Int64(-seconds * Double(NSEC_PER_SEC)))
+       let interval = -seconds * Double(NSEC_PER_SEC)
+       let t = CDispatch.dispatch_time(time.rawValue,
+               interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
        return DispatchWallTime(rawValue: t)
 }