Skip to content

[Proposal] Update ProgressManager Proposal #1335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Jun 30, 2025

Conversation

chloe-yeo
Copy link
Contributor

@chloe-yeo chloe-yeo commented Jun 5, 2025

ProgressManager Proposal Update

@chloe-yeo
Copy link
Contributor Author

@swift-ci please test

@chloe-yeo chloe-yeo marked this pull request as ready for review June 27, 2025 20:39
///
/// - Parameters:
/// - property: Type of property.
/// - values: Sum of values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a copy-pasta leftover?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, thanks for catching this, will fix this!

///
/// - Parameter property: Type of property.
/// - Returns: Array of values for property.
public func values<P: ProgressManager.Property>(of property: P.Type) -> [P.Value]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a sentence or two for this and the below API in the section about properties? I don't think I see the discussion in this proposal

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I can add this!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added :)

We considered introducing only two types in this API, `ProgressManager` and `Subprogress`, which would enable developers to create a tree of `ProgressManager` to report progress. However, this has two limitations:
- It assumes a single-parent, tree-based structure.
- Developers would have to expose a mutable `ProgressManager` to its observers if they decide to have `ProgressManager` as a property on a class. For example:
```swift
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think this indentation would cause this to not be rendered in code block as you intended.

Suggested change
```swift
```swift

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay will fix this!


let observedProgress = DownloadManager().progress
observedProgress.complete(count: 12) // ⚠️: ALLOWED, because `ProgressManager` is mutable!!
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```


### Introduce `totalCount` and `completedCount` properties as `UInt64`
We considered using `UInt64` as the type for `totalCount` and `completedCount` to support the case where developers use `totalCount` and `completedCount` to track downloads of larger files on 32-bit platforms byte-by-byte. However, developers are not encouraged to update progress byte-by-byte, and should instead set the counts to the granularity at which they want progress to be visibly updated. For instance, instead of updating the download progress of a 10,000 bytes file in a byte-by-byte fashion, developers can instead update the count by 1 for every 1,000 bytes that has been downloaded. In this case, developers set the `totalCount` to 10 instead of 10,000. To account for cases in which developers may want to report the current number of bytes downloaded, we added `totalByteCount` and `completedByteCount` to `ProgressManager.Properties`, which developers can set and display using format style.

### Make `totalCount` a settable property on `ProgressManager`
We previously considered making `totalCount` a settable property on `ProgressManager`, but this would introduce a race condition that is common among cases in which `Sendable` types have settable properties. This is because two threads can try to mutate `totalCount` at the same time, but the `Mutex` guarding `ProgressManager` will not be held across both operations, thus creating a race condition, resulting in the `totalCount` that can either reflects both the mutations, or one of the mutations indeterministically. Therefore, we changed it so that `totalCount` is a read-only property on `ProgressManager`, and is only mutable within the `withProperties` closure to prevent this race condition.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest that we remove the mention of mutex here. Using Mutex is an implementation detail, and is not really relevant to the discussion here. It is simply impossible to coordinate this within the class, regardless of the internal synchronization mechanism we use. (I guess the only way to forcefully synchronize this is to make ProgressManager a singleton...) It will always be the callsites' responsibility to make sure they're not mutating a shared variable concurrently.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

chloe-yeo

This comment was marked as resolved.

@chloe-yeo chloe-yeo requested a review from itingliu June 30, 2025 18:05
@chloe-yeo
Copy link
Contributor Author

@swift-ci please test

@chloe-yeo chloe-yeo merged commit 7a0e78f into swiftlang:main Jun 30, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants