2

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?

sneg
  • 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 Answers2

3

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.

CashCow
  • 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
  • Fair enough. – sehe Apr 09 '15 at 08:37
2

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.

Lingxi
  • 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