@@ -301,6 +301,18 @@ extension ProgressManager {
301301 }
302302
303303 // MARK: Clean up dirty paths
304+ internal struct ByteCountUpdateInfo {
305+ let currentSummary : UInt64
306+ let dirtyChildren : [ ( index: Int , manager: ProgressManager ) ]
307+ let nonDirtySummaries : [ ( index: Int , summary: UInt64 , isAlive: Bool ) ]
308+ let type : CountType
309+ }
310+
311+ internal struct ByteCountUpdate {
312+ let index : Int
313+ let updatedSummary : UInt64
314+ }
315+
304316 internal struct ThroughputUpdateInfo {
305317 let currentSummary : [ UInt64 ]
306318 let dirtyChildren : [ ( index: Int , manager: ProgressManager ) ]
@@ -323,6 +335,111 @@ extension ProgressManager {
323335 let updatedSummary : Duration
324336 }
325337
338+ internal mutating func getByteCountUpdateInfo( type: CountType ) -> ByteCountUpdateInfo {
339+ let currentSummary : UInt64
340+ var dirtyChildren : [ ( index: Int , manager: ProgressManager ) ] = [ ]
341+ var nonDirtySummaries : [ ( index: Int , summary: UInt64 , isAlive: Bool ) ] = [ ]
342+
343+ switch type {
344+ case . total:
345+ var value : UInt64 = 0
346+ ProgressManager . Properties. TotalByteCount. reduce ( into: & value, value: totalByteCount)
347+ currentSummary = value
348+
349+ guard !children. isEmpty else {
350+ return ByteCountUpdateInfo (
351+ currentSummary: currentSummary,
352+ dirtyChildren: [ ] ,
353+ nonDirtySummaries: [ ] ,
354+ type: type
355+ )
356+ }
357+
358+ for (idx, childState) in children. enumerated ( ) {
359+ if childState. totalByteCount. isDirty {
360+ if let child = childState. child {
361+ dirtyChildren. append ( ( idx, child) )
362+ }
363+ } else {
364+ let isAlive = childState. child != nil
365+ nonDirtySummaries. append ( ( idx, childState. totalByteCount. value, isAlive) )
366+ }
367+ }
368+
369+ case . completed:
370+ var value : UInt64 = 0
371+ ProgressManager . Properties. CompletedByteCount. reduce ( into: & value, value: completedByteCount)
372+ currentSummary = value
373+
374+ guard !children. isEmpty else {
375+ return ByteCountUpdateInfo (
376+ currentSummary: currentSummary,
377+ dirtyChildren: [ ] ,
378+ nonDirtySummaries: [ ] ,
379+ type: type
380+ )
381+ }
382+
383+ for (idx, childState) in children. enumerated ( ) {
384+ if childState. completedByteCount. isDirty {
385+ if let child = childState. child {
386+ dirtyChildren. append ( ( idx, child) )
387+ }
388+ } else {
389+ let isAlive = childState. child != nil
390+ nonDirtySummaries. append ( ( idx, childState. completedByteCount. value, isAlive) )
391+ }
392+ }
393+ }
394+
395+ return ByteCountUpdateInfo (
396+ currentSummary: currentSummary,
397+ dirtyChildren: dirtyChildren,
398+ nonDirtySummaries: nonDirtySummaries,
399+ type: type
400+ )
401+ }
402+
403+ internal mutating func updateByteCount( _ updateInfo: ByteCountUpdateInfo , _ childUpdates: [ ByteCountUpdate ] ) -> UInt64 {
404+ var value = updateInfo. currentSummary
405+
406+ switch updateInfo. type {
407+ case . total:
408+ // Apply updates from children that were dirty
409+ for update in childUpdates {
410+ children [ update. index] . totalByteCount = PropertyStateUInt64 ( value: update. updatedSummary, isDirty: false )
411+ value = ProgressManager . Properties. TotalByteCount. merge ( value, update. updatedSummary)
412+ }
413+
414+ // Apply values from non-dirty children
415+ for (_, childSummary, isAlive) in updateInfo. nonDirtySummaries {
416+ if isAlive {
417+ value = ProgressManager . Properties. TotalByteCount. merge ( value, childSummary)
418+ } else {
419+ value = ProgressManager . Properties. TotalByteCount. finalSummary ( value, childSummary)
420+ }
421+ }
422+
423+ case . completed:
424+ // Apply updates from children that were dirty
425+ for update in childUpdates {
426+ children [ update. index] . completedByteCount = PropertyStateUInt64 ( value: update. updatedSummary, isDirty: false )
427+ value = ProgressManager . Properties. CompletedByteCount. merge ( value, update. updatedSummary)
428+ }
429+
430+ // Apply values from non-dirty children
431+ for (_, childSummary, isAlive) in updateInfo. nonDirtySummaries {
432+ if isAlive {
433+ value = ProgressManager . Properties. CompletedByteCount. merge ( value, childSummary)
434+ } else {
435+ value = ProgressManager . Properties. CompletedByteCount. finalSummary ( value, childSummary)
436+ }
437+ }
438+ }
439+
440+ return value
441+ }
442+
326443 internal mutating func getThroughputUpdateInfo( ) -> ThroughputUpdateInfo {
327444 var currentSummary = ProgressManager . Properties. Throughput. defaultSummary
328445 ProgressManager . Properties. Throughput. reduce ( into: & currentSummary, value: throughput)
0 commit comments