1717import Foundation
1818
1919/// A type that represents a task whose progress is being monitored.
20- public struct ProgressTask : Sendable , Equatable {
20+ public struct ProgressTask : Sendable , Equatable , Hashable {
2121 private var id = UUID ( )
22- private var coordinator : ProgressTaskCoordinator
22+ internal var coordinator : ProgressTaskCoordinator
2323
2424 init ( manager: ProgressTaskCoordinator ) {
2525 self . coordinator = manager
@@ -29,6 +29,10 @@ public struct ProgressTask: Sendable, Equatable {
2929 lhs. id == rhs. id
3030 }
3131
32+ public func hash( into hasher: inout Hasher ) {
33+ hasher. combine ( id)
34+ }
35+
3236 /// Returns `true` if this task is the currently active task, `false` otherwise.
3337 public func isCurrent( ) async -> Bool {
3438 guard let currentTask = await coordinator. currentTask else {
@@ -41,6 +45,7 @@ public struct ProgressTask: Sendable, Equatable {
4145/// A type that coordinates progress tasks to ignore updates from completed tasks.
4246public actor ProgressTaskCoordinator {
4347 var currentTask : ProgressTask ?
48+ var activeTasks : Set < ProgressTask > = [ ]
4449
4550 /// Creates an instance of `ProgressTaskCoordinator`.
4651 public init ( ) { }
@@ -52,9 +57,36 @@ public actor ProgressTaskCoordinator {
5257 return newTask
5358 }
5459
60+ /// Starts multiple concurrent tasks and returns them.
61+ /// - Parameter count: The number of concurrent tasks to start.
62+ /// - Returns: An array of ProgressTask instances.
63+ public func startConcurrentTasks( count: Int ) -> [ ProgressTask ] {
64+ var tasks : [ ProgressTask ] = [ ]
65+ for _ in 0 ..< count {
66+ let task = ProgressTask ( manager: self )
67+ tasks. append ( task)
68+ activeTasks. insert ( task)
69+ }
70+ return tasks
71+ }
72+
73+ /// Marks a specific task as completed and removes it from active tasks.
74+ /// - Parameter task: The task to mark as completed.
75+ public func completeTask( _ task: ProgressTask ) {
76+ activeTasks. remove ( task)
77+ }
78+
79+ /// Checks if a task is currently active.
80+ /// - Parameter task: The task to check.
81+ /// - Returns: `true` if the task is active, `false` otherwise.
82+ public func isTaskActive( _ task: ProgressTask ) -> Bool {
83+ activeTasks. contains ( task)
84+ }
85+
5586 /// Performs cleanup when the monitored tasks complete.
5687 public func finish( ) {
5788 currentTask = nil
89+ activeTasks. removeAll ( )
5890 }
5991
6092 /// Returns a handler that updates the progress of a given task.
@@ -69,4 +101,17 @@ public actor ProgressTaskCoordinator {
69101 }
70102 }
71103 }
104+
105+ /// Returns a handler that updates the progress for concurrent tasks.
106+ /// - Parameters:
107+ /// - task: The task whose progress is being updated.
108+ /// - progressUpdate: The handler to invoke when progress updates are received.
109+ public static func concurrentHandler( for task: ProgressTask , from progressUpdate: @escaping ProgressUpdateHandler ) -> ProgressUpdateHandler {
110+ { events in
111+ // Only process updates if the task is still active
112+ if await task. coordinator. isTaskActive ( task) {
113+ await progressUpdate ( events)
114+ }
115+ }
116+ }
72117}
0 commit comments