99import Foundation
1010import UIKit
1111
12- enum Result < T> {
13- case success( T )
14- case failure( Error )
12+ enum ConcurrentOperationError : Error , Equatable {
13+ case cancelled
1514}
1615
17- class ConcurrentOperation < T> : Operation {
16+ class ConcurrentOperation < Value> : Operation , @unchecked Sendable {
17+ typealias OperationCompletionHandler = ( _ result: Result < Value , Error > ) -> Void
1818
19- typealias OperationCompletionHandler = ( _ result : Result < T > ) -> Void
19+ private ( set ) var completionHandler : ( OperationCompletionHandler ) ?
2020
21- var completionHandler : ( OperationCompletionHandler ) ?
21+ private let lock = NSRecursiveLock ( )
22+
23+ // MARK: - Init
24+
25+ init ( completionHandler: @escaping ( _ result: Result < Value , Error > ) -> Void ) {
26+ self . completionHandler = completionHandler
27+
28+ super. init ( )
29+ }
2230
2331 // MARK: - State
2432
@@ -28,14 +36,29 @@ class ConcurrentOperation<T>: Operation {
2836 case finished = " isFinished "
2937 }
3038
31- private var state = State . ready {
39+ private var _state = State . ready {
3240 willSet {
3341 willChangeValue ( forKey: newValue. rawValue)
34- willChangeValue ( forKey: state . rawValue)
42+ willChangeValue ( forKey: _state . rawValue)
3543 }
3644 didSet {
3745 didChangeValue ( forKey: oldValue. rawValue)
38- didChangeValue ( forKey: state. rawValue)
46+ didChangeValue ( forKey: _state. rawValue)
47+ }
48+ }
49+
50+ private var state : State {
51+ get {
52+ lock. lock ( )
53+ defer { lock. unlock ( ) }
54+
55+ return _state
56+ }
57+ set {
58+ lock. lock ( )
59+ defer { lock. unlock ( ) }
60+
61+ _state = newValue
3962 }
4063 }
4164
@@ -51,42 +74,39 @@ class ConcurrentOperation<T>: Operation {
5174 return state == . finished
5275 }
5376
54- // MARK: - Start
77+ override var isAsynchronous : Bool {
78+ return true
79+ }
80+
81+ // MARK: - Lifecycle
5582
5683 override func start( ) {
5784 guard !isCancelled else {
58- finish ( )
85+ finish ( result : . failure ( ConcurrentOperationError . cancelled ) )
5986 return
6087 }
6188
62- if !isExecuting {
63- state = . executing
64- }
89+ state = . executing
6590
6691 main ( )
6792 }
6893
69- // MARK: - Finish
70-
71- func finish( ) {
72- if isExecuting {
73- state = . finished
74- }
75- }
76-
77- func complete( result: Result < T > ) {
78- finish ( )
79-
80- if !isCancelled {
81- completionHandler ? ( result)
94+ func finish( result: Result < Value , Error > ) {
95+ lock. lock ( )
96+ defer { lock. unlock ( ) }
97+
98+ guard !isFinished else {
99+ return
82100 }
101+
102+ state = . finished
103+
104+ completionHandler ? ( result)
83105 }
84106
85- // MARK: - Cancel
86-
87107 override func cancel( ) {
88108 super. cancel ( )
89109
90- finish ( )
110+ finish ( result : . failure ( ConcurrentOperationError . cancelled ) )
91111 }
92112}
0 commit comments