Files
swift-mirror/stdlib/public/Darwin/Foundation/Schedulers+RunLoop.swift
2020-03-24 11:30:45 -07:00

200 lines
6.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// Only support 64bit
#if !(os(iOS) && (arch(i386) || arch(arm)))
@_exported import Foundation // Clang module
import Combine
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
extension RunLoop: Scheduler {
/// The scheduler time type used by the run loop.
public struct SchedulerTimeType: Strideable, Codable, Hashable {
/// The date represented by this type.
public var date: Date
/// Initializes a run loop scheduler time with the given date.
///
/// - Parameter date: The date to represent.
public init(_ date: Date) {
self.date = date
}
/// Returns the distance to another run loop scheduler time.
///
/// - Parameter other: Another dispatch queue time.
/// - Returns: The time interval between this time and the provided time.
public func distance(to other: RunLoop.SchedulerTimeType) -> SchedulerTimeType.Stride {
return Stride(floatLiteral: date.distance(to: other.date))
}
/// Returns a run loop scheduler time calculated by advancing this instances time by the given interval.
///
/// - Parameter n: A time interval to advance.
/// - Returns: A dispatch queue time advanced by the given interval from this instances time.
public func advanced(by n: SchedulerTimeType.Stride) -> RunLoop.SchedulerTimeType {
return SchedulerTimeType(date.advanced(by: n.timeInterval))
}
/// The interval by which run loop times advance.
public struct Stride: ExpressibleByFloatLiteral, Comparable, SignedNumeric, Codable, SchedulerTimeIntervalConvertible {
public typealias FloatLiteralType = TimeInterval
public typealias IntegerLiteralType = TimeInterval
public typealias Magnitude = TimeInterval
/// The value of this time interval in seconds.
public var magnitude: TimeInterval
/// The value of this time interval in seconds.
public var timeInterval: TimeInterval {
return magnitude
}
public init(integerLiteral value: TimeInterval) {
magnitude = value
}
public init(floatLiteral value: TimeInterval) {
magnitude = value
}
public init(_ timeInterval: TimeInterval) {
magnitude = timeInterval
}
public init?<T>(exactly source: T) where T: BinaryInteger {
if let d = TimeInterval(exactly: source) {
magnitude = d
} else {
return nil
}
}
// ---
public static func < (lhs: Stride, rhs: Stride) -> Bool {
return lhs.magnitude < rhs.magnitude
}
// ---
public static func * (lhs: Stride, rhs: Stride) -> Stride {
return Stride(lhs.timeInterval * rhs.timeInterval)
}
public static func + (lhs: Stride, rhs: Stride) -> Stride {
return Stride(lhs.magnitude + rhs.magnitude)
}
public static func - (lhs: Stride, rhs: Stride) -> Stride {
return Stride(lhs.magnitude - rhs.magnitude)
}
// ---
public static func *= (lhs: inout Stride, rhs: Stride) {
let result = lhs * rhs
lhs = result
}
public static func += (lhs: inout Stride, rhs: Stride) {
let result = lhs + rhs
lhs = result
}
public static func -= (lhs: inout Stride, rhs: Stride) {
let result = lhs - rhs
lhs = result
}
// ---
public static func seconds(_ s: Int) -> Stride {
return Stride(Double(s))
}
public static func seconds(_ s: Double) -> Stride {
return Stride(s)
}
public static func milliseconds(_ ms: Int) -> Stride {
return Stride(Double(ms) / 1_000.0)
}
public static func microseconds(_ us: Int) -> Stride {
return Stride(Double(us) / 1_000_000.0)
}
public static func nanoseconds(_ ns: Int) -> Stride {
return Stride(Double(ns) / 1_000_000_000.0)
}
}
}
/// Options that affect the operation of the run loop scheduler.
public struct SchedulerOptions { }
public func schedule(options: SchedulerOptions?,
_ action: @escaping () -> Void) {
self.perform(action)
}
public func schedule(after date: SchedulerTimeType,
tolerance: SchedulerTimeType.Stride,
options: SchedulerOptions?,
_ action: @escaping () -> Void) {
let ti = date.date.timeIntervalSince(Date())
self.perform(#selector(self.runLoopScheduled), with: _CombineRunLoopAction(action), afterDelay: ti)
}
public func schedule(after date: SchedulerTimeType,
interval: SchedulerTimeType.Stride,
tolerance: SchedulerTimeType.Stride,
options: SchedulerOptions?,
_ action: @escaping () -> Void) -> Cancellable {
let timer = Timer(fire: date.date, interval: interval.timeInterval, repeats: true) { _ in
action()
}
timer.tolerance = tolerance.timeInterval
self.add(timer, forMode: .default)
return AnyCancellable(timer.invalidate)
}
public var now: SchedulerTimeType {
return SchedulerTimeType(Date())
}
public var minimumTolerance: SchedulerTimeType.Stride {
return 0.0
}
@objc
fileprivate func runLoopScheduled(action: _CombineRunLoopAction) {
action.action()
}
}
@objc
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
private class _CombineRunLoopAction: NSObject {
let action: () -> Void
init(_ action: @escaping () -> Void) {
self.action = action
}
}
#endif /* !(os(iOS) && (arch(i386) || arch(arm))) */