2 Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
21 #ifndef DCPOMATIC_SAFE_STRINGSTREAM_H
22 #define DCPOMATIC_SAFE_STRINGSTREAM_H
24 #include <boost/thread/mutex.hpp>
26 /* I've not been able to reproduce it, but there have been reports that DCP-o-matic crashes
27 * on OS X with two simultaneous backtraces that look like this:
29 * 0 libSystem.B.dylib 0x00007fff84ebe264 __numeric_load_locale + 125
30 * 1 libSystem.B.dylib 0x00007fff84e2aac4 loadlocale + 323
31 * 2 libstdc++.6.dylib 0x00007fff8976ba69 std::__convert_from_v(int* const&, char*, int, char const*, ...) + 199
32 * 3 libstdc++.6.dylib 0x00007fff8974e99b std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char,
33 std::char_traits<char> > >::_M_insert_float<double>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, double) const + 199
34 * 4 libstdc++.6.dylib 0x00007fff8974ebc0 std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> >
35 >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, double) const + 28
36 * 5 libstdc++.6.dylib 0x00007fff897566a2 std::ostream& std::ostream::_M_insert<double>(double) + 178
37 * 6 libdcpomatic.dylib 0x0000000100331e21 StringPrivate::Composition& StringPrivate::Composition::arg<float>(float const&) + 33
39 * in two different threads. I'm assuming that for some bizarre reason it is unsafe to use two separate stringstream
40 * objects in different threads on OS X. This is a hack to work around it.
43 class SafeStringStream
49 SafeStringStream (std::string s)
54 std::ostream& operator<< (T val)
56 boost::mutex::scoped_lock lm (_mutex);
62 std::istream& operator>> (T& val)
64 boost::mutex::scoped_lock lm (_mutex);
69 std::string str () const {
70 return _stream.str ();
73 void str (std::string const & s) {
77 void imbue (std::locale const & loc)
79 boost::mutex::scoped_lock lm (_mutex);
93 void precision (int p)
95 _stream.precision (p);
100 return _stream.good ();
103 std::string getline ()
105 boost::mutex::scoped_lock lm (_mutex);
107 std::getline (_stream, s);
111 void setf (std::ios_base::fmtflags flags, std::ios_base::fmtflags mask)
113 _stream.setf (flags, mask);
117 static boost::mutex _mutex;
118 std::stringstream _stream;