Могу ли я применить ключевое слово `_Atomic` C11 к типам перечислений? - PullRequest
4 голосов
/ 05 марта 2019

Если у меня есть тип

enum foo {
    FOO,
    BAR,
    BAZ,
};

Могу ли я объявить атомарную версию этого типа, как

_Atomic(enum foo);

или я должен использовать, например, atomic_int и приведите результат atomic_load()?

Следующая программа компилируется без предупреждений:

#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;
}

но так же

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

enum foo {
    FOO,
    BAR,
    BAZ,
};

int main(void) {
    enum foo foo;

    atomic_store(&foo, BAR);

    enum foo val = atomic_load(&foo);

    printf("%u\n", val);

    return 0;
}

Ответы [ 2 ]

3 голосов
/ 06 марта 2019

Да, это законно. Кстати, вам на самом деле не нужны парены, _Atomic enum foo foo; эквивалентно.

_Atomic работает как другие классификаторы типов, например const и volatile.


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

- ошибка clang . error: address argument to atomic operation must be a pointer to _Atomic type ('enum foo *' invalid). (Из Проводник компилятора Godbolt ).


Это просто странная реализация GCC, которую он компилирует даже без предупреждения, даже на -Wall. Это, вероятно, следует изменить ...

Атомные встроенные элементы GCC подобно void __atomic_store_n (type *ptr, type val, int memorder) принимают указатель на простой тип, не требуя _Atomic.

C ++ 11 <atomic> использует эти встроенные функции. Аналогично, в GCC C11 stdatomic.h используется

#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)

(__extension__ для выражения-выражения GNU C, где x = {foo; bar;} принимает значение bar.)

Так что на самом деле ничего этого не требует, чтобы тип указателя имел _Atomic.

3 голосов
/ 05 марта 2019

Да, все типы данных могут быть атомарными, и нет необходимости использовать атомарные универсальные функции для них. Тогда все операции с таким объектом являются атомарными.

Для вашего второго примера странно, что ваш компилятор не выдает предупреждение. Использование неатомарного для атомарного действия является нарушением ограничения, поэтому компилятор должен дать вам диагностику.

...