cunionatomiccompare-and-swap

Are _Atomic members of unions a good idea?


I'm using _Atomic integers inside of unions, such as:

union dedup_option_seq {
    struct {
        uint32_t seq       :18;     // enough bits for seq
        uint32_t not_empty :1;      // inverted so that zero is empty
    };
    _Atomic uint32_t value;
};

I can then happily use &foo.value as a parameter in the atomic_...() functions.

I can set unions' values using the syntax:

union dedup_option_seq foo = {
    .seq = 42,
    .not_empty = 1
};

It's all working nicely, but am I causing any undefined behaviour, or other issues, when using unions with an _Atomic member?


Solution

  • It's all working nicely, but am I causing any undefined behaviour, or other issues, when using unions with an _Atomic member?

    C allows you to read back a different member of a union than the one that was last set. This much is ok in C (but not in C++). C does not restrict that based on the qualifiers (such as _Atomic) of the types involved, so that is not directly a problem.

    However,

    Between these, C allows of your example that

    Additionally, manipulating _Atomic object value non-atomically via other members of the union seems fraught. At minimum, such manipulations do not enjoy any of the atomicity guarantees that manipulating value directly provides.

    So is there undefined behavior here? Hard to say. There are definitely questions about the behavior that the language spec does not directly address. Some or all of that might be better characterized as unspecified than as undefined, but the former is not that much better than the latter if you require your program to reproducibly yield the same results on diverse C implementations.