2 Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef DCPOMATIC_SAFE_STRINGSTREAM_H
21 #define DCPOMATIC_SAFE_STRINGSTREAM_H
23 #include <boost/thread/mutex.hpp>
25 /* I've not been able to reproduce it, but there have been reports that DCP-o-matic crashes
26 * on OS X with two simultaneous backtraces that look like this:
28 * 0 libSystem.B.dylib 0x00007fff84ebe264 __numeric_load_locale + 125
29 * 1 libSystem.B.dylib 0x00007fff84e2aac4 loadlocale + 323
30 * 2 libstdc++.6.dylib 0x00007fff8976ba69 std::__convert_from_v(int* const&, char*, int, char const*, ...) + 199
31 * 3 libstdc++.6.dylib 0x00007fff8974e99b std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char,
32 std::char_traits<char> > >::_M_insert_float<double>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, double) const + 199
33 * 4 libstdc++.6.dylib 0x00007fff8974ebc0 std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> >
34 >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, double) const + 28
35 * 5 libstdc++.6.dylib 0x00007fff897566a2 std::ostream& std::ostream::_M_insert<double>(double) + 178
36 * 6 libdcpomatic.dylib 0x0000000100331e21 StringPrivate::Composition& StringPrivate::Composition::arg<float>(float const&) + 33
38 * in two different threads. I'm assuming that for some bizarre reason it is unsafe to use two separate stringstream
39 * objects in different threads on OS X. This is a hack to work around it.
42 class SafeStringStream
48 SafeStringStream (std::string s)
53 std::ostream& operator<< (T val)
55 boost::mutex::scoped_lock lm (_mutex);
61 std::istream& operator>> (T& val)
63 boost::mutex::scoped_lock lm (_mutex);
68 std::string str () const {
69 return _stream.str ();
72 void str (std::string const & s) {
76 void imbue (std::locale const & loc)
78 boost::mutex::scoped_lock lm (_mutex);
92 void precision (int p)
94 _stream.precision (p);
99 return _stream.good ();
102 std::string getline ()
104 boost::mutex::scoped_lock lm (_mutex);
106 std::getline (_stream, s);
110 void setf (std::ios_base::fmtflags flags, std::ios_base::fmtflags mask)
112 _stream.setf (flags, mask);
116 static boost::mutex _mutex;
117 std::stringstream _stream;