[swift-evolution] Pitch: Much better-performing, Swift-native Progress replacement
Charles Srstka
cocoadev at charlessoft.com
Wed Feb 22 13:52:09 CST 2017
> On Feb 22, 2017, at 1:41 PM, Charles Srstka via swift-evolution <swift-evolution at swift.org> wrote:
>
>> * Updating completedUnitCount atomically
>>
>> The best practice here is to keep the progress object thread local. I think that updating one progress from multiple threads could be a code smell. Perhaps then you are doing several parts of the work and you should instead form a tree. This also leads in a direction where completed unit count is either 100% handed out to children or 100% controlled by your work-update-progress loop. Mixing the two leads to easy confusion about who is responsible for which portion. If you follow this rule, you never have to get the completed unit count, which means the race you describe does not exist.
>
> NSProgress is designed to be thread-safe by protecting access to its properties with an NSLock, but it is not in fact thread-safe. It is making a promise to its users that it is not keeping. In addition, the lack of an atomic increment means that if you are getting data from an API that only reports deltas, you either have to get the old completedUnitCount, or keep track of the running total yourself. An atomic increment operation would not only improve thread safety, but it would improve the experience, since it would reduce the work the user needs to do, while remaining safe and performant.
One thing to add to this is that when dealing with async APIs that you don’t control, you don’t always know that things will be thread-local.
So if some library provides:
public func OpaqueAPI(input: SomeInput, dataHandler: (Data) -> ())
then in your client code:
let progress = Progress.discreteProgress(totalUnitCount: ...)
OpaqueAPI(input: blah) { data in
// Update my progress by data.count, but I don’t necessarily know what thread this will happen on, or that it will be the same one every time
}
So, now I have to protect either the progress or some running total var that I’m keeping with locks/mutexes/semaphores/sync queues/etc., adding a ton of boilerplate to the method.
Charles
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170222/e34e0987/attachment.html>
More information about the swift-evolution
mailing list