From 3d08723522d665bab8a1a9014e48b0acb6a76f74 Mon Sep 17 00:00:00 2001 From: Franz Busch Date: Fri, 25 Aug 2023 13:19:02 +0100 Subject: [PATCH] Remove background correction in `AsyncTimerSequence` # Motivation Currently, the `AsyncTimerSequence` is trying to correct for when an application becomes suspended and the timer might fire multiple times once the application gets foregrounded again. However, this is already handled by the `Clock` types themselves. The `SuspendingClock` is correcting for suspension of the app whereas the `ContinuousClock` is not. Additionally, this was not only hit by background an application but by just calling `Task.sleep` in the for-await loop that is consuming the sequence. # Modification This removes the part of the code in `AsyncTimerSequence` which corrected for suspension of the application. --- .../AsyncAlgorithms/AsyncTimerSequence.swift | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/Sources/AsyncAlgorithms/AsyncTimerSequence.swift b/Sources/AsyncAlgorithms/AsyncTimerSequence.swift index f3a06fc0..dcfc878b 100644 --- a/Sources/AsyncAlgorithms/AsyncTimerSequence.swift +++ b/Sources/AsyncAlgorithms/AsyncTimerSequence.swift @@ -13,59 +13,49 @@ @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) public struct AsyncTimerSequence: 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 } - - func nextDeadline(_ clock: C) -> C.Instant { - let now = clock.now - let last = self.last ?? now - let next = last.advanced(by: interval) - if next < now { - return last.advanced(by: interval * Int(((next.duration(to: now)) / interval).rounded(.up))) - } else { - return next - } - } - + public mutating func next() async -> C.Instant? { - guard let clock = clock else { + guard let clock = self.clock else { return nil } - let next = nextDeadline(clock) + + let next = (self.last ?? clock.now).advanced(by: self.interval) do { - try await clock.sleep(until: next, tolerance: tolerance) + try await clock.sleep(until: next, tolerance: self.tolerance) } catch { self.clock = nil return nil } let now = clock.now - last = next + 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) }