Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Atomically exchange value on result of comparison

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!

like image 508
dckrooney Avatar asked Aug 17 '11 22:08

dckrooney


2 Answers

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;
}
like image 35
Brian Gideon Avatar answered Sep 21 '22 21:09

Brian Gideon


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).

like image 93
hmakholm left over Monica Avatar answered Sep 22 '22 21:09

hmakholm left over Monica