Is comparing 2 int an atomic operation?

I am writing a very simple atomic counter like

class counter
{
    /* ... */

    int increment()
    {
        return __sync_add_and_fetch( &counter_, 1 );
    }
    int decrement()
    {
        return __sync_sub_and_fetch( &counter_, 1 );
    }
    bool operator==( int val ) // const
    {
        return __sync_bool_compare_and_swap( &counter_, val, counter_ );
    }

private:
    volatile int counter_;
};

      

Can I use it return counter_ == val;

inside mine operator==

(in short and will be able to uncomment the qualifier const

)? Or should I use __sync_bool_compare_and_swap

instead?


Edit: So, I'm more confused than at the beginning. After reading the comments and answers, I think that leaving "compare and exchange" more appropriate. It?

Edit 2: I got rid of this operator==

, but I'm still curious. I will wait and hope for a little more activity on this issue. Thank.

+3


source to share


2 answers


Yes and no.

Equality testing is atomic in that it is thread safe, but it only checks for equality at that point in time. A fraction of a second, one way or another, and the value you are comparing may have a different meaning. In particular, it is not a permanent feature as it uses hidden data that can change.

However, I would use it ==

here because your swap looks pointless.


Edit:

The point is that this is a variable load, which should be atomic, and not some other material.



This is what your program does:

  • Gets some values ​​in registers.

  • Loads an integer from memory.

  • Edits some values ​​in registers.

  • Returns

    ...

There's only one thing that has anything to do with concurrency: load. The counter value can change continuously, but your procedure cannot do anything special about it. Even with blocking, the best it can do is load the current value and work with what it has.

This value may have changed by the time the function returned, but all the code he could hope to do is tell whether the value matches the point at which it looked. The responsibility for this to be true must be due to the fact that nothing updated the counter until it was done).

Loading a structure or array, vector, or any other multivalued type will require you to acquire a read lock to make sure that what you get is self-consistent (that the first bit you read matches the last bit you read). But the integer load is quite definitely atomic (although not really guaranteed by C / C ++), so you don't need to worry.

The equality operator ==

only works on the contents of your own function (registers and stack), so there is no problem with concurrency (unless you took the address of your stack variable and sent it to another thread).

+4


source


Comparing 2 volatile variables is never a mindless atom (I think you mean that) because you have to load variables from memory every time and cannot handle them in registries. Comparison is done on most architectures done by subtracting both and checking for null. These are at least 3 instructions.



The question of atomicity is only needed here if there are decisions to make because of any connection between two values. Due to the volatility of values, you must poll for these values. Then the atomicity of the comparison doesn't make sense, because if you don't succeed in this turn, you will get it on the next turn, but there is no guarantee that you will hit every equality. Therefore, in this sense, the comparison with __sync_bool_compare_and_swap

is meaningless.

+1


source







All Articles