1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Async Algorithms open source project
//
// Copyright (c) 2022 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
//
//===----------------------------------------------------------------------===//
/// An `AsyncSequence` that produces elements at regular intervals.
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
public struct AsyncTimerSequence<C: Clock>: AsyncSequence {
public typealias Element = C.Instant
/// The iterator for an `AsyncTimerSequence` instance.
public struct Iterator: AsyncIteratorProtocol {
var clock: C?
let interval: C.Instant.Duration
let tolerance: C.Instant.Duration?
var last: C.Instant?
init(interval: C.Instant.Duration, tolerance: C.Instant.Duration?, clock: C) {
self.clock = clock
self.interval = interval
self.tolerance = tolerance
}
public mutating func next() async -> C.Instant? {
guard let clock = self.clock else {
return nil
}
let next = (self.last ?? clock.now).advanced(by: self.interval)
do {
try await clock.sleep(until: next, tolerance: self.tolerance)
} catch {
self.clock = nil
return nil
}
let now = clock.now
self.last = next
return now
}
}
let clock: C
let interval: C.Instant.Duration
let tolerance: C.Instant.Duration?
/// Create an `AsyncTimerSequence` with a given repeating interval.
public init(interval: C.Instant.Duration, tolerance: C.Instant.Duration? = nil, clock: C) {
self.clock = clock
self.interval = interval
self.tolerance = tolerance
}
public func makeAsyncIterator() -> Iterator {
Iterator(interval: interval, tolerance: tolerance, clock: clock)
}
}
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
extension AsyncTimerSequence {
/// Create an `AsyncTimerSequence` with a given repeating interval.
public static func repeating(every interval: C.Instant.Duration, tolerance: C.Instant.Duration? = nil, clock: C) -> AsyncTimerSequence<C> {
return AsyncTimerSequence(interval: interval, tolerance: tolerance, clock: clock)
}
}
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
extension AsyncTimerSequence where C == SuspendingClock {
/// Create an `AsyncTimerSequence` with a given repeating interval.
public static func repeating(every interval: Duration, tolerance: Duration? = nil) -> AsyncTimerSequence<SuspendingClock> {
return AsyncTimerSequence(interval: interval, tolerance: tolerance, clock: SuspendingClock())
}
}
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
extension AsyncTimerSequence: Sendable { }
@available(*, unavailable)
extension AsyncTimerSequence.Iterator: Sendable { }
|