Увеличение volatile в C ++ 20 с операциями с volatile устарело

В C ++ 20 исключены некоторые операции с типами volatile (после P1152).

Следующий код, действовавший до C ++ 20:

void busyLoop(std::size_t count) {
  for (volatile size_t counter = 0; counter < count; ++counter);
}

теперь генерирует предупреждение об устаревании:

warning: '++' expression of 'volatile'-qualified type is deprecated [-Wvolatile]

Изменение ++ на += или на counter = counter + 1 не помогает, поскольку проблема, похоже, связана с вычислением нового значения на основе изменчивого типа.

Как можно привести приведенный выше код в соответствие с новыми правилами C ++ 20?


person Amir Kirsh    schedule 01.01.2021    source источник
comment
Вы проверили, что volatile действительно нужен для начала? В свое время я видел (и сделал) множество циклов «занято-ожидание», но никогда не видел (или не нуждался в использовании) volatile.   -  person Some programmer dude    schedule 01.01.2021
comment
@Someprogrammerdude - это всего лишь минимальный пример, показывающий устаревание, выполненное в C ++ 20. В любом случае, специально для этого случая: без volatile = 2µs, с volatile = 27779µs, также есть изменения в сгенерированная сборка в проводнике компилятора, хотя время меньше по неизвестной причине.   -  person Amir Kirsh    schedule 01.01.2021
comment
С точки зрения стандартов, настраивать нечего. Устарело означает, что может исчезнуть в будущем. Код, который был действителен до прекращения поддержки, по-прежнему действителен, и его значение не изменилось.   -  person Pete Becker    schedule 01.01.2021


Ответы (3)


Смысл отказа от этих операций состоит в том, чтобы прояснить, что переменные volatile никоим образом не являются атомарными и не следует ожидать, что ими можно будет манипулировать атомарно. Следовательно, для любого фактического кода, использующего volatile, вам необходимо прочитать значение в локальном, управлять этой локальной копией, а затем записать значение обратно в значение volatile.

Этот шаблон доступа предназначен для имитации того, что комитет надеется кодифицировать в функциональном интерфейсе, который (возможно?) В какой-то момент полностью заменит volatile. То есть volatile становится способом доступа к адресу памяти во время загрузки и сохранения; это не было бы внутренним свойством объекта.

person Nicol Bolas    schedule 01.01.2021

Хотя увеличение volatile, как видно из вопроса, устарело в C ++ 20, вы можете увеличить энергонезависимый тип и присвоить результат обратно типу volatile.

Следующий код действителен в C ++ 20:

void busyLoop(size_t count) {
  size_t i = 0;
  for ([[maybe_unused]]volatile size_t counter = 0; i < count; counter = i, ++i);
}
person Amir Kirsh    schedule 01.01.2021
comment
Это заставляет counter получить неправильное значение. То есть он получает значение, отличное от того, что было бы в исходном коде. Если volatile по какой-то причине действительно имеет значение в этом примере, то получатель значения volatile будет получать значения в неправильном порядке. - person Nicol Bolas; 01.01.2021
comment
@NicolBolas исправлено, спасибо. - person Amir Kirsh; 07.01.2021

counter=counter+1 правильный (в той мере, в которой этот код вообще желателен). Предупреждение для этого - это ошибка GCC: предполагается, что он будет предупреждать только о таких вещах, как reg=vol=1;, которые могут присвоить или не присвоить 1 reg. (Даже написание void(counter=counter+1) не помогает.)

person Davis Herring    schedule 02.01.2021
comment
Попытка выполнить поиск в bugzilla gcc не смогла найти, была ли в нем отправлена ​​ошибка. Вы знаете, есть ли уже обнаруженная ошибка, или мне следует ее открыть? - person Amir Kirsh; 07.01.2021
comment
@AmirKirsh: Я не смотрел. Я знаю только, что это относится к делу for; он не предупреждает об отдельном заявлении. Предположительно, он не может распознать этот контекст как выражение отброшенного значения. - person Davis Herring; 07.01.2021