Является ли оператор 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.