Last active
December 23, 2023 19:09
-
-
Save NSSimpleApps/b95ce2046a5df36e6015e613f22f1355 to your computer and use it in GitHub Desktop.
AppercodeAsyncOperation
This file contains hidden or 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
/// Асинхронная операция. Завершать методом finish(with:). | |
final class AppercodeAsyncOperation<T>: Operation { | |
enum State: Int { | |
case ready | |
case executing | |
case finished | |
case cancelled | |
} | |
private let lock = NSLock() | |
private var state = State.ready | |
private var result: Result<T, Error>? | |
private let block: (AppercodeAsyncOperation) -> Void | |
init(block: @escaping (AppercodeAsyncOperation) -> Void, completion: @escaping (Result<T, Error>?) -> Void) { | |
self.block = block | |
super.init() | |
self.completionBlock = { [unowned self] in | |
self.lock.lock() | |
let result = self.result | |
self.lock.unlock() | |
completion(result) | |
} | |
} | |
override var isAsynchronous: Bool { | |
return true | |
} | |
override var isCancelled: Bool { | |
self.lock.lock() | |
let isCancelled = self.state == .cancelled | |
self.lock.unlock() | |
return isCancelled | |
} | |
override func cancel() { | |
self.lock.lock() | |
let state = self.state | |
self.lock.unlock() | |
if state == .executing || state == .ready { | |
self.willChangeValue(forKey: "isReady") | |
self.willChangeValue(forKey: "isCancelled") | |
self.willChangeValue(forKey: "isExecuting") | |
self.willChangeValue(forKey: "isFinished") | |
self.lock.lock() | |
self.result = nil | |
self.state = .cancelled | |
self.lock.unlock() | |
self.didChangeValue(forKey: "isReady") | |
self.didChangeValue(forKey: "isCancelled") | |
self.didChangeValue(forKey: "isExecuting") | |
self.didChangeValue(forKey: "isFinished") | |
} | |
} | |
override var isExecuting: Bool { | |
self.lock.lock() | |
let isExecuting = self.state == .executing | |
self.lock.unlock() | |
return isExecuting | |
} | |
override var isFinished: Bool { | |
self.lock.lock() | |
let state = self.state | |
let isFinished = state == .finished || state == .cancelled | |
self.lock.unlock() | |
return isFinished | |
} | |
override var isReady: Bool { | |
self.lock.lock() | |
let isReady = self.state == .ready | |
self.lock.unlock() | |
return isReady | |
} | |
override func start() { | |
self.lock.lock() | |
let state = self.state | |
self.lock.unlock() | |
if state == .ready { | |
self.willChangeValue(forKey: "isReady") | |
self.willChangeValue(forKey: "isExecuting") | |
self.lock.lock() | |
self.state = .executing | |
self.lock.unlock() | |
self.didChangeValue(forKey: "isReady") | |
self.didChangeValue(forKey: "isExecuting") | |
self.main() | |
} | |
} | |
override func main() { | |
self.block(self) | |
} | |
func finish(with result: Result<T, Error>) { | |
self.lock.lock() | |
let state = self.state | |
self.lock.unlock() | |
if state == .executing || state == .ready { | |
self.willChangeValue(forKey: "isReady") | |
self.willChangeValue(forKey: "isExecuting") | |
self.willChangeValue(forKey: "isFinished") | |
self.lock.lock() | |
self.result = result | |
self.state = .finished | |
self.lock.unlock() | |
self.didChangeValue(forKey: "isReady") | |
self.didChangeValue(forKey: "isExecuting") | |
self.didChangeValue(forKey: "isFinished") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment