I am actually failing to find an answer to this question in boost documentation. I am being a bit paranoid about using atof
in a multi-threaded environment, so one suggestion was to replace the call with lexical_cast
. Is lexical_cast
thread-safe?

- 2,088
- 4
- 19
- 23
-
Out of interest, why are you paranoid about the thread safety/re-entrancy of atof? I can't think of any reason to use static storage, or any interaction with global state except the locale. Is it that? – Useless Apr 08 '15 at 10:20
-
yes, `setlocale` problem – sneg Apr 08 '15 at 10:32
-
atof and sprintf are generally not suitable for production code, as they are prone to breakage on `.` versus `,`. This is rather unfortunate as it's hard to write these yourself. – MSalters Apr 09 '15 at 09:35
2 Answers
Yes, boost::lexical_cast
does not modify the input string in any way and produces a new output if run on the same string from multiple threads.
It creates a stringstream
which in itself is not thread-safe, i.e. cannot be shared between threads without synchronisation, but would use a different stringstream
object in each thread.
The issue I have with lexical_cast
which is why I avoid using it is the total uselessness of the exception it throws (bad_cast with no context). However that is a separate issue, not thread-safety.
Another issue (limitation) with lexical_cast is that it will only use the C locale (classic). So if you have your own facet, maybe for date-times, and you want to use lexical_cast on it, you may be tempted to modify the classic locale as a workaround, and that is where it will stop being thread-safe unless it is done right at the start.
In reality, if you are parsing a file you would probably be better off using either boost::spirit
if it has a specific grammar or boost::serialize
or even regular istream. In fact boost::lexical_cast
would be highly inefficient for this purpose as it creates a new stream for every token.

- 30,981
- 5
- 61
- 92
-
Boost has had [try_lexical_convert](http://www.boost.org/doc/libs/1_57_0/doc/html/boost_lexical_cast/synopsis.html#boost_lexical_cast.synopsis.try_lexical_convert) since 1.56 – sehe Apr 08 '15 at 17:11
-
I don't mind it throwing, but the exception text should include the symbol being converted and the type to which you were trying to convert it. A good "wrapper" though, that might use try_lexical_convert would pass in file and line (not __FILE__ and __LINE__ but the filename or stream name being parsed and the line number in that stream) and would output that too in the error message. – CashCow Apr 09 '15 at 08:13
-
Interestingly, how would you include the value in a message if conversion to string failed? Also, streams have no line number information, generically. So the things you mention are GoodThings but arguably reasonably absent from a library this generic. Boost Lexicalcast is a building block IMO – sehe Apr 09 '15 at 08:15
-
I'm not sure how conversion to string can fail at run-time. Either a value has a stream overload or not. Normally one wouldn't not implement operator<< to leave a fail state. – CashCow Apr 09 '15 at 08:34
-
Concurrent calls to lexical_cast
are safe. But pay attention that it depends on (at least for my installed version of Boost) the currently installed C++ locale. Access to the installed C++ (as well as C) locale should be synchronized manually by the user. See the Data races section here. So, for example, concurrent calls to lexical_cast
and std::locale::global
are unsafe. Despite this, it is considered bad practice to change the installed C/C++ locale other than at program startup.

- 14,579
- 2
- 37
- 93
-
Aha! Interesting, so actually my worries about `atof` aren't going to be solved by `lexical_cast`. :) Thank you. – sneg Apr 08 '15 at 10:42
-
Better implement your own. Few format-related facilities in the standard library are independent of the global C or C++ locale. – Lingxi Apr 08 '15 at 10:45
-
Not only standard library, boost as well, even spirit uses locale - hard to avoid really... – Nim Apr 08 '15 at 12:01