@@ -76,9 +76,9 @@ extension EffectProducer {
76
76
}
77
77
}
78
78
79
- _cancellationCancellables [ id, default: [ ] ] . insert (
79
+ _cancellationCancellables [ id, default: [ ] ] . insert (
80
80
cancellationDisposable
81
- )
81
+ )
82
82
83
83
return SignalProducer ( values. value)
84
84
. concat ( subject. output. producer)
@@ -164,6 +164,7 @@ extension EffectProducer {
164
164
}
165
165
}
166
166
167
+ #if swift(>=5.7)
167
168
/// Execute an operation with a cancellation identifier.
168
169
///
169
170
/// If the operation is in-flight when `Task.cancel(id:)` is called with the same identifier, the
@@ -206,13 +207,44 @@ extension EffectProducer {
206
207
/// - operation: An async operation.
207
208
/// - Throws: An error thrown by the operation.
208
209
/// - Returns: A value produced by operation.
210
+ @_unsafeInheritExecutor
209
211
public func withTaskCancellation< T: Sendable > (
210
212
id: AnyHashable ,
211
213
cancelInFlight: Bool = false ,
212
214
operation: @Sendable @escaping ( ) async throws -> T
213
215
) async rethrows -> T {
214
216
let id = _CancelToken ( id: id)
215
- let ( cancellable, task) = _cancellablesLock. sync { ( ) -> ( AnyDisposable , Task < T , Error > ) in
217
+ let ( cancellable, task) = _cancellablesLock. sync { ( ) -> ( AnyDisposable , Task < T , Error > ) in
218
+ if cancelInFlight {
219
+ _cancellationCancellables [ id] ? . forEach { $0. dispose ( ) }
220
+ }
221
+ let task = Task { try await operation ( ) }
222
+ let cancellable = AnyDisposable { task. cancel ( ) }
223
+ _cancellationCancellables [ id, default: [ ] ] . insert ( cancellable)
224
+ return ( cancellable, task)
225
+ }
226
+ defer {
227
+ _cancellablesLock. sync {
228
+ _cancellationCancellables [ id] ? . remove ( cancellable)
229
+ if _cancellationCancellables [ id] ? . isEmpty == . some( true ) {
230
+ _cancellationCancellables [ id] = nil
231
+ }
232
+ }
233
+ }
234
+ do {
235
+ return try await task. cancellableValue
236
+ } catch {
237
+ return try Result < T , Error > . failure ( error) . _rethrowGet ( )
238
+ }
239
+ }
240
+ #else
241
+ public func withTaskCancellation< T: Sendable > (
242
+ id: AnyHashable ,
243
+ cancelInFlight: Bool = false ,
244
+ operation: @Sendable @escaping ( ) async throws -> T
245
+ ) async rethrows -> T {
246
+ let id = _CancelToken ( id: id)
247
+ let ( cancellable, task) = _cancellablesLock. sync { ( ) -> ( AnyDisposable , Task < T , Error > ) in
216
248
if cancelInFlight {
217
249
_cancellationCancellables [ id] ? . forEach { $0. dispose ( ) }
218
250
}
@@ -235,7 +267,9 @@ public func withTaskCancellation<T: Sendable>(
235
267
return try Result < T , Error > . failure ( error) . _rethrowGet ( )
236
268
}
237
269
}
270
+ #endif
238
271
272
+ #if swift(>=5.7)
239
273
/// Execute an operation with a cancellation identifier.
240
274
///
241
275
/// A convenience for calling ``withTaskCancellation(id:cancelInFlight:operation:)-4dtr6`` with a
@@ -248,6 +282,7 @@ public func withTaskCancellation<T: Sendable>(
248
282
/// - operation: An async operation.
249
283
/// - Throws: An error thrown by the operation.
250
284
/// - Returns: A value produced by operation.
285
+ @_unsafeInheritExecutor
251
286
public func withTaskCancellation< T: Sendable > (
252
287
id: Any . Type ,
253
288
cancelInFlight: Bool = false ,
@@ -259,6 +294,19 @@ public func withTaskCancellation<T: Sendable>(
259
294
operation: operation
260
295
)
261
296
}
297
+ #else
298
+ public func withTaskCancellation< T: Sendable > (
299
+ id: Any . Type ,
300
+ cancelInFlight: Bool = false ,
301
+ operation: @Sendable @escaping ( ) async throws -> T
302
+ ) async rethrows -> T {
303
+ try await withTaskCancellation (
304
+ id: ObjectIdentifier ( id) ,
305
+ cancelInFlight: cancelInFlight,
306
+ operation: operation
307
+ )
308
+ }
309
+ #endif
262
310
263
311
extension Task where Success == Never , Failure == Never {
264
312
/// Cancel any currently in-flight operation with the given identifier.
0 commit comments