Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is ostream operator<< in libstdc++ thread-hostile?

ostream operator<< uses num_put::put() for number formatting. I'm trying to follow the code. I'll link to OSX files but similar files appear on some other systems I looked at. It seems to me that num_put::put() calls num_put::do_put(), which calls
num_put::_M_insert_float(), which 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() checks the current global locale, and if it's different from "C" then it calls setlocale() to set the global locale to "C", then uses vsnprintf() to format the number, then calls setlocale() again to revert to the old locale.

Since setlocale() affects all threads, it would seem that calling ostream operator<< with a floating point number is unsafe in a multi-threaded application which has the global locale set to something else than "C". But that would be very strange, so what am I missing? Thanks!

like image 968
Aleksander Fedoryński Avatar asked Mar 31 '14 04:03

Aleksander Fedoryński


1 Answers

The latest draft (N3936) specifically warns against this:

§ 18.10

6 A call to the setlocale function may introduce a data race with other calls to the setlocale function or with calls to functions that are affected by the current C locale. The implementation shall behave as if no library function other than locale::global() calls the setlocale function.

More recent versions of GCC limit the call to LC_NUMERIC instead of LC_ALL, and if you use glibc > 2.2 the implementation avoids the problem altogether by calling uselocale which only modifies the current thread (not much use for you on OSX I guess…).

Edit: I had a better look at the source

Although issues could potentially occur with the generic locale model if a function that depends on the C locale is called from another thread while __convert_from_v or another function modifies the C locale, the only supported locale for the generic locale model is "C" (which is the locale set during startup), so this isn't an issue unless support for other locales is added to the generic model.

The only time this could be an issue is if gcc is built with the gnu locale model and glibc is <= 2.2, which isn't going to happen on OSX.

like image 155
user657267 Avatar answered Nov 19 '22 10:11

user657267