From: maier Date: Thu, 1 Aug 2013 23:10:03 +0000 (+0000) Subject: Workaround for a problem in LogStream: X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e5e84e46b7f36b6ba40a60ca60401d2a5cc23ff;p=dealii-svn.git Workaround for a problem in LogStream: It is invalid to test for std::flush or std::endl with function pointers, std::ostream & (* const p_flush) (std::ostream &) = &std::flush; p == p_flush ? ..., as there could be multiple versions of of it. And in fact, LLVM's libc++ implements std::flush and std::endl in a way that every shared library and executable has its local copy. Fix this by implementing a custom streambuf class that queries this sort of information. git-svn-id: https://svn.dealii.org/branches/branch_port_to_libcxx@30215 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/source/base/logstream.cc b/deal.II/source/base/logstream.cc index ba7f8773f3..e05f28a89b 100644 --- a/deal.II/source/base/logstream.cc +++ b/deal.II/source/base/logstream.cc @@ -137,23 +137,65 @@ LogStream::operator<< (std::ostream& (*p) (std::ostream &)) // Print to the internal stringstream: stream << p; - // Next check whether this is the flush or endl - // manipulator, and if so print out the message. - std::ostream & (* const p_flush) (std::ostream &) = &std::flush; - std::ostream & (* const p_endl) (std::ostream &) = &std::endl; - if (p == p_flush || p == p_endl) + + // This is a bloody hack until LogStream got reimplemented as a proper + // child of std::streambuf (or similar). + // + // The problem is that at this point we would like to know whether an + // std::flush or std::endl has called us, however, there is no way to + // detect this in a sane manner. + // + // The obvious idea to compare function pointers, + // std::ostream & (* const p_flush) (std::ostream &) = &std::flush; + // p == p_flush ? ..., + // is wrong as there doesn't has to be a _single_ std::flush instance... + // there could be multiple of it. And in fact, LLVM's libc++ implements + // std::flush and std::endl in a way that every shared library and + // executable has its local copy... fun... + // + // - Maier, 2013 + + class QueryStreambuf : public std::streambuf + { + // Implement a minimalistic stream buffer that only stores the fact + // whether overflow or sync was called + public: + QueryStreambuf() + : _flushed(false), _newline_written(false) + { + } + bool flushed() { return _flushed; } + bool newline_written() { return _newline_written; } + private: + int_type overflow(int_type ch) + { + _newline_written = true; + return ch; + } + int sync() + { + _flushed = true; + return 0; + } + bool _flushed; + bool _newline_written; + } query_streambuf; + + { + // and initialize an ostream with this streambuf: + std::ostream inject (&query_streambuf); + inject << p; + } + + if (query_streambuf.flushed()) { Threads::Mutex::ScopedLock lock(write_lock); - // Print the line head in case of a newline: + // Print the line head in case of a previous newline: if (at_newline) print_line_head(); - if (p == p_flush) - at_newline = false; - - if (p == p_endl) - at_newline = true; + at_newline = query_streambuf.newline_written(); if (get_prefixes().size() <= std_depth) *std_out << stream.str(); @@ -161,7 +203,7 @@ LogStream::operator<< (std::ostream& (*p) (std::ostream &)) if (file && (get_prefixes().size() <= file_depth)) *file << stream.str() << std::flush; - // Start a new string + // Start a new string: stream.str(""); }