diff --git a/SwiftSignalKit/Signal_Timing.swift b/SwiftSignalKit/Signal_Timing.swift index dc5316be60..a96fbbae6f 100644 --- a/SwiftSignalKit/Signal_Timing.swift +++ b/SwiftSignalKit/Signal_Timing.swift @@ -28,6 +28,58 @@ public func delay(_ timeout: Double, queue: Queue) -> (_ signal: Signal(_ timeout: Double, granularity: Double = 4.0, queue: Queue) -> (_ signal: Signal) -> Signal { + return { signal in + return Signal { subscriber in + let disposable = MetaDisposable() + queue.async { + let beginTimestamp = CFAbsoluteTimeGetCurrent() + + let startFinalTimer: () -> Void = { + let finalTimeout = beginTimestamp + timeout - CFAbsoluteTimeGetCurrent() + let timer = Timer(timeout: max(0.0, finalTimeout), repeat: false, completion: { + disposable.set(signal.start(next: { next in + subscriber.putNext(next) + }, error: { error in + subscriber.putError(error) + }, completed: { + subscriber.putCompletion() + })) + }, queue: queue) + disposable.set(ActionDisposable { + queue.async { + timer.invalidate() + } + }) + timer.start() + } + + var invalidateImpl: (() -> Void)? + let timer = Timer(timeout: granularity, repeat: true, completion: { + let currentTimestamp = CFAbsoluteTimeGetCurrent() + if beginTimestamp + timeout >= currentTimestamp - granularity * 1.1 { + invalidateImpl?() + startFinalTimer() + } + }, queue: queue) + + invalidateImpl = { + queue.async { + timer.invalidate() + } + } + + disposable.set(ActionDisposable { + invalidateImpl?() + }) + + timer.start() + } + return disposable + } + } +} + public func timeout(_ timeout: Double, queue: Queue, alternate: Signal) -> (Signal) -> Signal { return { signal in return Signal { subscriber in