@@ -2,8 +2,8 @@ import Foundation
22
33/// An object that controls cooperative cancellation of multiple registered tasks and linked object registered tasks.
44///
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.
77/// By calling the ``cancel(file:function:line:)`` method all the registered tasks will be cancelled
88/// and the cancellation event will be propagated to linked cancellation sources,
99/// which in turn cancels their registered tasks and further propagates cancellation.
@@ -42,10 +42,12 @@ public struct CancellationSource: AsyncObject, Cancellable, Loggable {
4242 /// The lifetime task that is cancelled when
4343 /// `CancellationSource` is cancelled.
4444 @usableFromInline
45- var lifetime : Task < Void , Error > !
45+ let lifetime : Task < Void , Error > !
4646 /// The stream continuation used to register work items
4747 /// 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
4951
5052 /// A Boolean value that indicates whether cancellation is already
5153 /// invoked on the source.
@@ -59,10 +61,21 @@ public struct CancellationSource: AsyncObject, Cancellable, Loggable {
5961
6062 /// Creates a new cancellation source object.
6163 ///
64+ /// - Parameters:
65+ /// - priority: The minimum priority of task that this source is going to handle.
66+ /// By default, priority is `.background`.
67+ ///
6268 /// - 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) {
6679 try await withThrowingTaskGroup ( of: Void . self) { group in
6780 for await item in stream {
6881 group. addTask {
@@ -94,6 +107,10 @@ public struct CancellationSource: AsyncObject, Cancellable, Loggable {
94107 /// pass it explicitly as it defaults to `#function`).
95108 /// - line: The line work registration originates from (there's usually no need to pass it
96109 /// 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.
97114 @Sendable
98115 public func register< C: Cancellable > (
99116 task: C ,
@@ -158,6 +175,9 @@ public struct CancellationSource: AsyncObject, Cancellable, Loggable {
158175 /// pass it explicitly as it defaults to `#function`).
159176 /// - line: The line wait request originates from (there's usually no need to pass it
160177 /// 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.
161181 @Sendable
162182 public func wait(
163183 file: String = #fileID,
0 commit comments