summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-04-16 15:09:20 +0200
committerAndrej Mihajlov <and@mullvad.net>2022-04-29 10:30:25 +0200
commitf658aa645b816f31a98590638899a86467f2a8b7 (patch)
tree513e872b33d63a082afb0edde10ebdccefb437df
parentd3b82886935ab2ccdda355057b096248b7a6f301 (diff)
downloadmullvadvpn-f658aa645b816f31a98590638899a86467f2a8b7.tar.xz
mullvadvpn-f658aa645b816f31a98590638899a86467f2a8b7.zip
ResultOperation: refactor how finish() is handled to avoid preconditionFailure
-rw-r--r--ios/MullvadVPN/Operations/ResultOperation.swift27
1 files changed, 17 insertions, 10 deletions
diff --git a/ios/MullvadVPN/Operations/ResultOperation.swift b/ios/MullvadVPN/Operations/ResultOperation.swift
index 3d9233ce2e..a0cab6dcc9 100644
--- a/ios/MullvadVPN/Operations/ResultOperation.swift
+++ b/ios/MullvadVPN/Operations/ResultOperation.swift
@@ -17,6 +17,7 @@ class ResultOperation<Success, Failure: Error>: AsyncOperation {
private var completionValue: Completion?
private let completionQueue: DispatchQueue?
private var completionHandler: CompletionHandler?
+ private var pendingFinish = false
var completion: Completion? {
stateLock.lock()
@@ -33,32 +34,38 @@ class ResultOperation<Success, Failure: Error>: AsyncOperation {
@available(*, unavailable)
override func finish() {
- // Propagate cancellation if finish() is called directly from start().
- if isCancelled {
- finish(completion: .cancelled)
- } else {
- preconditionFailure("Use finish(completion:) to finish operation.")
- }
+ _finish()
}
func finish(completion: Completion) {
stateLock.lock()
+ if completionValue == nil {
+ completionValue = completion
+ }
+ stateLock.unlock()
+ _finish()
+ }
+
+ private func _finish() {
+ stateLock.lock()
// Bail if operation is already finishing.
- guard completionValue == nil else {
+ guard !pendingFinish else {
stateLock.unlock()
return
}
- // Store completion value.
- completionValue = completion
+ // Mark that operation is pending finish.
+ pendingFinish = true
// Copy completion handler.
- let completionHandler: CompletionHandler? = self.completionHandler
+ let completionHandler = self.completionHandler
// Unset completion handler.
self.completionHandler = nil
+ // Copy completion value.
+ let completion = completionValue ?? .cancelled
stateLock.unlock()
let block = {