@@ -14,9 +14,10 @@ import Dispatch
1414public final class TaskOperation < R: Sendable > : Operation , AsyncObject ,
1515 @unchecked Sendable
1616{
17- /// The dispatch queue used to synchronize data access and modifications.
17+ /// The platform dependent lock used to
18+ /// synchronize data access and modifications.
1819 @usableFromInline
19- let propQueue : DispatchQueue
20+ let locker : Locker
2021 /// The asynchronous action to perform as part of the operation..
2122 private let underlyingAction : @Sendable ( ) async throws -> R
2223 /// The top-level task that executes asynchronous action provided
@@ -35,33 +36,35 @@ public final class TaskOperation<R: Sendable>: Operation, AsyncObject,
3536 public override var isCancelled : Bool { execTask? . isCancelled ?? false }
3637
3738 /// Private store for boolean value indicating whether the operation is currently executing.
38- private var _isExecuting : Bool = false
39+ @usableFromInline
40+ var _isExecuting : Bool = false
3941 /// A Boolean value indicating whether the operation is currently executing.
4042 ///
4143 /// The value of this property is true if the operation is currently executing
4244 /// provided asynchronous operation or false if it is not.
4345 public override internal( set) var isExecuting : Bool {
44- get { propQueue . sync { _isExecuting } }
46+ get { locker . perform { _isExecuting } }
4547 @usableFromInline
4648 set {
4749 willChangeValue ( forKey: " isExecuting " )
48- propQueue . sync ( flags : [ . barrier ] ) { _isExecuting = newValue }
50+ locker . perform { _isExecuting = newValue }
4951 didChangeValue ( forKey: " isExecuting " )
5052 }
5153 }
5254
5355 /// Private store for boolean value indicating whether the operation has finished executing its task.
54- private var _isFinished : Bool = false
56+ @usableFromInline
57+ var _isFinished : Bool = false
5558 /// A Boolean value indicating whether the operation has finished executing its task.
5659 ///
5760 /// The value of this property is true if the operation is finished executing or cancelled
5861 /// provided asynchronous operation or false if it is not.
5962 public override internal( set) var isFinished : Bool {
60- get { propQueue . sync { _isFinished } }
63+ get { locker . perform { _isFinished } }
6164 @usableFromInline
6265 set {
6366 willChangeValue ( forKey: " isFinished " )
64- propQueue . sync ( flags : [ . barrier ] ) {
67+ locker . perform {
6568 _isFinished = newValue
6669 guard newValue, !continuations. isEmpty else { return }
6770 continuations. forEach { $0. value. resume ( ) }
@@ -79,44 +82,30 @@ public final class TaskOperation<R: Sendable>: Operation, AsyncObject,
7982 get async { ( await execTask? . result) ?? . failure( CancellationError ( ) ) }
8083 }
8184
82- /// Creates a new operation that executes the provided throwing asynchronous task.
85+ /// Creates a new operation that executes the provided asynchronous task.
8386 ///
84- /// The provided dispatch queue is used to synchronize operation property access and modifications
85- /// and prevent data races.
87+ /// The operation execution only starts after ``start()`` is invoked.
88+ /// Operation completes when underlying asynchronous task finishes.
89+ /// The provided lock is used to synchronize operation property access and modifications
90+ /// to prevent data races.
8691 ///
8792 /// - Parameters:
88- /// - queue: The dispatch queue to be used to synchronize data access and modifications.
89- /// - operation: The throwing asynchronous operation to execute.
93+ /// - locker: The locker to use to synchronize property read and mutations.
94+ /// New lock object is created in case none provided.
95+ /// - operation: The asynchronous operation to execute.
9096 ///
9197 /// - Returns: The newly created asynchronous operation.
9298 public init (
93- queue : DispatchQueue ,
99+ synchronizedWith locker : Locker = . init ( ) ,
94100 operation: @escaping @Sendable ( ) async throws -> R
95101 ) {
96- self . propQueue = queue
102+ self . locker = locker
97103 self . underlyingAction = operation
98104 super. init ( )
99105 }
100106
101- deinit { self . continuations. forEach { $0. value. cancel ( ) } }
102-
103- /// Creates a new operation that executes the provided non-throwing asynchronous task.
104- ///
105- /// The provided dispatch queue is used to synchronize operation property access and modifications
106- /// and prevent data races.
107- ///
108- /// - Parameters:
109- /// - queue: The dispatch queue to be used to synchronize data access and modifications.
110- /// - operation: The non-throwing asynchronous operation to execute.
111- ///
112- /// - Returns: The newly created asynchronous operation.
113- public init (
114- queue: DispatchQueue ,
115- operation: @escaping @Sendable ( ) async -> R
116- ) {
117- self . propQueue = queue
118- self . underlyingAction = operation
119- super. init ( )
107+ deinit {
108+ locker. perform { self . continuations. forEach { $0. value. cancel ( ) } }
120109 }
121110
122111 /// Begins the execution of the operation.
@@ -138,9 +127,11 @@ public final class TaskOperation<R: Sendable>: Operation, AsyncObject,
138127 public override func main( ) {
139128 guard isExecuting, execTask == nil else { return }
140129 execTask = Task { [ weak self] in
141- guard let self = self else { throw CancellationError ( ) }
142- defer { self . _finish ( ) }
143- let result = try await underlyingAction ( )
130+ guard
131+ let action = self ? . underlyingAction
132+ else { throw CancellationError ( ) }
133+ defer { self ? . _finish ( ) }
134+ let result = try await action ( )
144135 return result
145136 }
146137 }
@@ -185,8 +176,8 @@ public final class TaskOperation<R: Sendable>: Operation, AsyncObject,
185176 _ continuation: Continuation ,
186177 withKey key: UUID
187178 ) {
188- propQueue . sync ( flags : [ . barrier ] ) {
189- if isFinished { continuation. resume ( ) ; return }
179+ locker . perform {
180+ if _isFinished { continuation. resume ( ) ; return }
190181 continuations [ key] = continuation
191182 }
192183 }
@@ -197,7 +188,7 @@ public final class TaskOperation<R: Sendable>: Operation, AsyncObject,
197188 /// - Parameter key: The key in the map.
198189 @inlinable
199190 func _removeContinuation( withKey key: UUID ) {
200- propQueue . sync ( flags : [ . barrier ] ) {
191+ locker . perform {
201192 let continuation = continuations. removeValue ( forKey: key)
202193 continuation? . cancel ( )
203194 }
0 commit comments