What is the difference between...?
struct foo
{
uint16_t a;
uint16_t b;
uint16_t c;
uint16_t not_used;
};
and
union foo
{
uint64_t dont_care;
struct
{
uint16_t a;
uint16_t b;
uint16_t c;
uint16_t not_used;
};
};
Well yes, 47 characters. But apart from that, what if you e.g. make a std::atomic<foo>?
For a compare-exchange, the difference is around 200 instructions! And no, the union is not the one with more instructions. :)
It is of course well-known that std::atomic doesn't guarantee that just about everything be atomic, in particular it gives no guarantees whatsoever except on atomic_flag. How could one guarantee every possible thing being atomic, anyway -- the hardware doesn't necessarily even support that. OK. Accepted.
But you can somewhat expect that something that easily fits within the instruction set's capabilities (an integer, a struct of two integers, four smaller integers) is "just atomic" anyway. Well, that's not the case.
But what's really stunning is not so much that the compiler fails to emit e.g. a single CMPXCHG8B when it could just do that in the first case. What truly does me is that if you give the compiler a "hint" by aliasing with an uint64_t as in the second case, then all of a sudden, as if by magic, it works...
How did I find out? You don't want to know. :lol: