Re[5]: volatile у переменной класса
От: emusic Франция https://software.muzychenko.net/ru
Дата: 10.01.05 18:43
Оценка: -1
Здравствуйте, MaximE, Вы писали:

ME>Использование любого примитива синхронизации в POSIX и win32 является вызовом ф-ции. Вызов ф-ции — sequence point. Если у тебя уже есть sequence points вокруг защищаемых данных, зачем тогда volatile?


Абсолютной необходимости в примитивах синхронизации нет. Если один процесс записывает значения в некоторую ячейку общей памяти, а другой их оттуда читает, и доступ к ячейке на всех поддерживаемых платформах гарантированно атомарный — какой смысл в дополнительных примитивах? Достаточно лишь указать компилятору, что с объектом нужно вести себя более аккуратно, что и делает volatile.

Например, в Windows MME в описателе звукового буфера есть флажок WHDR_DONE, означающий, что драйвер завершил обработку буфера. Можно, конечно, заказать специфическое уведомление, но можно и просто опрашивать этот флажок время от времени. Что запретит компилятору перечитывать его из памяти, если весь описатель не будет объявлен с volatile?

>> Функции используются только для изменения volatile-переменных. Чтение их значений может происходить в параллельных потоках без каких-либо функций.


ME>Это так только по случайному стечению обстоятельств на IA32.


Почему по случайному? Еще не так давно подавляющее большинство платформ работало именно так.

ME> volatile имеет влияние лишь на код, генерируемый компилятором. На переупорядочивание инструкций процессором он не имеет никакого влияния.


А зачем? Назначение volatile — влиять именно на код. Соответственно, процессор своими средствами обеспечивает определенность вычислений.

ME> Именно по этой причине на всех современных RISC процессорах, а также на IA64, тебе придется использовать барьеры памяти чтобы прочитать актуальное значение.


Именно этим может и заниматься компилятор, обрабатывая volatile.

>> ME> После sequence points, компилятор обязан перечитывать значения переменных из памяти, неважно, volatile ли, const ли, или это переменная без cv-квалификатора

>>
>> С чего бы он вдруг стал обязан? Компилятор обязан лишь обеспечить последовательное выполнение заданных действий в рамках одного потока исполнения. Для взаимодействия с "внешними" процессами и существует volatile.

ME>С тем, что состояние программы после sequence point is indeterminate.


Из чего это следует?

>> Простейший пример:

>>
>>
>> void f (int &a, int &b) {
>>   if (!a) {
>>     b = a;
>>   }
>> }
>>

>>
>> При включенной оптимизации многие компиляторы (например, VC++ 6.0) сгенерируют только один опрос переменной a — в проверке условия. Для присваивания будет сгенерирован явный нуль.

ME>Здесь именно простейший пример: нет вызовов ф-ций, компилятор видит весь контекст и плевал на sequence points. Добавим вызов ф-ции.


А давай вместо вызова функции добавим модификацию объекта — например, введем переменную c и сделаем ей инкремент:

  int c = b;

  if (!a) {

    c++;

    b = a;

  }

  return c;


Модификация объекта, согласно стандарту, есть sequence point. А по соглашениям MS любой оператор также является SP, и условие в if является ею же. Однако это не мешает компилятору по-прежнему использовать константу-нуль.

Я вообще не понимаю, почему ты относишь значение объекта к side effects.

ME>Мой point: volatile бесполезен (и даже вреден) для multithreading, барьеры нужны по-любому.


Где в C++ барьеры? Их там нет — они реализуются средствами платформы. Наличие барьеров без volatile не гарантирует правильной работы. Наличие volatile без барьеров — тоже не гарантирует. volatile обеспечивает поддержку со стороны языка, барьер — со стороны аппаратуры. Зачем, по-твоему, вообще существует volatile? Именно для урезания вольностей оптимизатора в отношении состояния объекта.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.