If we read an obsolete value, then CompareExchange will not perform the exchange - we basically say: "Perform the operation only if the value is really the one on which we based our calculations." Until at some point we get the right value, that's fine. It would be a problem if we continued to read the constant value forever, so CompareExchange never passed the check, but I strongly suspect that CompareExchange memory CompareExchange mean that at least after a while through the loop we will read the current value. The worst thing that could happen would be forever cyclical - the important thing is that we cannot update the variable in the wrong way.
(And yes, I think you're right that the Total property is dodgy.)
EDIT: In other words:
CompareExchange(ref totalValue, computedValue, initialValue)
means: "If the current state was indeed initialValue , then my calculations are valid and you must set it to computedValue ."
The current state may be incorrect for at least two reasons:
- Purpose
initialValue = totalValue; used an obsolete read with a different old value - Something changed
totalValue after this assignment
We don’t need to deal with these situations in different ways - so it’s good to do a “cheap” reading until at some point we start to see updated values ... and I believe that the memory barriers involved in CompareExchange guarantee that in a round-robin round, the obsolete value that we see is always as outdated as the previous call to CompareExchange .
EDIT. To clarify, I believe that the pattern is correct if and only if CompareExchange represents a memory barrier to totalValue . If this is not the case - if we are still reading arbitrarily the old values of totalValue , when we continue to totalValue loop, then the code is really broken and can never totalValue .
source share