Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
219 views
in Technique[技术] by (71.8m points)

.net - How do I atomically swap 2 ints in C#?

What (if any) is the C# equivalent of the x86 asm xchg instruction?

With that command, which imo is a genuine exchange (unlike Interlocked.Exchange), I could simply atomically swap two ints, which is what I am really trying to do.

Update:

Sample code based upon my suggestion. Variable suffixed "_V" are decorated as volatile:

// 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 (i.e. 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;

Note the lazy update.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

Note that UP in the function name means UniProcessor. This is not atomic on SMP / multi-core systems. This implementation will only be used by CLR on single-core systems.

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 taking a bus lock. xchg has an implicit lock prefix, so unlike xadd or cmpxchg it simply can't be omitted for single-core systems to still do the operation in one instruction to make it atomic with respect to interrupts (and thus other threads on uniprocessor).

The odd looking jumping code is an optimization in case branch prediction data is not available. Needless to say perhaps, trying to do a better job than what has been mulled over for many years by very good software engineers with generous helpings from the chip manufacturers is a tall task.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...