I have a very simple operation that needs to be done atomically:
if (a > b)
b = a
where a and b are ints
EDIT: and a is local.
Is there a fast way to do this in C#? I'd like to avoid locking manually if possible. I've looked at Interlocked.CompareExchange, but as I understand it, this only tests for equality.
Thanks!
Henning is correct. I will provide the details as they pertain to C#. The pattern can be generalized with the following function.
public static T InterlockedOperation<T>(ref T location, T operand)
{
T initial, computed;
do
{
initial = location;
computed = op(initial, operand); // where op is replaced with a specific implementation
}
while (Interlocked.CompareExchange(ref location, computed, initial) != initial);
return computed;
}
In your specific case we can define an InterlockedGreaterThanExchange
function like this.
public static int InterlockedGreaterThanExchange(ref int location, int value)
{
int initial, computed;
do
{
initial = location;
computed = value > initial ? value : initial;
}
while (Interlocked.CompareExchange(ref location, computed, initial) != initial);
return computed;
}
The canonical way is to use interlocked compare-exchange in a loop:
int oldvalue, newvalue ;
do {
oldvalue = b ; // you'll want to force this to be a volatile read somehow
if( a > oldvalue )
newvalue = a ;
else
break ;
} while( interlocked replace oldvalue with newvalue in b does NOT succeed );
(Pseudocode because I don't bother to look up the correct way to do an interlocked exchange in C#).
As you see, unless you have overriding efficiency concerns, using plain old mutexes is far simpler and more readable.
Edit: This assumes that a
is a local variable or at least not subject to asynchronous writes. It both of a
and b
can be modified behind your back, then there is no lock-free way of doing this update atomically. (Thanks to silev for pointing this out).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With