Chani
Chani

Reputation: 5165

C++11 atomic library std::compare_and_exchange semantics

If sequenceNumber is atomic<int> (seq_no is just an int),

Why does

sequenceNumber.compare_exchange_strong(sequenceNumber, seq_no );

not compile ?

I had a comparison operation with the atomic variable sequenceNumber before the compare_exchange_strong operation and wanted to check if the value of sequenceNumber had been changed by the other thread by the time I actually came to update it in my thread.

Something like this:

if ( seq_no > sequenceNumber )
      sequenceNumber.compare_exchange_strong(sequenceNumber, seq_no);

I fixed it by:

int current_sequence_number = sequenceNumber.load();
if ( seq_no > current_sequence_number )
    sequenceNumber.compare_exchange_strong(current_sequence_number, seq_no );

But I am wondering why the compiler does not allow me to use an atomic<int> in place of the first argument, i.e. the "expected" parameter in the function call -

bool compare_exchange_strong( T& expected, T desired,
                              std::memory_order order = 
                                  std::memory_order_seq_cst ); 

What was the motivation behind disallowing an atomic variable in place of the expected argument especially when seq_no > sequenceNumber seems to be allowed ?

By the way, is using seq_no > sequenceNumber also wrong ? (even though it compiles) Should I go for seq_no > sequenceNumber.load() in that case as well ?

Upvotes: 0

Views: 247

Answers (1)

Igor Tandetnik
Igor Tandetnik

Reputation: 52471

atomic<T>::compare_exchange_strong takes T& as its first parameter. atomic<T> is not convertible to T& (even though it is convertible to an rvalue of type T; such a conversion just calls load()).

If atomic<T> were convertible to T&, it would effectively give unrestricted access to underlying raw storage, and allow users to modify it at will, bypassing any synchronization mechanisms. Which would thoroughly defeat the point of having an atomic in the first place.

Upvotes: 1

Related Questions