@@ -2,8 +2,8 @@ import Foundation
2
2
3
3
/// An object that controls cooperative cancellation of multiple registered tasks and linked object registered tasks.
4
4
///
5
- /// You can register tasks for cancellation using the ``register(task:file:function:line:)`` method
6
- /// and link with additional sources by creating object with ``init(linkedWith:) `` method.
5
+ /// You can register tasks for cancellation using the ``register(task:file:function:line:)`` method and link with
6
+ /// additional sources by creating object with ``init(priority: linkedWith:file:function:line:)-7b9gf `` method.
7
7
/// By calling the ``cancel(file:function:line:)`` method all the registered tasks will be cancelled
8
8
/// and the cancellation event will be propagated to linked cancellation sources,
9
9
/// which in turn cancels their registered tasks and further propagates cancellation.
@@ -42,10 +42,12 @@ public struct CancellationSource: AsyncObject, Cancellable, Loggable {
42
42
/// The lifetime task that is cancelled when
43
43
/// `CancellationSource` is cancelled.
44
44
@usableFromInline
45
- var lifetime : Task < Void , Error > !
45
+ let lifetime : Task < Void , Error > !
46
46
/// The stream continuation used to register work items
47
47
/// for cooperative cancellation.
48
- var pipe : AsyncStream < WorkItem > . Continuation !
48
+ let pipe : AsyncStream < WorkItem > . Continuation !
49
+ /// The priority of the detached cancellation task.
50
+ let priority : TaskPriority
49
51
50
52
/// A Boolean value that indicates whether cancellation is already
51
53
/// invoked on the source.
@@ -59,10 +61,21 @@ public struct CancellationSource: AsyncObject, Cancellable, Loggable {
59
61
60
62
/// Creates a new cancellation source object.
61
63
///
64
+ /// - Parameters:
65
+ /// - priority: The minimum priority of task that this source is going to handle.
66
+ /// By default, priority is `.background`.
67
+ ///
62
68
/// - Returns: The newly created cancellation source.
63
- public init ( ) {
64
- let stream = AsyncStream< WorkItem> { self . pipe = $0 }
65
- self . lifetime = Task . detached {
69
+ ///
70
+ /// - NOTE: `CancellationSource` uses `Task`'s `result` and `value` APIs
71
+ /// to wait for completion which has side effect of increasing `Task`'s priority.
72
+ /// Hence, provide the least priority for the submitted tasks to use in cancellation task.
73
+ public init ( priority: TaskPriority = . background) {
74
+ var continuation : AsyncStream < WorkItem > . Continuation !
75
+ let stream = AsyncStream< WorkItem> { continuation = $0 }
76
+ self . priority = priority
77
+ self . pipe = continuation
78
+ self . lifetime = Task . detached ( priority: priority) {
66
79
try await withThrowingTaskGroup ( of: Void . self) { group in
67
80
for await item in stream {
68
81
group. addTask {
@@ -94,6 +107,10 @@ public struct CancellationSource: AsyncObject, Cancellable, Loggable {
94
107
/// pass it explicitly as it defaults to `#function`).
95
108
/// - line: The line work registration originates from (there's usually no need to pass it
96
109
/// explicitly as it defaults to `#line`).
110
+ ///
111
+ /// - Important: Do not use this method to link `CancellationSource` as it might introduce
112
+ /// circular linking which will cause all the affected cancellation tasks to leak.
113
+ /// Use ``init(priority:linkedWith:file:function:line:)-7b9gf`` instead.
97
114
@Sendable
98
115
public func register< C: Cancellable > (
99
116
task: C ,
@@ -158,6 +175,9 @@ public struct CancellationSource: AsyncObject, Cancellable, Loggable {
158
175
/// pass it explicitly as it defaults to `#function`).
159
176
/// - line: The line wait request originates from (there's usually no need to pass it
160
177
/// explicitly as it defaults to `#line`).
178
+ ///
179
+ /// - Important: Using this method might introduce circular linking of`CancellationSource`
180
+ /// which will cause all the affected cancellation tasks to leak.
161
181
@Sendable
162
182
public func wait(
163
183
file: String = #fileID,
0 commit comments