简体   繁体   中英

Can I apply the C11 `_Atomic` keyword to enum types?

If I have a type

enum foo {
    FOO,
    BAR,
    BAZ,
};

can I then declare an atomic version of that type like

_Atomic(enum foo);

or do I have to use eg atomic_int and cast the result of atomic_load() ?

The following program compiles without warnings:

    #include <stdatomic.h>
    #include <stdio.h>

    enum foo {FOO, BAR, BAZ};

    int main(void) {
        _Atomic(enum foo) foo_a;
        atomic_store(&foo_a, BAR);
        enum foo val = atomic_load(&foo_a);
        printf("%u\n", val);
        return 0;
    }

but so does:

    #include <stdatomic.h>
    #include <stdio.h>

    enum foo {FOO, BAR, BAZ};

    int main(void) {
        enum foo foo; // <---- non atomic
        atomic_store(&foo, BAR);
        enum foo val = atomic_load(&foo);
        printf("%u\n", val);
        return 0;
    }

Yes, all data types can be atomic, and there is no need to use the atomic generic functions for these. All operations with such an object is then atomic.

For your second example it is weird that you compiler does not issue a warning. Using a non-atomic for an atomic operation is a constraint violation, so the compiler should give you a diagnostic.

Yes this is legal. BTW, you don't actually need the parens, _Atomic enum foo foo; is equivalent.

_Atomic works like other type qualifiers, like const and volatile .


enum foo foo;
atomic_store(&foo, BAR);

is an error with clang . error: address argument to atomic operation must be a pointer to _Atomic type ('enum foo *' invalid) . (From the Godbolt compiler explorer ).


It's just a quirk of GCC's implementation that it compiles without even a warning, even at -Wall . That should probably be changed...

GCC's atomic builtins like void __atomic_store_n (type *ptr, type val, int memorder) take a pointer to a plain type, without requiring _Atomic .

C++11 <atomic> uses these builtins. Similarly, GCC's C11 stdatomic.h uses

#define atomic_store_explicit(PTR, VAL, MO)                             \
  __extension__                                                         \
  ({                                                                    \
    __auto_type __atomic_store_ptr = (PTR);                             \
    __typeof__ (*__atomic_store_ptr) __atomic_store_tmp = (VAL);        \
    __atomic_store (__atomic_store_ptr, &__atomic_store_tmp, (MO));     \
  })

#define atomic_store(PTR, VAL)                          \
  atomic_store_explicit (PTR, VAL, __ATOMIC_SEQ_CST)

(The __extension__ is for the GNU C statement-expression, where x = {foo; bar;} takes the value of bar .)

So none of this actually requires that the pointer type has _Atomic .

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