linuxx86-64atomicc11

How can I combine a comparison and an update in one atomic operation?


I have two threads, which will execute:

_Atomic volatile uint64_t foo;

// returns 1 if it updated foo, 0 if fool already had the new value 
int try_to_update_foo(uint64_t new) {
    if (foo < new) {
        foo = new;
        return 1;
    }
    return 0;
}

I want the foo < new comparison and foo = new assignment operations to be one atomic operation.

i.e. If two threads both try to update foo to the same new value, one must return 1 and the other must returns 0. (It doesn't matter which way around.)

Can I make this work in C11, without involving semaphores/mutexs?


Solution

  • You can use atomic_compare_exchange_weak() or atomic_compare_exchange_strong():

    #include <stdatomic.h>
    
    _Atomic uint64_t foo;
    
    int try_to_update_foo(uint64_t new) {
        uint64_t expected = atomic_load(&foo);
        while (expected < new) {
            if (atomic_compare_exchange_weak(&foo, &expected, new)) {
                return 1;
            }
        }
        return 0;
    }
    

    See docs for details: https://en.cppreference.com/w/c/atomic/atomic_compare_exchange