Skip to content

Commit c113a98

Browse files
committed
temporary revert using dirty bit
1 parent 19a20e5 commit c113a98

File tree

1 file changed

+65
-174
lines changed

1 file changed

+65
-174
lines changed

Sources/FoundationEssentials/ProgressManager/ProgressManager.swift

Lines changed: 65 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,6 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
5353
var otherProperties: [AnyMetatypeWrapper: (any Sendable)]
5454
// Type: Metatype maps to dictionary of child to value
5555
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-
6556
var children: Set<ProgressManager>
6657
}
6758

@@ -87,10 +78,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
8778
public var totalCount: Int? {
8879
_$observationRegistrar.access(self, keyPath: \.totalCount)
8980
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)
9482
}
9583
}
9684

@@ -99,10 +87,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
9987
public var completedCount: Int {
10088
_$observationRegistrar.access(self, keyPath: \.completedCount)
10189
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)
10691
}
10792
}
10893

@@ -112,10 +97,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
11297
public var fractionCompleted: Double {
11398
_$observationRegistrar.access(self, keyPath: \.fractionCompleted)
11499
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)
119101
}
120102
}
121103

@@ -124,12 +106,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
124106
public var isIndeterminate: Bool {
125107
_$observationRegistrar.access(self, keyPath: \.isIndeterminate)
126108
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)
133110
}
134111
}
135112

@@ -138,47 +115,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
138115
public var isFinished: Bool {
139116
_$observationRegistrar.access(self, keyPath: \.isFinished)
140117
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)
182119
}
183120
}
184121

@@ -204,17 +141,24 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
204141
/// The total units of work.
205142
public var totalCount: Int? {
206143
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)
211145
}
212146

213147
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)
218162
manager.ghostReporter?.notifyObservers(with: .totalCountUpdated)
219163
manager.monitorInterop.withLock { [manager] interop in
220164
if interop == true {
@@ -228,17 +172,15 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
228172
/// The completed units of work.
229173
public var completedCount: Int {
230174
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)
235176
}
236177

237178
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)
241182
manager.ghostReporter?.notifyObservers(with: .fractionUpdated)
183+
242184
manager.monitorInterop.withLock { [manager] interop in
243185
if interop == true {
244186
manager.notifyObservers(with: .fractionUpdated)
@@ -293,14 +235,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
293235
childFraction: _ProgressFraction(completed: 0, total: 1),
294236
interopChild: nil
295237
)
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())
304239
self.state = LockedState(initialState: state)
305240
self.interopObservation = interopObservation
306241
self.ghostReporter = ghostReporter
@@ -314,6 +249,34 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
314249
self.init(total: totalCount, ghostReporter: nil, interopObservation: nil)
315250
}
316251

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+
317280
/// Returns a `Subprogress` representing a portion of `self` which can be passed to any method that reports progress.
318281
///
319282
/// - 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 {
343306
/// Increases `completedCount` by `count`.
344307
/// - Parameter count: Units of work.
345308
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)
350311

351312
// Interop updates stuff
352313
ghostReporter?.notifyObservers(with: .fractionUpdated)
@@ -382,16 +343,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
382343
return try state.withLock { state in
383344
var values = Values(manager: self, state: state)
384345
// 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())
395347
let result = try closure(&values)
396348
state = values.state
397349
return result
@@ -405,7 +357,7 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
405357
// var values = Values(manager: self, state: state)
406358
// // This is done to avoid copy on write later
407359
// state = State(fractionState: FractionState(indeterminate: true, selfFraction: _ProgressFraction(), childFraction: _ProgressFraction()), otherProperties: [:], childrenOtherProperties: [:])
408-
//
360+
//
409361
// do {
410362
// let result = try closure(&values)
411363
// state = values.state
@@ -477,26 +429,14 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
477429
let current: _ProgressFraction
478430
}
479431

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)
494438
}
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)
500440
}
501441

502442
private func updateFractionCompleted(from: _ProgressFraction, to: _ProgressFraction) {
@@ -538,60 +478,11 @@ internal struct AnyMetatypeWrapper: Hashable, Equatable, Sendable {
538478
state.fractionState.childFraction = state.fractionState.childFraction - (multiple * next)
539479
}
540480
}
541-
state.isDirtyTotal = false
542-
state.isDirtyCompleted = false
543481
return UpdateState(previous: previousOverallFraction, current: state.fractionState.overallFraction)
544482
}
545483
updateFractionCompleted(from: updateState.previous, to: updateState.current)
546484
}
547485

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-
595486
//MARK: Interop-related internal methods
596487
/// Adds `observer` to list of `_observers` in `self`.
597488
internal func addObserver(observer: @escaping @Sendable (ObserverState) -> Void) {

0 commit comments

Comments
 (0)