Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do compare and increment atomically?

In my attempt to develope a thread-safe C++ weak pointer template class, I need to check a flag that indicating the object is still alive, if yes then increment the object's reference count and I need to do the both steps atomically.

I know the existance of intrinsics functions provided by the compiler, for instance _InterlockedCompareExchange() and _InterlockedIncrement(). But what I want is an interlockedCompareIncrement() function, is there an efficient way to simulate this intrinsic using other primitives, at least on the Windows x86 platform?

like image 384
Ricky Lung Avatar asked Mar 04 '10 04:03

Ricky Lung


People also ask

What is atomically increment?

In computer science, the fetch-and-add CPU instruction (FAA) atomically increments the contents of a memory location by a specified value. That is, fetch-and-add performs the operation increment the value at address x by a, where x is a memory location and a is some value, and return the original value at x.

Is ++ atomic in Java?

Although globalVariable++ was executed 1000 times, the final value of globalVariable was 797. It proves that the + + increment operator in Java is not atomic.

How do atomic operations work?

During an atomic operation, a processor can read and write a location during the same data transmission. In this way, another input/output mechanism or processor cannot perform memory reading or writing tasks until the atomic operation has finished.


1 Answers

Suppose that value is your flag variable. It should be declared volatile.

long curvalue;
long newvalue;

do
{
    curvalue = value;
    newvalue = curvalue + 1;
}
while( _InterlockedCompareExchange( &value, newvalue, curvalue ) != curvalue );

As you see you can generalize this to whatever kind of arithmetic you need by changing the operations that are applied to calculate newvalue.

If you want to compare two values at the same time, your best bet is to pack both values into a single variable, and then operate on that single variable. Since you're using a flag combined with a reference count, I'd recommend using the lowest bit of value as the 'alive' flag, and then increment/decrement by 2 at a time. This allows you to encode both the flag and the reference count into a single 32-bit variable.

like image 164
Aaron Klotz Avatar answered Sep 20 '22 00:09

Aaron Klotz