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