> On Feb 22, 2017, at 1:41 PM, Charles Srstka via swift-evolution 
> <swift-evolution@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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to