Здравствуйте, MaximE, Вы писали:
ME>Гарантируется. После вызова "непрозрачной" ф-ции компилятор будет перечитывать значения всех переменных из памяти. В противном случае даже single threaded код работать не будет.
Ну, положим, не совсем всех. Если это локальная переменная, адрес которой нигде "налево" не "утекал", то её вполне можно заховать и в регистре.
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Здравствуйте, Seriously Serious, Вы писали:
SS>А если ВСЕ функции станут прозрачными и компилятор будет ВСЁ держать в регистрах?
Во-первых, из "прозрачности" ещё не следует, что можно "всё держать в регистрах". "Прозрачность", то есть доступность для компилятора тела данной функции, может позволить компилятору сделать вывод о том, какие объекты подвергаются модификации при её вызове, а какие — нет. А может и не позволить.
Во-вторых, тогда барьеры (и многопоточность вообще) станут просто невозможны.
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Mr. None wrote:
> ME>volatile не имеет никакого отношения к multithreading, поэтому его применение в этой ситуации не только бесполезно, но может быть и вредно, так как с volatile компилятор не сможет соптимизировтать доступ к этой переменной. Но если один из потоков изменяет переменную, синхронизация при помощи мютексов обязательна. > > Так надоело по крупицам вылавливать информацию о volatile и multithreading`ге и некоторых других особенностях плюсов, связанных с этим... Максим, если у вас богатый опыт в этом вопросе, может наконец-то статью напишете, где изложите все свои знания насчёт этих вопросов? Интересно было бы почитать...
К сожалению, опыт у меня не большой и очень узкий, и к разработке компиляторов и моделей памяти я не причастен.
Чему могу научить — так это пользоваться google'ом для поиска информации.
eao197 wrote:
> ... Поэтому еще раз проясню свою позицию: я хочу увидеть реальные примеры (из реальных, а не тестовых примеров), когда использовались примитивы синхронизации, но приложение все равно работало не правильно до тех пор, пока не было использовано volatile. При этом меня не интересуют ни обработчики аппаратных прерываний, ни работа с железом через отображаемые в память порты ввода/вывода. > > Прошу не приводить примеров, когда компилятору специальными ключами явно указывали, что ни одна функция не имеет побочных эффектов. Применение такого ключа в многопоточной программе, ИМХО, является проявлением излишнего оптимизма программиста. Кроме того, такой пример я уже видел. Может есть что-то еще?
Andrew S wrote:
> ME>Конечно, защитников volatile это не убедит, т.к. они скажут, что в ms знали особенности компилятора и нужные ключи компиляции, когда они компилировали ф-ции EnterCriticalSection et al. > > А что на нее глядеть? Она пользуется извне только для отладочных целей (соотв, когда никакой оптимизации и нет).
Код ф-ций EnterCriticalSection et al компилировался с этим определением ст-ры.
achp wrote:
> Здравствуйте, MaximE, Вы писали: > > ME>Гарантируется. После вызова "непрозрачной" ф-ции компилятор будет перечитывать значения всех переменных из памяти. В противном случае даже single threaded код работать не будет. > > Ну, положим, не совсем всех. Если это локальная переменная, адрес которой нигде "налево" не "утекал", то её вполне можно заховать и в регистре.
Он может утечь не явно.
("Непрозрачная") ф-ция может взять адрес возврата, по .pdb файлу определить, что это за вызывающая ф-ция, получить адрес ее фрейма и пробежаться по ее переменным и аргументам — no big deal.
achp wrote:
> Здравствуйте, Seriously Serious, Вы писали: > > SS>А если ВСЕ функции станут прозрачными и компилятор будет ВСЁ держать в регистрах? > > Во-первых, из "прозрачности" ещё не следует, что можно "всё держать в регистрах". "Прозрачность", то есть доступность для компилятора тела данной функции, может позволить компилятору сделать вывод о том, какие объекты подвергаются модификации при её вызове, а какие — нет. А может и не позволить. > > Во-вторых, тогда барьеры (и многопоточность вообще) станут просто невозможны.
Еще примерчик. Любая "непрозрачная" ф-ция может изменить errno. errno не объявлен volatile.
>> >> А что на нее глядеть? Она пользуется извне только для отладочных целей (соотв, когда никакой оптимизации и нет).
ME>Код ф-ций EnterCriticalSection et al компилировался с этим определением ст-ры.
Это заявление сделано на основании анализа исходников, доступных в сети, или же просто домыслы?
Здравствуйте, MaximE, Вы писали:
E>>Надо отдать должное реализации этих функций: если секция не захвачена другим потоком — объекты синхронизации не задействуются, все выливается только в вызовы InterlockedXXX.
ME> LONG LockCount; ME> LONG RecursionCount;
ME>Каунтеры не объявлены как volatile.
А необязательно. Cache cogerency в x86 имеется, для работы с этими счетчиками в NTDLL используются lock-префиксы (в базовой версии DLL там nop'ы, в MP вставляются lock'и). На Alpha/PPC, соответственно, используются более другие способы.
Вообще, какой смысл так упираться, пытаясь доказать ненужность volatile вообще, но почему-то посредством исключительно частных случаев?
eao197 wrote:
> Шутки-шутками, но допустим, я захотел, чтобы моя программа использовала мою функцию strlen. Я не описываю ее прототипа, т.к. он определен в <cstring>, просто прилинковываю к программе еще один obj или lib. Но задачей моей strlen, кроме основной работы, может быть, скажем сбор статистики. Или strlen помещает последнюю вычесленную длину в глобальную переменную, чтобы она была доступна без повторного обращения к strlen. Или кэширует адреса строк и их длины для того, чтобы повторно не вычислять длину той же самой строки. Для этого моя strlen модифицирует какие-либо глобальные данные. Которые могут быть определены даже в другой lib-е. Так вот мне интересно, имеет ли право компилятор, встретив где-то в коде strlen посчитать, что он все знает про эту функцию (она же из стандартной библиотеки) и оптимизировать все, что находится вокруг нее? Причем меня волнует компилятор, который, пока, делает основную оптимизацию, а не линкер, который-то явно будет знать, что strlen не стандартная. > > Пример с strlen может быть и притянут с потолка. Но почему такого не может быть с malloc/free/realloc? Ведь предоставление своих версий глобальных new и delete является распространенной практикой.
Объявление/определение функции из стандартной библиотеки С, например strlen, в глобальном или ::std неймспейсах с внешней компоновкой приводит к ub. Это значит что можно создать strlen только либо в своем неймспейсе, либо локальную, либо статическую (с внутренней компоновкой).
В 17.4.3 вообще куча страшилок, но new/delete и некоторые другие специально разрешено переопределять.
Здравствуйте, MaximE, Вы писали:
ME>Он может утечь не явно.
ME>("Непрозрачная") ф-ция может взять адрес возврата, по .pdb файлу определить, что это за вызывающая ф-ция, получить адрес ее фрейма и пробежаться по ее переменным и аргументам — no big deal.
Это уже мошенничество. Если автор такое делает, то это из той же оперы, что и "assume no aliasing".
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Здравствуйте, eao197, Вы писали:
E>имеет ли право компилятор, встретив где-то в коде strlen посчитать, что он все знает про эту функцию (она же из стандартной библиотеки) и оптимизировать все, что находится вокруг нее?
Сам по себе — конечно, нет. Но многие компиляторы имеют intrinsic-версии распространенных коротких функций, и strlen часто в их числе. Тогда вместо вызова генерируется инлайновый код. Чтобы подменить такую функцию, надо сказать компилятору, что такой замены делать не нужно. Для VC++ это #pragma function.
Здравствуйте, achp, Вы писали:
A>Во-первых, из "прозрачности" ещё не следует, что можно "всё держать в регистрах". "Прозрачность", то есть доступность для компилятора тела данной функции, может позволить компилятору сделать вывод о том, какие объекты подвергаются модификации при её вызове, а какие — нет. А может и не позволить.
В каких случаях?
A>Во-вторых, тогда барьеры (и многопоточность вообще) станут просто невозможны.
Вот я и об этом.
Здравствуйте, MaximE, Вы писали:
ME>("Непрозрачная") ф-ция может взять адрес возврата, по .pdb файлу определить, что это за вызывающая ф-ция, получить адрес ее фрейма и пробежаться по ее переменным и аргументам — no big deal.
Тогда можно и проще — скастить функцию в указатель на другой прототип, вызвать — и нехай компилятор разгребает то, что в итоге получится
Andrew S wrote:
> ME>Еще примерчик. Любая "непрозрачная" ф-ция может изменить errno. errno не объявлен volatile. > > Потому что для каждого потока он свой
Да, это сакральное занание доступно единицам (в Линукс при многопоточности это вообще макрос вызова ф-ции).
Я это привел к тому, что после вызова непрозрачных ф-ций компилятор будет перечитвать значение этой переменной, хотя она не объявлена volatile. (безотносительно к многопоточности)
emusic wrote:
> Здравствуйте, MaximE, Вы писали: > > ME>Любая "непрозрачная" ф-ция может изменить errno. errno не объявлен volatile. > > Он внешний следовательно, компилятору принципиально не может быть известно количество желающих его модифицировать, и оптимизации он никак не подлежит.
Мы все еще ждем от тебя примеров кода, подтверждающие, что при использовании синхронизации нужен еще и volatile.