@@ -53,15 +53,6 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
53
53
var otherProperties : [ AnyMetatypeWrapper : ( any Sendable ) ]
54
54
// Type: Metatype maps to dictionary of child to value
55
55
var childrenOtherProperties : [ AnyMetatypeWrapper : OrderedDictionary < ProgressManager , [ ( any Sendable ) ] > ]
56
-
57
- // dirty bit for completed count
58
- var isDirtyCompleted : Bool
59
- var updatedCompletedCount : Int
60
-
61
- // dirty bit for total count
62
- var isDirtyTotal : Bool
63
- var updatedTotalCount : Int ?
64
-
65
56
var children : Set < ProgressManager >
66
57
}
67
58
@@ -87,10 +78,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
87
78
public var totalCount : Int ? {
88
79
_ $observationRegistrar. access ( self , keyPath: \. totalCount)
89
80
return state. withLock { state in
90
- if state. isDirtyTotal {
91
- updateDirtiedValues ( state: & state)
92
- }
93
- return getTotalCount ( fractionState: & state. fractionState)
81
+ getTotalCount ( fractionState: & state. fractionState)
94
82
}
95
83
}
96
84
@@ -99,10 +87,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
99
87
public var completedCount : Int {
100
88
_ $observationRegistrar. access ( self , keyPath: \. completedCount)
101
89
return state. withLock { state in
102
- if state. isDirtyCompleted {
103
- updateDirtiedValues ( state: & state)
104
- }
105
- return getCompletedCount ( fractionState: & state. fractionState)
90
+ getCompletedCount ( fractionState: & state. fractionState)
106
91
}
107
92
}
108
93
@@ -112,10 +97,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
112
97
public var fractionCompleted : Double {
113
98
_ $observationRegistrar. access ( self , keyPath: \. fractionCompleted)
114
99
return state. withLock { state in
115
- if state. isDirtyTotal || state. isDirtyCompleted {
116
- updateDirtiedValues ( state: & state)
117
- }
118
- return getFractionCompleted ( fractionState: & state. fractionState)
100
+ getFractionCompleted ( fractionState: & state. fractionState)
119
101
}
120
102
}
121
103
@@ -124,12 +106,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
124
106
public var isIndeterminate : Bool {
125
107
_ $observationRegistrar. access ( self , keyPath: \. isIndeterminate)
126
108
return state. withLock { state in
127
- if state. isDirtyTotal {
128
- if state. isDirtyTotal || state. isDirtyCompleted {
129
- updateDirtiedValues ( state: & state)
130
- }
131
- }
132
- return getIsIndeterminate ( fractionState: & state. fractionState)
109
+ getIsIndeterminate ( fractionState: & state. fractionState)
133
110
}
134
111
}
135
112
@@ -138,47 +115,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
138
115
public var isFinished : Bool {
139
116
_ $observationRegistrar. access ( self , keyPath: \. isFinished)
140
117
return state. withLock { state in
141
- if state. isDirtyTotal || state. isDirtyCompleted {
142
- updateDirtiedValues ( state: & state)
143
- }
144
- return getIsFinished ( fractionState: & state. fractionState)
145
- }
146
- }
147
-
148
- /// This is called if the total dirty bit is set
149
- private func updateDirtiedValues( state: inout State ) {
150
- if state. children. isEmpty {
151
- // If there are no children, update value directly and don't traverse down anymore
152
- let updateState = getPreviousAndCurrentState ( state: & state)
153
- updateFractionCompleted ( from: updateState. previous, to: updateState. current)
154
-
155
- // mark dirty bit false
156
- state. isDirtyTotal = false
157
- state. isDirtyCompleted = false
158
- } else {
159
- // If there are children, traverse down
160
- for child in state. children {
161
- child. updateDirtiedValues ( )
162
- }
163
- }
164
- }
165
-
166
- private func updateDirtiedValues( ) {
167
- state. withLock { state in
168
- if state. children. isEmpty {
169
- // If there are no children, update value directly and don't traverse down anymore
170
- let updateState = getPreviousAndCurrentState ( state: & state)
171
- updateFractionCompleted ( from: updateState. previous, to: updateState. current)
172
-
173
- // mark dirty bit false
174
- state. isDirtyTotal = false
175
- state. isDirtyCompleted = false
176
- } else {
177
- // If there are children, traverse down
178
- for child in state. children {
179
- child. updateDirtiedValues ( )
180
- }
181
- }
118
+ getIsFinished ( fractionState: & state. fractionState)
182
119
}
183
120
}
184
121
@@ -204,17 +141,24 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
204
141
/// The total units of work.
205
142
public var totalCount : Int ? {
206
143
mutating get {
207
- if state. isDirtyTotal {
208
- manager. updateDirtiedValues ( state: & state)
209
- }
210
- return manager. getTotalCount ( fractionState: & state. fractionState)
144
+ manager. getTotalCount ( fractionState: & state. fractionState)
211
145
}
212
146
213
147
set {
214
- state. updatedTotalCount = newValue
215
- manager. markTotalDirty ( state: & state)
216
-
217
- // Interop updates stuff
148
+ let previous = state. fractionState. overallFraction
149
+ if state. fractionState. selfFraction. total != newValue && state. fractionState. selfFraction. total > 0 {
150
+ state. fractionState. childFraction = state. fractionState. childFraction * _ProgressFraction( completed: state. fractionState. selfFraction. total, total: newValue ?? 1 )
151
+ }
152
+ state. fractionState. selfFraction. total = newValue ?? 0
153
+
154
+ // if newValue is nil, reset indeterminate to true
155
+ if newValue != nil {
156
+ state. fractionState. indeterminate = false
157
+ } else {
158
+ state. fractionState. indeterminate = true
159
+ }
160
+ //TODO: rdar://149015734 Check throttling
161
+ manager. updateFractionCompleted ( from: previous, to: state. fractionState. overallFraction)
218
162
manager. ghostReporter? . notifyObservers ( with: . totalCountUpdated)
219
163
manager. monitorInterop. withLock { [ manager] interop in
220
164
if interop == true {
@@ -228,17 +172,15 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
228
172
/// The completed units of work.
229
173
public var completedCount : Int {
230
174
mutating get {
231
- if state. isDirtyCompleted {
232
- manager. updateDirtiedValues ( state: & state)
233
- }
234
- return manager. getCompletedCount ( fractionState: & state. fractionState)
175
+ manager. getCompletedCount ( fractionState: & state. fractionState)
235
176
}
236
177
237
178
set {
238
- state . updatedCompletedCount = newValue
239
- manager . markCompletedDirty ( state: & state )
240
-
179
+ let prev = state . fractionState . overallFraction
180
+ state. fractionState . selfFraction . completed = newValue
181
+ manager . updateFractionCompleted ( from : prev , to : state . fractionState . overallFraction )
241
182
manager. ghostReporter? . notifyObservers ( with: . fractionUpdated)
183
+
242
184
manager. monitorInterop. withLock { [ manager] interop in
243
185
if interop == true {
244
186
manager. notifyObservers ( with: . fractionUpdated)
@@ -293,14 +235,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
293
235
childFraction: _ProgressFraction ( completed: 0 , total: 1 ) ,
294
236
interopChild: nil
295
237
)
296
- let state = State ( fractionState: fractionState,
297
- otherProperties: [ : ] ,
298
- childrenOtherProperties: [ : ] ,
299
- isDirtyCompleted: false ,
300
- updatedCompletedCount: 0 ,
301
- isDirtyTotal: false ,
302
- updatedTotalCount: 0 ,
303
- children: Set ( ) )
238
+ let state = State ( fractionState: fractionState, otherProperties: [ : ] , childrenOtherProperties: [ : ] , children: Set ( ) )
304
239
self . state = LockedState ( initialState: state)
305
240
self . interopObservation = interopObservation
306
241
self . ghostReporter = ghostReporter
@@ -314,6 +249,34 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
314
249
self . init ( total: totalCount, ghostReporter: nil , interopObservation: nil )
315
250
}
316
251
252
+ /// Sets `totalCount`.
253
+ /// - Parameter newTotal: Total units of work.
254
+ public func setTotalCount( _ newTotal: Int ? ) {
255
+ state. withLock { state in
256
+ let previous = state. fractionState. overallFraction
257
+ if state. fractionState. selfFraction. total != newTotal && state. fractionState. selfFraction. total > 0 {
258
+ state. fractionState. childFraction = state. fractionState. childFraction * _ProgressFraction( completed: state. fractionState. selfFraction. total, total: newTotal ?? 1 )
259
+ }
260
+ state. fractionState. selfFraction. total = newTotal ?? 0
261
+
262
+ // if newValue is nil, reset indeterminate to true
263
+ if newTotal != nil {
264
+ state. fractionState. indeterminate = false
265
+ } else {
266
+ state. fractionState. indeterminate = true
267
+ }
268
+ updateFractionCompleted ( from: previous, to: state. fractionState. overallFraction)
269
+
270
+ ghostReporter? . notifyObservers ( with: . totalCountUpdated)
271
+
272
+ monitorInterop. withLock { [ self ] interop in
273
+ if interop == true {
274
+ notifyObservers ( with: . totalCountUpdated)
275
+ }
276
+ }
277
+ }
278
+ }
279
+
317
280
/// Returns a `Subprogress` representing a portion of `self` which can be passed to any method that reports progress.
318
281
///
319
282
/// - Parameter count: Units, which is a portion of `totalCount`delegated to an instance of `Subprogress`.
@@ -343,10 +306,8 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
343
306
/// Increases `completedCount` by `count`.
344
307
/// - Parameter count: Units of work.
345
308
public func complete( count: Int ) {
346
- state. withLock { state in
347
- state. updatedCompletedCount = state. fractionState. selfFraction. completed + count
348
- markCompletedDirty ( state: & state)
349
- }
309
+ let updateState = updateCompletedCount ( count: count)
310
+ updateFractionCompleted ( from: updateState. previous, to: updateState. current)
350
311
351
312
// Interop updates stuff
352
313
ghostReporter? . notifyObservers ( with: . fractionUpdated)
@@ -382,16 +343,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
382
343
return try state. withLock { state in
383
344
var values = Values ( manager: self , state: state)
384
345
// This is done to avoid copy on write later
385
- state = State ( fractionState: FractionState ( indeterminate: true ,
386
- selfFraction: _ProgressFraction ( ) ,
387
- childFraction: _ProgressFraction ( ) ) ,
388
- otherProperties: [ : ] ,
389
- childrenOtherProperties: [ : ] ,
390
- isDirtyCompleted: false ,
391
- updatedCompletedCount: 0 ,
392
- isDirtyTotal: false ,
393
- updatedTotalCount: 0 ,
394
- children: Set ( ) )
346
+ state = State ( fractionState: FractionState ( indeterminate: true , selfFraction: _ProgressFraction ( ) , childFraction: _ProgressFraction ( ) ) , otherProperties: [ : ] , childrenOtherProperties: [ : ] , children: Set ( ) )
395
347
let result = try closure ( & values)
396
348
state = values. state
397
349
return result
@@ -405,7 +357,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
405
357
// var values = Values(manager: self, state: state)
406
358
// // This is done to avoid copy on write later
407
359
// state = State(fractionState: FractionState(indeterminate: true, selfFraction: _ProgressFraction(), childFraction: _ProgressFraction()), otherProperties: [:], childrenOtherProperties: [:])
408
- //
360
+ //
409
361
// do {
410
362
// let result = try closure(&values)
411
363
// state = values.state
@@ -477,26 +429,14 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
477
429
let current : _ProgressFraction
478
430
}
479
431
480
- private func getPreviousAndCurrentState( state: inout State ) -> UpdateState {
481
- let prev = state. fractionState. overallFraction
482
- if state. isDirtyTotal {
483
- if state. updatedTotalCount == nil {
484
- print ( " updated total count is nil " )
485
- state. fractionState. indeterminate = true
486
- } else {
487
- state. fractionState. indeterminate = false
488
- }
489
- // actually update totalCount
490
- if ( state. fractionState. selfFraction. total != ( state. updatedTotalCount ?? 0 ) ) && ( state. fractionState. selfFraction. total > 0 ) {
491
- state. fractionState. childFraction = state. fractionState. childFraction * _ProgressFraction( completed: state. fractionState. selfFraction. total, total: state. updatedTotalCount ?? 1 )
492
- }
493
- state. fractionState. selfFraction. total = state. updatedTotalCount ?? 0
432
+ private func updateCompletedCount( count: Int ) -> UpdateState {
433
+ // Acquire and release child's lock
434
+ let ( previous, current) = state. withLock { state in
435
+ let prev = state. fractionState. overallFraction
436
+ state. fractionState. selfFraction. completed += count
437
+ return ( prev, state. fractionState. overallFraction)
494
438
}
495
- if state. isDirtyCompleted {
496
- // actually update completedCount
497
- state. fractionState. selfFraction. completed = state. updatedCompletedCount
498
- }
499
- return UpdateState ( previous: prev, current: state. fractionState. overallFraction)
439
+ return UpdateState ( previous: previous, current: current)
500
440
}
501
441
502
442
private func updateFractionCompleted( from: _ProgressFraction , to: _ProgressFraction ) {
@@ -538,60 +478,11 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
538
478
state. fractionState. childFraction = state. fractionState. childFraction - ( multiple * next)
539
479
}
540
480
}
541
- state. isDirtyTotal = false
542
- state. isDirtyCompleted = false
543
481
return UpdateState ( previous: previousOverallFraction, current: state. fractionState. overallFraction)
544
482
}
545
483
updateFractionCompleted ( from: updateState. previous, to: updateState. current)
546
484
}
547
485
548
-
549
- /// Update completedCount and mark all ancestors as dirty.
550
- private func markCompletedDirty( state: inout State ) {
551
- state. isDirtyCompleted = true
552
-
553
- // recursively mark all ancestors as dirty
554
- parents. withLock { parents in
555
- for (parent, _) in parents {
556
- parent. markCompletedDirty ( )
557
- }
558
- }
559
- }
560
-
561
- private func markCompletedDirty( ) {
562
- state. withLock { state in
563
- state. isDirtyCompleted = true
564
- }
565
-
566
- parents. withLock { parents in
567
- for (parent, _) in parents {
568
- parent. markCompletedDirty ( )
569
- }
570
- }
571
- }
572
-
573
- private func markTotalDirty( state: inout State ) {
574
- state. isDirtyTotal = true
575
-
576
- parents. withLock { parents in
577
- for (parent, _) in parents {
578
- parent. markTotalDirty ( )
579
- }
580
- }
581
- }
582
-
583
- private func markTotalDirty( ) {
584
- state. withLock { state in
585
- state. isDirtyTotal = true
586
- }
587
-
588
- parents. withLock { parents in
589
- for (parent, _) in parents {
590
- parent. markTotalDirty ( )
591
- }
592
- }
593
- }
594
-
595
486
//MARK: Interop-related internal methods
596
487
/// Adds `observer` to list of `_observers` in `self`.
597
488
internal func addObserver( observer: @escaping @Sendable ( ObserverState ) -> Void ) {
0 commit comments