简体   繁体   中英

Why does compare_exchange_strong fail with std::atomic<double>, std::atomic<float> in C++?

I am reading C++ Concurrency in Action Chapter 5. This chapter says,

Note that although you can use std::atomic<float> or std::atomic<double>, because the built-in floating point types do satisfy the criteria for use with memcpy and memcmp, the behavior may be surprising in the case of compare_exchange_strong. The operation may fail even though the old stored value was equal in value to the comparand, if the stored value had a different representation. Note that there are no atomic arithmetic operations on floating-point values. You'll get similar behavior with compare_exchange_strong if you use std::atomic<> with a user-defined type that has an equality-comparison operator defined, and that operator differs from the comparison using memcmp—the operation may fail because the otherwise-equal values have a different representation.

But I don't understand why it is.

  1. If float and double can use memcpy and memcmp, what is the matter to do atomic operation like compare_exchange_strong?

  2. I can't use compare_exchange_weak also?

  3. Above paragraph, what does "difference representation" mean?

IEEE-754 floats use a signed/magnitude format to determine the sign of the mantissa. That is, there's a sign bit, and then there are bits that represent a positive number. If the sign bit is set, then the number is interpreted as negative.

Of course, if all of the numeric (and exponent) bits are 0, and the sign bit is set, then that yields the "number" -0.0. As far as real-world human math is concerned, there is no "negative 0". So logically, such a number should be treated as equivalent to +0.0. And normal floating-point comparison logic does exactly that. But these two equivalent values are stored with different binary representations; one has the sign bit set; the other does not.

So if you do a comparison of the binary representation of two floating point values (which is what the atomic_compare_* operations will do), then -0.0 will not be considered equal to +0.0.

There are other cases where IEEE-754 equality testing can go wrong, but this is the simplest one to explain.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM