My question is quite simple. Why isn't std::atomic<double>
implemented completely? I know it has to do with atomic RMW (read-modify-write) access. But I really don't see, why this shouldn't be possible on a double
.
It's specified that any trivially copyable type can be used. And of course double
is among them. So C++11 requires the basic operations (load, store, CAS, exchange, etc.) that you can use with any class type.
However, on integers an extra set of operations is possible (fetch_add
, ++
, +=
, etc).
A double
differs very little from these types. It's native, trivially copyable, etc. Why didn't the standard include the double
with these types?
Update: C++20 does specialize std::atomic<T>
for floating-point types, with fetch_add and sub. C++20 std::atomic<float>- std::atomic<double>.specializations But not atomic absolute-value (AND) or negate (XOR).
Editor's note: Without C++20 you can roll your own out of CAS; see Atomic double floating point or SSE/AVX vector load/store on x86_64 for portable examples; atomic<double>
and float are lock-free on most C++ implementations.
double
operations. So how would you implement it? – Favoritedouble
even trivially copyable in the strictest sense seeing how its memory storage is not identical with register storage on most current CPUs? But even if it is, does it make sense to perform atomic operations on floating point data at all? You could probably say "sure, why not?", but it's hard for me to imagine why one would want to do any such thing. Integers and pointers and double pointers type-punned as large integers, sure. But floating point data? – Lorenlorenadouble
values, whichever is needed for "task". Once done, the worker thread posts the pointer to data onto the "results" queue from which the main thread can pull them. – Lorenlorenastd::atomic
is the most desirable thing, yes. But expect it to be implemented with a mutex, I'm pretty sure it's not lockfree on any mainstream architecture (this would very much surprise me). I wonder whether it might be worth punning thedouble
into anint64_t
and back. Not precisely the nicest thing to do, but this will be lockfree on (almost) every platform, and the cost to convert between floating point and integer is probably more or less equivalent to a mutex on fast path (spinning) and a few dozen times faster when congested (syscall). – Lorenlorenastd::atomic_is_lock_free
actually says atomic double is lock free for the msvc2013 compiler:). So at least in this particular case it seems to be lock free:). – Vaulesfld qword
/fstp qword
is a copy fordouble
. Converting to 80-bit internal format and back will never change the result, because everydouble
can be exactly represented in that format. (denormals are normalized when loading, but the extra exponent range always allows it to exactly represent the value). – Ceporahdouble
can be exactly represented). The only thing that could munge adouble
is if the x87 precision mode was set to 24-bit (float
) mantissa. Fun fact, gcc usesfild
/fistp
to implementstd::atomic<int64_t>
load/store on 32-bit x86. (from/to integer avoids raising FP exceptions).fld
can raise exceptions if they're unmasked. – Ceporahstd::atomic<double>
is lock-free on gcc/clang/msvc. stackoverflow.com/questions/45055402/… – CeporahInterlockedXor64
– Ceporah