@@ -87,7 +87,7 @@ public enum TaskExecutionState {
8787 case finished
8888}
8989
90- fileprivate actor QueuedTask < TaskDescription: TaskDescriptionProtocol > {
90+ public actor QueuedTask < TaskDescription: TaskDescriptionProtocol > {
9191 /// Result of `executionTask` / the tasks in `executionTaskCreatedContinuation`.
9292 /// See doc comment on `executionTask`.
9393 enum ExecutionTaskFinishStatus {
@@ -147,14 +147,38 @@ fileprivate actor QueuedTask<TaskDescription: TaskDescriptionProtocol> {
147147 /// Gets reset every time `executionTask` finishes.
148148 nonisolated ( unsafe) private var cancelledToBeRescheduled : AtomicBool = . init( initialValue: false )
149149
150+ private nonisolated ( unsafe) var _isExecuting : AtomicBool = . init( initialValue: false )
151+
152+ /// Whether the task is currently executing or still queued to be executed later.
153+ public nonisolated var isExecuting : Bool {
154+ return _isExecuting. value
155+ }
156+
157+ /// Wait for the task to finish.
158+ ///
159+ /// If the tasks that waits for this queued task to finished is cancelled, the QueuedTask will still continue
160+ /// executing.
161+ public func waitToFinish( ) async {
162+ return await resultTask. value
163+ }
164+
165+ /// Wait for the task to finish.
166+ ///
167+ /// If the tasks that waits for this queued task to finished is cancelled, the QueuedTask will also be cancelled.
168+ /// This assumes that the caller of this method has unique control over the task and is the only one interested in its
169+ /// value.
170+ public func waitToFinishPropagatingCancellation( ) async {
171+ return await resultTask. valuePropagatingCancellation
172+ }
173+
150174 /// A callback that will be called when the task starts executing, is cancelled to be rescheduled, or when it finishes
151175 /// execution.
152- private let executionStateChangedCallback : ( @Sendable ( TaskExecutionState) async -> Void ) ?
176+ private let executionStateChangedCallback : ( @Sendable ( QueuedTask , TaskExecutionState) async -> Void ) ?
153177
154178 init (
155179 priority: TaskPriority ? = nil ,
156180 description: TaskDescription ,
157- executionStateChangedCallback: ( @Sendable ( TaskExecutionState) async -> Void ) ?
181+ executionStateChangedCallback: ( @Sendable ( QueuedTask , TaskExecutionState) async -> Void ) ?
158182 ) async {
159183 self . _priority = . init( initialValue: priority? . rawValue ?? Task . currentPriority. rawValue)
160184 self . description = description
@@ -214,19 +238,21 @@ fileprivate actor QueuedTask<TaskDescription: TaskDescriptionProtocol> {
214238 }
215239 executionTask = task
216240 executionTaskCreatedContinuation. yield ( task)
217- await executionStateChangedCallback ? ( . executing)
241+ _isExecuting. value = true
242+ await executionStateChangedCallback ? ( self , . executing)
218243 return await task. value
219244 }
220245
221246 /// Implementation detail of `execute` that is called after `self.description.execute()` finishes.
222247 private func finalizeExecution( ) async -> ExecutionTaskFinishStatus {
223248 self . executionTask = nil
249+ _isExecuting. value = false
224250 if Task . isCancelled && self . cancelledToBeRescheduled. value {
225- await executionStateChangedCallback ? ( . cancelledToBeRescheduled)
251+ await executionStateChangedCallback ? ( self , . cancelledToBeRescheduled)
226252 self . cancelledToBeRescheduled. value = false
227253 return ExecutionTaskFinishStatus . cancelledToBeRescheduled
228254 } else {
229- await executionStateChangedCallback ? ( . finished)
255+ await executionStateChangedCallback ? ( self , . finished)
230256 return ExecutionTaskFinishStatus . terminated
231257 }
232258 }
@@ -327,8 +353,10 @@ public actor TaskScheduler<TaskDescription: TaskDescriptionProtocol> {
327353 public func schedule(
328354 priority: TaskPriority ? = nil ,
329355 _ taskDescription: TaskDescription ,
330- @_inheritActorContext executionStateChangedCallback: ( @Sendable ( TaskExecutionState) async -> Void ) ? = nil
331- ) async -> Task < Void , Never > {
356+ @_inheritActorContext executionStateChangedCallback: (
357+ @Sendable ( QueuedTask < TaskDescription > , TaskExecutionState ) async -> Void
358+ ) ? = nil
359+ ) async -> QueuedTask < TaskDescription > {
332360 let queuedTask = await QueuedTask (
333361 priority: priority,
334362 description: taskDescription,
@@ -341,7 +369,7 @@ public actor TaskScheduler<TaskDescription: TaskDescriptionProtocol> {
341369 // queued task.
342370 await self . poke ( )
343371 }
344- return queuedTask. resultTask
372+ return queuedTask
345373 }
346374
347375 /// Trigger all queued tasks to update their priority.
0 commit comments