Является ли оператор ostream << в libstdС++ потоком-враждебным?
ostream
оператор <<
использует num_put::put()
для форматирования чисел. Я пытаюсь выполнить код. Я привяжусь к файлам OSX, но похожие файлы появятся на некоторых других системах, на которые я смотрел. Мне кажется, что num_put::put()
вызывает num_put::do_put()
, который вызывает
num_put::_M_insert_float()
, который calls __convert_from_v()
:
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/c++locale.h
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/locale_facets.tcc
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-60/include/c++/4.2.1/bits/locale_facets.h
__convert_from_v()
проверяет текущую глобальную локаль, и если она отличается от "C" , тогда она вызывает setlocale()
, чтобы установить глобальную локальу на "C" , затем использует vsnprintf()
для форматирования номера, а затем вызывает setlocale()
снова, чтобы вернуться к старой локали.
Так как setlocale()
влияет на все потоки, кажется, что вызов ostream
operator <<
с числом с плавающей запятой является небезопасным в многопоточном приложении, которое имеет глобальную локаль, установленную на что-то другое, чем "C" . Но это было бы очень странно, так что мне не хватает? Спасибо!
Ответы
Ответ 1
Последний проект (N3936) специально предупреждает об этом:
§ 18.10
6 Вызов функции setlocale может привести к гонке данных с другие вызовы функции setlocale или вызовы функций, которые зависят от текущего языкового стандарта. Реализация должна вести себя как если бы никакая функция библиотеки, отличная от locale:: global(), вызывала setlocale.
Более поздние версии GCC ограничивают вызов LC_NUMERIC
вместо LC_ALL
, и если вы используете glibc > 2.2, реализация полностью устраняет проблему, вызывая uselocale
, которая только модифицирует текущий поток (не очень много используется для вы на OSX, я думаю...).
Изменить: я лучше посмотрел на источник
Хотя общая модель локали может возникнуть, если функция, зависящая от языка C, вызывается из другого потока, а __convert_from_v
или другая функция изменяет локаль C, единственный поддерживаемый языковой стандарт для стандартной модели локали - "C"
(это локаль, установленная во время запуска), поэтому это не проблема, если в общую модель не добавлена поддержка других локалей.
Единственный раз, когда это может быть проблемой, - если gcc построен с моделью gnu locale, а glibc - <= 2.2, что не произойдет в OSX.