Last active
August 4, 2017 15:25
-
-
Save pgherveou/9f57434575ca6f6662306666defdad84 to your computer and use it in GitHub Desktop.
Async operationQueue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
/// List of states that can be used to update an asynchronous operation state. | |
public enum AsyncOperationState { | |
case ready | |
case executing | |
case finished | |
fileprivate var keyPath: String { | |
switch self { | |
case .ready: return #keyPath(Operation.isReady) | |
case .executing: return #keyPath(Operation.isExecuting) | |
case .finished: return #keyPath(Operation.isFinished) | |
} | |
} | |
} | |
/// A base class for asynchronous operation. | |
open class AsyncOperation: Operation { | |
private let stateQueue = DispatchQueue(label: "AsyncOperationStateQueue", attributes: .concurrent) | |
private var rawState: AsyncOperationState = .ready | |
private var state: AsyncOperationState { | |
get { | |
return self.stateQueue.sync { self.rawState } | |
} | |
set { | |
let oldKey = self.state.keyPath | |
let newKey = newValue.keyPath | |
self.willChangeValue(forKey: oldKey) | |
self.willChangeValue(forKey: newKey) | |
self.stateQueue.async(flags: .barrier) { self.rawState = newValue } | |
self.didChangeValue(forKey: oldKey) | |
self.didChangeValue(forKey: newKey) | |
} | |
} | |
override final public var isAsynchronous: Bool { return true } | |
override final public var isReady: Bool { return self.state == .ready && super.isReady } | |
override final public var isExecuting: Bool { return self.state == .executing } | |
override final public var isFinished: Bool { return self.state == .finished } | |
/// Set the operation state. | |
/// | |
/// - parameter state: the new operation State | |
public final func setState(_ state: AsyncOperationState) { | |
self.state = state | |
} | |
} | |
/// An asynchronous operation that complete after the given time Interval. | |
public final class WaitOperation: AsyncOperation { | |
private var timer: DispatchSourceTimer? | |
private let timeInterval: DispatchTimeInterval | |
public init(timeInterval: DispatchTimeInterval) { | |
self.timeInterval = timeInterval | |
} | |
override public func start() { | |
super.start() | |
if self.isCancelled { | |
self.setState(.finished) | |
return | |
} | |
self.setState(.executing) | |
self.timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global()) | |
self.timer?.scheduleOneshot(deadline: .now() + self.timeInterval) | |
self.timer?.setEventHandler { [weak self] in self?.setState(.finished) } | |
self.timer?.resume() | |
} | |
override public func cancel() { | |
super.cancel() | |
self.timer?.cancel() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
inspired from https://gist.github.com/calebd/93fa347397cec5f88233