atomic compare(not equal) and swap atomic compare(not equal) and swap multithreading multithreading

atomic compare(not equal) and swap


How about this:

void compare_and_swap_if_not_equal(word_t const required_non_value, word_t const new_value, word_t* ptr_to_shared_variable) {     for (;;) {        word_t const snapshot_value = *ptr_to_shared_variable;        if (required_non_value == snapshot_value) {            break;            // or (sleep and) 'continue;', if you want to wait for the stored value to be different             // -- but you might of course miss a transient change to a different state and back.        } else {             if (compare_and_swap_if_equal(ptr_to_shared_variable, snapshot_value, new_value)) {                // we know the stored value was different; if this 'theory' still matches reality: swap! done!                break;            }        }    }}

Untested. Uncompiled. The 'const' used because I like it that way :). 'word_t' is a type placeholder, I don't know what the real type should be. And I don't know how what 'compare_and_swap_if_equal' is called in stdatomic.h.

(added) atomic_compare_exchange_weak() is the ticket. For some reason, it takes a pointer to the 'expected' argument, so you'll have to modify above code to

if (atomic_compare_exchange_weak(ptr_to_shared_variable, &snapshot_value, new_value)) ...

The 'weak' version should work in the above code; returning 'false' spuriously will only add another trip around the loop. Still uncompiled, untested; don't rely on this code at home.


It depends on your architecture, but in general it is not possible to do this in C.

Typically compare and swap is implemented with an instruction that atomically loads from a location in memory and stores a value to that location if the location in memory matches some existing value that you specify.

At least on x86 there is no provision for only doing this load if the values don't match. Also it's not clear why you would want to do something like that. Perhaps another architecture would support something like this, but that would be architecture dependent, not something that could be done in C in a portable way.