@@ -27,6 +27,7 @@ internal struct FractionState {
2727 var overallFraction : _ProgressFraction {
2828 selfFraction + childFraction
2929 }
30+ var children : Set < ProgressManager >
3031 var interopChild : ProgressManager ? // read from this if self is actually an interop ghost
3132}
3233
@@ -153,6 +154,13 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
153154 }
154155 state. fractionState. selfFraction. total = newValue ?? 0
155156
157+ // Updating my own childFraction here because previously they did not get updated because my total was 0
158+ if !state. fractionState. children. isEmpty {
159+ for child in state. fractionState. children {
160+ child. updateChildFractionSpecial ( of: manager, state: & state)
161+ }
162+ }
163+
156164 // if newValue is nil, reset indeterminate to true
157165 if newValue != nil {
158166 state. fractionState. indeterminate = false
@@ -227,16 +235,15 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
227235 }
228236
229237 internal let parents : LockedState < [ ProgressManager : Int ] >
230- private let children : LockedState < Set < ProgressManager > >
231238 private let state : LockedState < State >
232239
233240 internal init ( total: Int ? , ghostReporter: ProgressManager ? , interopObservation: ( any Sendable ) ? ) {
234241 self . parents = . init( initialState: [ : ] )
235- self . children = . init( initialState: Set ( ) )
236242 let fractionState = FractionState (
237243 indeterminate: total == nil ? true : false ,
238244 selfFraction: _ProgressFraction ( completed: 0 , total: total ?? 0 ) ,
239245 childFraction: _ProgressFraction ( completed: 0 , total: 1 ) ,
246+ children: Set < ProgressManager > ( ) ,
240247 interopChild: nil
241248 )
242249 let state = State ( fractionState: fractionState, otherProperties: [ : ] , childrenOtherProperties: [ : ] )
@@ -324,7 +331,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
324331 return try state. withLock { ( state) throws ( E) -> T in
325332 var values = Values ( manager: self , state: state)
326333 // This is done to avoid copy on write later
327- state = State ( fractionState: FractionState ( indeterminate: true , selfFraction: _ProgressFraction ( ) , childFraction: _ProgressFraction ( ) ) , otherProperties: [ : ] , childrenOtherProperties: [ : ] )
334+ state = State ( fractionState: FractionState ( indeterminate: true , selfFraction: _ProgressFraction ( ) , childFraction: _ProgressFraction ( ) , children : Set ( ) ) , otherProperties: [ : ] , childrenOtherProperties: [ : ] )
328335 let result = try closure ( & values)
329336 state = values. state
330337 return result
@@ -402,6 +409,23 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
402409 return UpdateState ( previous: previous, current: current)
403410 }
404411
412+ // This is used when parent has its lock acquired and wants its child to update parent's childFraction to reflect child's own changes
413+ private func updateChildFractionSpecial( of manager: ProgressManager , state managerState: inout State ) {
414+ let portion = parents. withLock { parents in
415+ return parents [ manager]
416+ }
417+
418+ if let portionOfParent = portion {
419+ let myFraction = state. withLock { $0. fractionState. overallFraction }
420+
421+ if myFraction. isFinished {
422+ // If I'm not finished, update my entry in parent's childFraction
423+ managerState. fractionState. childFraction = managerState. fractionState. childFraction + _ProgressFraction( completed: portionOfParent, total: managerState. fractionState. selfFraction. total) * myFraction
424+
425+ }
426+ }
427+ }
428+
405429 private func updateFractionCompleted( from: _ProgressFraction , to: _ProgressFraction ) {
406430 _ $observationRegistrar. withMutation ( of: self , keyPath: \. fractionCompleted) {
407431 if from != to {
@@ -491,8 +515,8 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
491515 }
492516
493517 internal func addToChildren( childManager: ProgressManager ) {
494- _ = children . withLock { children in
495- children. insert ( childManager)
518+ _ = state . withLock { state in
519+ state . fractionState . children. insert ( childManager)
496520 }
497521 }
498522
0 commit comments