Инициализация atomic_flag

У меня есть struct, назовем его struct foo, к которому я хотел бы добавить переменную atomic_flag. До сих пор я callocизменял структуру, учитывая, что в основном она должна быть инициализирована нулем. Как мне инициализировать элемент atomic_flag?

struct foo{
    //...
    atomic_flag a_flg;
    //...
};
struct foo *foop = calloc(1,sizeof *foop);
if(!foop) return -1;

//should I be giving up `calloc` (/`malloc`+`memset`) in favor of `malloc`+this?
*foop = (struct foo){ ATOMIC_FLAG_INIT };

Редактировать:

Я обнаружил, что это связано с DR#421 от Jens Gustedt, который предлагает сделать нулевую/инициализацию по умолчанию только для atomic_flags. Как я могу узнать, был ли он принят?


person PSkocik    schedule 02.04.2019    source источник
comment
Обратите внимание, что для инициализации *foop = ... вам все равно нужно сделать точку foop где-то действительной, и что вам нужно явно указать инициализацию для всех членов структуры.   -  person Some programmer dude    schedule 02.04.2019


Ответы (1)


Стандарт C11 говорит о 7.17.8p4:

atomic_flag, который явно не инициализирован с помощью ATOMIC_FLAG_INIT, изначально находится в неопределенном состоянии.

И нет никаких указаний на тип atomic_flag или его содержимое, так что обнуление здесь не поможет.

Вам нужно будет инициализировать его до известного состояния либо с помощью макроса, либо с помощью функций atomic_flag_clear или atomic_flag_clear_explicit.

person Acorn    schedule 02.04.2019
comment
Спасибо. Я тоже так читаю, но мне это кажется очень неуклюжим. Я нашел этот DR#421 Jens Gustedt, который рекомендует, чтобы нулевая инициализация работала только для атомарных флагов, но не похоже, что это было одобрено (или было?). - person PSkocik; 02.04.2019
comment
@PSkocik: на практике, вероятно, в любой реальной реализации (и, безусловно, во всех основных компиляторах x86 и ARM, таких как gcc/clang/MSVC/ICC), это действительно работает. atomic_flag требуется, чтобы не было блокировок, и в обычных реализациях это всего лишь 1-байтовый bool. Это безопасно для инициализации нулями. Конечно, это на процессорах, которые поддерживают атомарные операции без блокировки для других типов, по крайней мере, до ширины регистра. (Проверьте ассемблер, чтобы увидеть, как он его использует, если вы когда-либо не уверены, что все нули являются допустимым представлением объекта для atomic_flag.) - person Peter Cordes; 02.04.2019
comment
@PSkocik, нет, к сожалению, он не был одобрен, был одобрен только тот, что для ATOMIC_VAR_INIT. Когда мы обсуждали это в то время, я узнал, что некоторые платформы, похоже, должны использовать другое значение для инициализации, в зависимости от имеющихся у них атомарных примитивов. А инициализация данных malloced составным литералом — это хорошая привычка, поэтому я бы посоветовал вам сохранить ее в таком виде. - person Jens Gustedt; 02.04.2019
comment
@JensGustedt Спасибо! - person PSkocik; 02.04.2019
comment
Похоже, atomic_flag_clear_explicit(&foop->a_flg,memory_order_relaxed) должен быть оптимальным способом сделать это. - person PSkocik; 02.04.2019
comment
@JensGustedt: Какая часть кода C когда-либо будет задействована для работы на платформах, которые не могут обеспечить нормальную инициализацию без дополнительных затрат? Какой недостаток был бы в наличии стандартных макросов, которые указывали бы на такие вещи, как, будет ли нормальная инициализация работать с атомарными типами, будут ли указатели в all-bits-zero (например, полученные от calloc) изначально нулевыми, будут ли операции с целыми числами, кроме деления/остатка всегда свободны от побочных эффектов и т.д.? - person supercat; 05.04.2019
comment
@supercat, почему ты спрашиваешь меня об этом? Это определенно не было моим решением оставить все как есть. - person Jens Gustedt; 06.04.2019
comment
@JensGustedt: Мне интересно, есть ли у вас какое-либо представление о менталитете некоторых членов Комитета, которые, кажется, выступают против любых усилий по определению поведения кода, использующего общие функции платформы, при работе на платформах, поддерживающих такие функции. - person supercat; 07.04.2019
comment
@supercat, на это есть как минимум три ответа. (1) Ходя на заседания комитета, я многое узнал о том, как я живу в довольно ограниченном пузыре, существует множество платформ C со своими собственными ограничениями, о которых я не знал. (2) Это не определено в хорошем смысле этого слова, поэтому реализации или другие стандарты (например, POSIX) могут делать с этим все, что захотят. (3) Комитет С и его восприятие вещей со временем эволюционируют, так что сегодня возможно даже изменить этот конкретный аспект. - person Jens Gustedt; 07.04.2019
comment
@JensGustedt: C можно было бы сделать более полезным на как распространенных, так и на необычных платформах, если бы он сделал необязательными функции, которые можно легко поддерживать на некоторых платформах и дорого на других, но требовало, чтобы реализации предопределяли макросы или встроенные функции, поэтому программы может отказаться от компиляции для реализаций, которые их не поддерживают. Выбор функций для поддержки будет вопросом QoI для реализаций, а выбор функций, которые потребуются, может быть проблемой QoI для программ, но программа, которая тестирует все функции и гарантирует, что она нужна... - person supercat; 07.04.2019
comment
... и может дать сбой в некоторых реализациях, но не будет вызывать UB ни в одной из них. Говоря, например, что реализации могут использовать любой формат для хранения целых чисел со знаком или без знака и не должны использовать модуль степени двойки для типов без знака, но что реализации должны определять макросы, указывающие их целочисленную семантику, сделало бы реализацию практичной на 36-битном Univac, который не мог поддерживать C99, но предоставлял бы все преимущества, которые можно было бы получить от обязательного использования целых чисел с дополнением до двух. - person supercat; 07.04.2019