summaryrefslogtreecommitdiffhomepage
path: root/ios
diff options
context:
space:
mode:
Diffstat (limited to 'ios')
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj6
-rw-r--r--ios/MullvadVPN/Operations/ResultOperation.swift77
2 files changed, 82 insertions, 1 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 266f67eafe..65cf355107 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -273,6 +273,7 @@
58F559102697002100F630D0 /* HeaderBar.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F559092697002100F630D0 /* HeaderBar.strings */; };
58F61F4F2692F21C00DCFC2B /* WireguardKeys.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F61F4D2692F21C00DCFC2B /* WireguardKeys.strings */; };
58F7CA882692E34000FC59FD /* WireguardKeysContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7CA872692E34000FC59FD /* WireguardKeysContentView.swift */; };
+ 58F7D26527EB50A300E4D821 /* ResultOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7D26427EB50A300E4D821 /* ResultOperation.swift */; };
58F840B22464491D0044E708 /* ChainedError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F840B12464491D0044E708 /* ChainedError.swift */; };
58F840B32464491D0044E708 /* ChainedError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F840B12464491D0044E708 /* ChainedError.swift */; };
58F8AC0E25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F8AC0D25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift */; };
@@ -548,6 +549,7 @@
58F5590A2697002100F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/HeaderBar.strings; sourceTree = "<group>"; };
58F61F4E2692F21C00DCFC2B /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/WireguardKeys.strings; sourceTree = "<group>"; };
58F7CA872692E34000FC59FD /* WireguardKeysContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireguardKeysContentView.swift; sourceTree = "<group>"; };
+ 58F7D26427EB50A300E4D821 /* ResultOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultOperation.swift; sourceTree = "<group>"; };
58F840B12464491D0044E708 /* ChainedError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChainedError.swift; sourceTree = "<group>"; };
58F8AC0D25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProblemReportReviewViewController.swift; sourceTree = "<group>"; };
58FAEDEB245059F000CB0F5B /* KeychainAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainAttributes.swift; sourceTree = "<group>"; };
@@ -632,9 +634,10 @@
580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */,
58E973DD24850EB600096F90 /* AsyncOperation.swift */,
580EE20524B3222200F9D8A1 /* ExclusivityController.swift */,
+ 5840BE34279EDB16002836BA /* OperationCompletion.swift */,
5820675D26E6839900655B05 /* PresentAlertOperation.swift */,
5846226426E0D9630035F7C2 /* ProductsRequestOperation.swift */,
- 5840BE34279EDB16002836BA /* OperationCompletion.swift */,
+ 58F7D26427EB50A300E4D821 /* ResultOperation.swift */,
);
path = Operations;
sourceTree = "<group>";
@@ -1290,6 +1293,7 @@
585DA87D26B0254000B8C587 /* RelayCacheIO.swift in Sources */,
582AD44027BE616E002A6BFC /* CodingErrors+ChainedError.swift in Sources */,
58F2E148276A307400A79513 /* MapConnectionStatusOperation.swift in Sources */,
+ 58F7D26527EB50A300E4D821 /* ResultOperation.swift in Sources */,
58BA693123EADA6A009DC256 /* SimulatorTunnelProvider.swift in Sources */,
58F1311327E09B00007AC5BC /* Cancellable.swift in Sources */,
587C575326D2615F005EF767 /* PacketTunnelOptions.swift in Sources */,
diff --git a/ios/MullvadVPN/Operations/ResultOperation.swift b/ios/MullvadVPN/Operations/ResultOperation.swift
new file mode 100644
index 0000000000..ba2cd59c4e
--- /dev/null
+++ b/ios/MullvadVPN/Operations/ResultOperation.swift
@@ -0,0 +1,77 @@
+//
+// ResultOperation.swift
+// MullvadVPN
+//
+// Created by pronebird on 23/03/2022.
+// Copyright © 2022 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+/// Base class for operations producing result.
+class ResultOperation<Success, Failure: Error>: AsyncOperation {
+ typealias Completion = OperationCompletion<Success, Failure>
+ typealias CompletionHandler = (Completion) -> Void
+
+ private let stateLock = NSLock()
+ private var completionValue: Completion?
+ private let completionQueue: DispatchQueue?
+ private var completionHandler: CompletionHandler?
+
+ var completion: Completion? {
+ stateLock.lock()
+ defer { stateLock.unlock() }
+ return completionValue
+ }
+
+ init(completionQueue: DispatchQueue?, completionHandler: CompletionHandler?) {
+ self.completionQueue = completionQueue
+ self.completionHandler = completionHandler
+
+ super.init()
+ }
+
+ 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.")
+ }
+ }
+
+ func finish(completion: Completion) {
+ stateLock.lock()
+
+ // Bail if operation is already finishing.
+ guard completionValue == nil else {
+ stateLock.unlock()
+ return
+ }
+
+ // Store completion value.
+ completionValue = completion
+
+ // Copy completion handler.
+ let completionHandler: CompletionHandler? = self.completionHandler
+
+ // Unset completion handler.
+ self.completionHandler = nil
+
+ stateLock.unlock()
+
+ let block = {
+ // Call completion handler.
+ completionHandler?(completion)
+
+ // Finish operation.
+ super.finish()
+ }
+
+ if let completionQueue = completionQueue {
+ completionQueue.async(execute: block)
+ } else {
+ block()
+ }
+ }
+}