Signal-iOS/SignalServiceKit/Util/OffMainThreadTimer.swift
Jordan Rose b0de59f2e2 Remove required from every init that is not dynamically dispatched
This included:
- Removing unavailable inits wholesale if no longer `required`
- Marking a few classes `final` so they could continue using
  `Self(...)` rather than `OWSWhatever(...)`
2024-04-01 15:27:20 -07:00

66 lines
1.5 KiB
Swift

//
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
// A thread-safe timer that runs on a specific queue and which
// can be safely created, invalidated or deallocated on any thread.
public class OffMainThreadTimer {
private let timeInterval: TimeInterval
private let repeats: Bool
private let queue: DispatchQueue
public typealias Block = (OffMainThreadTimer) -> Void
private let block: Block
private let _isValid = AtomicBool(true, lock: .sharedGlobal)
public var isValid: Bool {
get { _isValid.get() }
set { _isValid.set(newValue) }
}
public init(timeInterval: TimeInterval,
repeats: Bool,
queue: DispatchQueue = .global(),
_ block: @escaping Block) {
owsAssertDebug(timeInterval > 0)
self.timeInterval = max(0, timeInterval)
self.repeats = repeats
self.queue = queue
self.block = block
scheduleNextFire()
}
private func scheduleNextFire() {
queue.asyncAfter(deadline: .now() + timeInterval) { [weak self] in
self?.fire()
}
}
private func fire() {
assertOnQueue(queue)
guard self.isValid else {
return
}
block(self)
guard repeats else {
invalidate()
return
}
scheduleNextFire()
}
deinit {
invalidate()
}
public func invalidate() {
isValid = false
}
}