How to Atomically Swap 2 Ints in C#

How do I atomically swap 2 ints in C#?

Here's kind of a weird idea. I don't know exactly how you have your data structure set up. But if it's possible you could store your two int values in a long, then I think you could swap them atomically.

For example, let's say you wrapped your two values in the following manner:

class SwappablePair
{
long m_pair;

public SwappablePair(int x, int y)
{
m_pair = ((long)x << 32) | (uint)y;
}

/// <summary>
/// Reads the values of X and Y atomically.
/// </summary>
public void GetValues(out int x, out int y)
{
long current = Interlocked.Read(ref m_pair);

x = (int)(current >> 32);
y = (int)(current & 0xffffffff);
}

/// <summary>
/// Sets the values of X and Y atomically.
/// </summary>
public void SetValues(int x, int y)
{
// If you wanted, you could also take the return value here
// and set two out int parameters to indicate what the previous
// values were.
Interlocked.Exchange(ref m_pair, ((long)x << 32) | (uint)y);
}
}

Then it seems you could add the following Swap method to result in a swapped pair "atomically" (actually, I don't know if it's fair to really say that the following is atomic; it's more like it produces the same result as an atomic swap).

/// <summary>
/// Swaps the values of X and Y atomically.
/// </summary>
public void Swap()
{
long orig, swapped;
do
{
orig = Interlocked.Read(ref m_pair);
swapped = orig << 32 | (uint)(orig >> 32);
} while (Interlocked.CompareExchange(ref m_pair, swapped, orig) != orig);
}

It is highly possible I've implemented this incorrectly, of course. And there could be a flaw in this idea. It's just an idea.

Swap two variables without using a temporary variable

First of all, swapping without a temporary variable in a language as C# is a very bad idea.

But for the sake of answer, you can use this code:

startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;

Problems can however occur with rounding off if the two numbers differ largely. This is due to the nature of floating point numbers.

If you want to hide the temporary variable, you can use a utility method:

public static class Foo {

public static void Swap<T> (ref T lhs, ref T rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
}

Swap Integer variables without using any assignment

You can use Interlocked.Exchange.

Swap two numbers without using another variable

use the following concept

int a=4 ;
int b=3 ;

a=a+b ; // a=7
b=a-b ; // b=7-3=4
a=a-b ; // c=7-4=3

How to swap two variable values?

if (sH > fH) {
double temp = sH;
sH = fH;
fH = temp;
}

The swapping can be accomplished by using a temporary third variable. Store sH in a temporary variable and assign sH to fH. This way the value of sH is cached and not lost when reassigning. Lastly, assign fH to temp. The values are now swapped.

Hope this helps

Is a C# 7 tuple-based variable swap thread safe?

"No, basically".

The ValueTuple<...> family are mutable value types, which makes it complex. The older Tuple<...> family were immutable reference types; the "immutable" matters because it means it isn't changing individual fields - it is creating a new object with all the values. The "reference-type" matters because this is then a single reference exchange which is thread-safe in as much as you can't get a "torn reference". It isn't thread-safe in other ways: there's no guarantees about ordering or registers, etc.

But with ValueTuple<...> even that is gone. Because it is a mutable type, this is most likely implemented as multiple ldloca/ld.../stfld instructions, so even if the value type is not larger than the CPU width, there's no guarantee that it will all be written in a single CPU instruction - and it almost certainly won't be. In the "return a value, assign the entire thing" scenario it might be a single CPU instruction if small enough, but it might not! To make it even more complex, in addition to the mutable field approach, there are also custom constructors - but they will still ultimately be writing over the same memory location (for value types, the destination managed reference is passed into the constructor, rather than the constructed value being passed out).

There is no guarantee whatsoever made by the language or runtime about tuple atomicity; they only make guarantees about references and certain primitives -additionally, even if it was: thread-safety is a lot more than just atomicity.

Finally, it would also depend don the target CPU; obviously a 2-int tuple cannot be atomic on a 32-bit CPU.

C#: Good/best implementation of Swap method

Well, the code you have posted (ref cards[n]) can only work with an array (not a list) - but you would use simply (where foo and bar are the two values):

static void Swap(ref int foo, ref int bar) {
int tmp = foo;
foo = bar;
bar = tmp;
}

Or possibly (if you want atomic):

Interlocked.Exchange(ref foo, ref bar);

Personally, I don't think I'd bother with a swap method, though - just do it directly; this means that you can use (either for a list or for an array):

int tmp = cards[n];
cards[n] = cards[i];
cards[i] = tmp;

If you really wanted to write a swap method that worked on either a list or an array, you'd have to do something like:

static void Swap(IList<int> list, int indexA, int indexB)
{
int tmp = list[indexA];
list[indexA] = list[indexB];
list[indexB] = tmp;
}

(it would be trivial to make this generic) - however, the original "inline" version (i.e. not a method) working on an array will be faster.

Is the return value of Interlocked.Exchange also processed atomically?

I assume you're considering code like this:

using System;
using System.Threading;

class Test
{
static int x = 1;
static int y = 2;

static void Main()
{
x = Interlocked.Exchange(ref y, 5);
}
}

In that case, no, the operation isn't atomic. In IL, there are two separate actions:

  • Calling the method
  • Copying the value from the notional stack to the field

It would be entirely possible for another thread to "see" y become 5 before the return value of Interlocked.Exchange was stored in x.

Personally, if I were looking at something where you need multiple field values to be changed atomically, I'd be considering locks instead of atomic lock-free operations.

Atomically exchange value on result of comparison

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



Related Topics



Leave a reply



Submit