Skip to content

Instantly share code, notes, and snippets.

@pgherveou
Last active August 4, 2017 15:25
Show Gist options
  • Save pgherveou/9f57434575ca6f6662306666defdad84 to your computer and use it in GitHub Desktop.
Save pgherveou/9f57434575ca6f6662306666defdad84 to your computer and use it in GitHub Desktop.
Async operationQueue
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()
}
}
@pgherveou
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment