How can I swap 2 ints in C #?

What (if any) is the equivalent of the C # ASM "XCHG" command .

With this command, which imo is a genuine exchange (unlike Interlocked.Exchange), I could just atomically change two ints, which I'm really trying to do.

Update:

Sample code based on my suggestion. The variable suffix "_V" is decorated as mutable:

// PART 3 - process links // prepare the new Producer address.ProducerNew.WorkMask_V = 0; // copy the current LinkMask address.ProducerNew.LinkMask_V = address.Producer.LinkMask_V; // has another (any) thread indicated it dropped its message link from this thread? if (this.routerEmptyMask[address.ID] != 0) { // allow all other bits to remain on (ie turn off now defunct links) address.ProducerNew.LinkMask_V &= ~this.routerEmptyMask[address.ID]; // reset this.routerEmptyMask[address.ID] = 0; } // PART 4 - swap address.ProducerNew = Interlocked.Exchange<IPC.Producer>(ref address.Producer, address.ProducerNew); // PART 5 - lazily include the new links, make a working copy workMask = address.Producer.LinkMask_V |= address.ProducerNew.WorkMask_V; 

Check out the lazy update.

+25
c # atomic
04 Oct '10 at 13:30
source share
8 answers

Here is some strange idea. I don’t know exactly how you set up your data structure. But if possible, you can store two int values ​​in long , then I think you can change them atomically.

For example, let's say you wrapped two values ​​as follows:

 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 that you can add the following Swap method to cause the pair to be replaced “atomically” (in fact, I don’t know if it is fair to say that the following is atomic, it looks more like 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 very possible that I did it wrong, of course. And there may be a flaw in this idea. This is just an idea.

+22
04 Oct '10 at 18:16
source share

This is a likely implementation for Interlocked.Exchange () in the CLR, copied from the SSCLI20 source:

 FASTCALL_FUNC ExchangeUP,8 _ASSERT_ALIGNED_4_X86 ecx mov eax, [ecx] ; attempted comparand retry: cmpxchg [ecx], edx jne retry1 ; predicted NOT taken retn retry1: jmp retry FASTCALL_ENDFUNC ExchangeUP 

It is superior to using XCHG because this code works without blocking the bus. An odd-looking jumping code is an optimization if branch prediction data is not available. Needless to say, perhaps trying to do a better job than what has been many years over the years, very good software engineers with generous help from chip manufacturers are a tall order.

+58
Oct 04 '10 at 13:48
source share

Why is Interlocked.Exchange not suitable?

If you need exact memory cells that need to be swapped, you are using the wrong language and platform since .NET abstracts memory management so you don't need to think about it.

If you should do something like this without Interlocked.Exchange , you can write code labeled unsafe and do a traditional pointer-based exchange like you could in C or C ++, but you will need to wrap it in a suitable synchronization context so that it is an atomic operation.

Update
You do not need to resort to unsafe code to automatically change. You can wrap code in a synchronization context to make it atomic.

 lock (myLockObject) { var x = Interlocked.Exchange(a, b); Interlocked.Exchange(b, x); } 

Update 2
If synchronization is not an option (as indicated in the comments), then I think you're out of luck. When you pursue some immeasurable effectiveness, you can concentrate elsewhere. If replacing two integer values ​​is a huge performance, you are probably using the wrong platform.

+23
04 Oct '10 at 13:34
source share

Interlocked.Exchange is the only thing you can do:

  var x = Interlocked.Exchange(a, b); Interlocked.Exchange(b, x); 

You are right that this will not be atomic, but using a local variable you are guaranteed that the values ​​will be consistent as long as both lines are executed. Your other options are unsafe code (for using pointers), using p / invoke in your native library, or redesigning so that it is no longer required.

+8
Oct 04 2018-10-10 at
source share

According to MSDN , Interlocked.Exchange is atomic.

If this is not suitable for you, you can implement XCHG in an insecure section using C / C ++.

+5
Oct 04 2018-10-10
source share

Interlocked.Exchange is the best way to swap two int values ​​in streaming safe mode in C #.

Use this class even if you have a multiprocessor computer, and you never know in which processor your thread will work.

+1
04 Oct 2018-10-10
source share

Outside of Interlocked.Exchange, I assume that the XCHG command is probably an implementation of the XOR Swap , so you can write your own.

Syntax C: (from Wikipedia link)

  void xorSwap (int *x, int *y) { if (x != y) { *x ^= *y; *y ^= *x; *x ^= *y; } } 

Change , this is not atomic, you have to synchronize it yourself

0
04 Oct '10 at 13:37
source share

I think I have found a better solution. It:

Interlocked.Exchange () Method (ref T, T)

All "new" variables can be set in the (Of T) class and replaced with current variables. This allows you to take an atomic picture, effectively replacing any number of variables.

0
04 Oct '10 at 16:55
source share



All Articles