diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-06-08 14:48:02 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-06-08 15:43:49 +0200 |
| commit | 6499f8a92996aa1d035180637d1592fdf13ad513 (patch) | |
| tree | 67039c3e5460c2975e01b1af043433dd84e8eec8 | |
| parent | 3227e1999eb540fd8645cd0f4c8e370851714662 (diff) | |
| download | mullvadvpn-6499f8a92996aa1d035180637d1592fdf13ad513.tar.xz mullvadvpn-6499f8a92996aa1d035180637d1592fdf13ad513.zip | |
Observe individual dependencies
| -rw-r--r-- | ios/MullvadVPN/Operations/AsyncOperation.swift | 80 |
1 files changed, 38 insertions, 42 deletions
diff --git a/ios/MullvadVPN/Operations/AsyncOperation.swift b/ios/MullvadVPN/Operations/AsyncOperation.swift index d3e13d2f81..6815311fab 100644 --- a/ios/MullvadVPN/Operations/AsyncOperation.swift +++ b/ios/MullvadVPN/Operations/AsyncOperation.swift @@ -40,9 +40,7 @@ import Foundation /// A base implementation of an asynchronous operation class AsyncOperation: Operation { - private static var observerContext = 0 - - /// A state lock used for manipulating the operation state flags in a thread safe fashion. + /// A state lock used for manipulating the operation state in a thread safe fashion. private let stateLock = NSRecursiveLock() /// Operation state. @@ -181,21 +179,6 @@ class AsyncOperation: Operation { init(dispatchQueue: DispatchQueue? = nil) { self.dispatchQueue = dispatchQueue ?? DispatchQueue(label: "AsyncOperation.dispatchQueue") super.init() - - addObserver( - self, - forKeyPath: #keyPath(isReady), - options: [], - context: &Self.observerContext - ) - } - - deinit { - removeObserver( - self, - forKeyPath: #keyPath(isReady), - context: &Self.observerContext - ) } // MARK: - KVO @@ -212,25 +195,6 @@ class AsyncOperation: Operation { return ["state"] } - override func observeValue( - forKeyPath keyPath: String?, - of object: Any?, - change: [NSKeyValueChangeKey : Any]?, - context: UnsafeMutableRawPointer? - ) - { - if context == &Self.observerContext { - checkReadiness() - } else { - super.observeValue( - forKeyPath: keyPath, - of: object, - change: change, - context: context - ) - } - } - // MARK: - Lifecycle final override func start() { @@ -323,16 +287,48 @@ class AsyncOperation: Operation { didChangeValue(for: \.state) } - private func checkReadiness() { + private func dependenciesDidFinish() { stateLock.lock() - if state == .pending && !_isCancelled && super.isReady { - evaluateConditions() - } - stateLock.unlock() + defer { stateLock.unlock() } + + guard state == .pending && !_isCancelled else { return } + + precondition(super.isReady, "Expect super.isReady to be true.") + + evaluateConditions() } func didEnqueue() { + stateLock.lock() + guard state == .initialized else { + stateLock.unlock() + return + } setState(.pending) + stateLock.unlock() + + let group = DispatchGroup() + var observers = [NSKeyValueObservation]() + + for dependency in dependencies { + group.enter() + + let observer = dependency.observe(\.isFinished, options: [.initial]) { dependency, _ in + if dependency.isFinished { + group.leave() + } + } + + observers.append(observer) + } + + group.notify(queue: dispatchQueue) { + for observer in observers { + observer.invalidate() + } + + self.dependenciesDidFinish() + } } // MARK: - Subclass overrides |
