]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Let LogStream respect std::flush for writing out content as well
authormaier <maier@0785d39b-7218-0410-832d-ea1e28bc413d>
Wed, 17 Apr 2013 17:37:03 +0000 (17:37 +0000)
committermaier <maier@0785d39b-7218-0410-832d-ea1e28bc413d>
Wed, 17 Apr 2013 17:37:03 +0000 (17:37 +0000)
LogStream (and therefore deallog) now respect std::flush and std::endl to
write out the buffered (thread local) content to console (and file).

git-svn-id: https://svn.dealii.org/trunk@29318 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/doc/news/changes.h
deal.II/include/deal.II/base/logstream.h
deal.II/source/base/logstream.cc

index 0b389615b6a9acd4252385932d6fc5aa76586d6f..772ca58f889c459f9232fb14a6c4b735eddb31e5 100644 (file)
@@ -106,6 +106,12 @@ this function.
 <h3>Specific improvements</h3>
 
 <ol>
+<li> Improved: Logstream (and deallog) now respect std::flush in addition to std::endl
+to write out content to the console/file.
+<br>
+(Matthias Maier, 2013/04/17)
+</li>
+
 <li> New: Functions::FEFieldFunction can now deal with
 parallel::distributed::Triangulation objects.
 <br>
index 2dfba16c7d94bf0e07cb59829e3c894e8c0e207d..2ef7be3fdad427adbed0b361e8148f580c721a2f 100644 (file)
@@ -44,17 +44,23 @@ DEAL_II_NAMESPACE_OPEN
  * </ul>
  *
  * The usual usage of this class is through the pregenerated object
- * <tt>deallog</tt>. Typical steps are
+ * <tt>deallog</tt>. Typical setup steps are:
  * <ul>
- * <li> <tt>deallog.attach(std::ostream)</tt>: write logging information into a file.
  * <li> <tt>deallog.depth_console(n)</tt>: restrict output on screen to outer loops.
- * <li> Before entering a new phase of your program, e.g. a new loop,
- *       <tt>LogStream::Prefix p("loopname")</tt>.
- * <li> <tt>deallog << anything << std::endl;</tt> to write logging information
- *       (Usage of <tt>std::endl</tt> is mandatory!).
- * <li> Destructor of the prefix will pop the prefix text from the stack.
+ * <li> <tt>deallog.attach(std::ostream)</tt>: write logging information into a file.
+ * <li> <tt>deallog.depth_file(n)</tt>: restrict output to file to outer loops.
  * </ul>
  *
+ * Before entering a new phase of your program, e.g. a new loop,
+ * a new prefix can be set via <tt>LogStream::Prefix p("loopname");</tt>.
+ * The destructor of the prefix will pop the prefix text from the stack. 
+ *
+ * Writes via the <tt>&lt;&lt;</tt> operator,
+ * <tt> deallog << "This is a log notice";</tt> will be buffered thread
+ * locally until a <tt>std::flush</tt> or <tt>std::endl</tt> is
+ * encountered, which will trigger a writeout to the console and, if set
+ * up, the log file.
+ *
  * <h3>LogStream and reproducible regression test output</h3>
  *
  * Generating reproducible floating point output for regression tests
@@ -87,53 +93,40 @@ class LogStream : public Subscriptor
 {
 public:
   /**
-   * A subclass allowing for the
-   * safe generation and removal of
-   * prefices.
+   * A subclass allowing for the safe generation and removal of prefices.
    *
-   * Somewhere at the beginning of
-   * a block, create one of these
-   * objects, and it will appear as
-   * a prefix in LogStream output
-   * like @p deallog. At the end of
-   * the block, the prefix will
-   * automatically be removed, when
+   * Somewhere at the beginning of a block, create one of these objects,
+   * and it will appear as a prefix in LogStream output like @p deallog. At
+   * the end of the block, the prefix will automatically be removed, when
    * this object is destroyed.
    *
-   * In other words, the scope of the object so created
-   * determines the lifetime of the prefix. The advantage of
-   * using such an object is that the prefix is removed
-   * whichever way you exit the scope -- by <code>continue</code>,
-   * <code>break</code>, <code>return</code>, <code>throw</code>,
-   * or by simply reaching the closing brace. In all of these
-   * cases, it is not necessary to remember to pop the prefix
-   * manually using LogStream::pop. In this, it works just like
-   * the better known Threads::Mutex::ScopedLock class.
+   * In other words, the scope of the object so created determines the
+   * lifetime of the prefix. The advantage of using such an object is that
+   * the prefix is removed whichever way you exit the scope -- by
+   * <code>continue</code>, <code>break</code>, <code>return</code>,
+   * <code>throw</code>, or by simply reaching the closing brace. In all of
+   * these cases, it is not necessary to remember to pop the prefix
+   * manually using LogStream::pop. In this, it works just like the better
+   * known Threads::Mutex::ScopedLock class.
    */
   class Prefix
   {
   public:
     /**
-     * Set a new prefix for
-     * @p deallog, which will be
-     * removed when the variable
-     * is destroyed .
+     * Set a new prefix for @p deallog, which will be removed when the
+     * variable is destroyed.
      */
     Prefix(const std::string &text);
 
     /**
-     * Set a new prefix for the
-     * given stream, which will
-     * be removed when the
-     * variable is destroyed .
+     * Set a new prefix for the given stream, which will be removed when
+     * the variable is destroyed.
      */
     Prefix(const std::string &text,
           LogStream &stream);
 
     /**
-     * Remove the prefix
-     * associated with this
-     * variable.
+     * Remove the prefix associated with this variable.
      */
     ~Prefix ();
 
@@ -141,305 +134,234 @@ public:
     SmartPointer<LogStream,LogStream::Prefix> stream;
   };
 
+
   /**
-   * Standard constructor, since we
-   * intend to provide an object
-   * <tt>deallog</tt> in the library. Set the
-   * standard output stream to <tt>std::cerr</tt>.
+   * Standard constructor, since we intend to provide an object
+   * <tt>deallog</tt> in the library. Set the standard output stream to
+   * <tt>std::cerr</tt>.
    */
   LogStream ();
 
+
   /**
    * Destructor.
    */
   ~LogStream();
 
+
   /**
-   * Enable output to a second
-   * stream <tt>o</tt>.
+   * Enable output to a second stream <tt>o</tt>.
    */
   void attach (std::ostream &o);
 
+
   /**
-   * Disable output to the second
-   * stream. You may want to call
-   * <tt>close</tt> on the stream that was
-   * previously attached to this object.
+   * Disable output to the second stream. You may want to call
+   * <tt>close</tt> on the stream that was previously attached to this
+   * object.
    */
   void detach ();
 
+
   /**
-   * Setup the logstream for
-   * regression test mode.
+   * Setup the logstream for regression test mode.
    *
-   * This sets the parameters
-   * #double_threshold,
-   * #float_threshold, and #offset
-   * to nonzero values. The exact
-   * values being used have been
-   * determined experimentally and
-   * can be found in the source
-   * code.
+   * This sets the parameters #double_threshold, #float_threshold, and
+   * #offset to nonzero values. The exact values being used have been
+   * determined experimentally and can be found in the source code.
    *
-   * Called with an argument
-   * <tt>false</tt>, switches off
-   * test mode and sets all
-   * involved parameters to zero.
+   * Called with an argument <tt>false</tt>, switches off test mode and
+   * sets all involved parameters to zero.
    */
   void test_mode (bool on=true);
 
+
   /**
    * Gives the default stream (<tt>std_out</tt>).
    */
   std::ostream &get_console ();
 
+
   /**
    * Gives the file stream.
    */
   std::ostream &get_file_stream ();
 
+
   /**
-   * @return true, if file stream
-   * has already been attached.
+   * @return true, if file stream has already been attached.
    */
   bool has_file () const;
 
+
   /**
-   * Reroutes cerr to LogStream.
-   * Works as a switch, turning
-   * logging of <tt>cerr</tt> on
-   * and off alternatingly with
-   * every call.
+   * Reroutes cerr to LogStream. Works as a switch, turning logging of
+   * <tt>cerr</tt> on and off alternatingly with every call.
    */
   void log_cerr ();
 
+
   /**
    * Return the prefix string.
    */
   const std::string &get_prefix () const;
 
+
   /**
-   * Push another prefix on the
-   * stack. Prefixes are
-   * automatically separated by a
-   * colon and there is a double
-   * colon after the last prefix.
+   * Push another prefix on the stack. Prefixes are automatically separated
+   * by a colon and there is a double colon after the last prefix.
    *
-   * A simpler way to add a prefix (without the manual
-   * need to add the corresponding pop()) is to use the
-   * Prefix class.
+   * A simpler way to add a prefix (without the manual need to add the
+   * corresponding pop()) is to use the Prefix class.
    */
   void push (const std::string &text);
 
+
   /**
    * Remove the last prefix added with push().
    */
   void pop ();
 
+
   /**
-   * Maximum number of levels to be
-   * printed on the console. This
-   * function allows to restrict
-   * console output to the upmost
-   * levels of iterations. Only
-   * output with less than <tt>n</tt>
-   * prefixes is printed. By calling
-   * this function with <tt>n=0</tt>, no
-   * console output will be written.
+   * Maximum number of levels to be printed on the console. This function
+   * allows to restrict console output to the upmost levels of iterations.
+   * Only output with less than <tt>n</tt> prefixes is printed. By calling
+   * this function with <tt>n=0</tt>, no console output will be written.
    *
-   * The previous value of this
-   * parameter is returned.
+   * The previous value of this parameter is returned.
    */
   unsigned int depth_console (const unsigned int n);
 
+
   /**
-   * Maximum number of levels to be
-   * written to the log file. The
-   * functionality is the same as
-   * <tt>depth_console</tt>, nevertheless,
-   * this function should be used
-   * with care, since it may spoile
-   * the value of a log file.
+   * Maximum number of levels to be written to the log file. The
+   * functionality is the same as <tt>depth_console</tt>, nevertheless,
+   * this function should be used with care, since it may spoile the value
+   * of a log file.
    *
-   * The previous value of this
-   * parameter is returned.
+   * The previous value of this parameter is returned.
    */
   unsigned int depth_file (const unsigned int n);
 
+
   /**
-   * Set time printing flag. If this flag
-   * is true, each output line will
-   * be prepended by the user time used
-   * by the running program so far.
+   * Set time printing flag. If this flag is true, each output line will be
+   * prepended by the user time used by the running program so far.
    *
-   * The previous value of this
-   * parameter is returned.
+   * The previous value of this parameter is returned.
    */
   bool log_execution_time (const bool flag);
 
+
   /**
-   * Output time differences
-   * between consecutive logs. If
-   * this function is invoked with
-   * <tt>true</tt>, the time difference
-   * between the previous log line
-   * and the recent one is
-   * printed. If it is invoked with
-   * <tt>false</tt>, the accumulated
-   * time since start of the
-   * program is printed (default
-   * behavior).
+   * Output time differences between consecutive logs. If this function is
+   * invoked with <tt>true</tt>, the time difference between the previous
+   * log line and the recent one is printed. If it is invoked with
+   * <tt>false</tt>, the accumulated time since start of the program is
+   * printed (default behavior).
    *
-   * The measurement of times is
-   * not changed by this function,
-   * just the output.
+   * The measurement of times is not changed by this function, just the
+   * output.
    *
-   * The previous value of this
-   * parameter is returned.
+   * The previous value of this parameter is returned.
    */
   bool log_time_differences (const bool flag);
 
+
   /**
-   * Write detailed timing
-   * information.
-   *
-   *
+   * Write detailed timing information.
    */
   void timestamp();
 
+
   /**
    * Log the thread id.
    */
   bool log_thread_id (const bool flag);
 
+
   /**
-   * Set a threshold for the
-   * minimal absolute value of
-   * double values. All numbers
-   * with a smaller absolute value
-   * will be printed as zero.
+   * Set a threshold for the minimal absolute value of double values. All
+   * numbers with a smaller absolute value will be printed as zero.
    *
-   * The default value for this
-   * threshold is zero,
-   * i.e. numbers are printed
+   * The default value for this threshold is zero, i.e. numbers are printed
    * according to their real value.
    *
-   * This feature is mostly useful
-   * for automated tests: there,
-   * one would like to reproduce
-   * the exact same solution in
-   * each run of a
-   * testsuite. However, subtle
-   * difference in processor,
-   * operating system, or compiler
-   * version can lead to
-   * differences in the last few
-   * digits of numbers, due to
-   * different rounding. While one
-   * can avoid trouble for most
-   * numbers when comparing with
-   * stored results by simply
-   * limiting the accuracy of
-   * output, this does not hold for
-   * numbers very close to zero,
-   * i.e. zero plus accumulated
-   * round-off. For these numbers,
-   * already the first digit is
-   * tainted by round-off. Using
-   * the present function, it is
-   * possible to eliminate this
-   * source of problems, by simply
-   * writing zero to the output in
-   * this case.
+   * This feature is mostly useful for automated tests: there, one would
+   * like to reproduce the exact same solution in each run of a testsuite.
+   * However, subtle difference in processor, operating system, or compiler
+   * version can lead to differences in the last few digits of numbers, due
+   * to different rounding. While one can avoid trouble for most numbers
+   * when comparing with stored results by simply limiting the accuracy of
+   * output, this does not hold for numbers very close to zero, i.e. zero
+   * plus accumulated round-off. For these numbers, already the first digit
+   * is tainted by round-off. Using the present function, it is possible to
+   * eliminate this source of problems, by simply writing zero to the
+   * output in this case.
    */
   void threshold_double(const double t);
+
+
   /**
-   * The same as
-   * threshold_double(), but for
-   * float values.
+   * The same as threshold_double(), but for float values.
    */
   void threshold_float(const float t);
 
+
   /**
-   * Output a constant something
-   * through this stream.
+   * Output a constant something through this stream.
    */
   template <typename T>
   LogStream &operator << (const T &t);
 
+
   /**
-   * Output double precision
-   * numbers through this
-   * stream.
+   * Output double precision numbers through this stream.
    *
-   * If they are set, this function
-   * applies the methods for making
-   * floating point output
-   * reproducible as discussed in
-   * the introduction.
+   * If they are set, this function applies the methods for making floating
+   * point output reproducible as discussed in the introduction.
    */
   LogStream &operator << (const double t);
 
+
   /**
-   * Output single precision
-   * numbers through this
-   * stream.
+   * Output single precision numbers through this stream.
    *
-   * If they are set, this function
-   * applies the methods for making
-   * floating point output
-   * reproducible as discussed in
-   * the introduction.
+   * If they are set, this function applies the methods for making floating
+   * point output reproducible as discussed in the introduction.
    */
   LogStream &operator << (const float t);
 
+
   /**
-   * Treat ostream
-   * manipulators. This passes on
-   * the whole thing to the
-   * template function with the
-   * exception of the
-   * <tt>std::endl</tt>
-   * manipulator, for which special
-   * action is performed: write the
-   * temporary stream buffer
-   * including a header to the file
-   * and <tt>std::cout</tt> and
-   * empty the buffer.
+   * Treat ostream manipulators. This passes on the whole thing to the
+   * template function with the exception of the <tt>std::endl</tt>
+   * manipulator, for which special action is performed: write the
+   * temporary stream buffer including a header to the file and
+   * <tt>std::cout</tt> and empty the buffer.
    *
-   * An overload of this function is needed
-   * anyway, since the compiler can't bind
-   * manipulators like @p std::endl
-   * directly to template arguments @p T
-   * like in the previous general
-   * template. This is due to the fact that
-   * @p std::endl is actually an overloaded
-   * set of functions for @p std::ostream,
-   * @p std::wostream, and potentially more
-   * of this kind. This function is
-   * therefore necessary to pick one
-   * element from this overload set.
+   * An overload of this function is needed anyway, since the compiler
+   * can't bind manipulators like @p std::endl directly to template
+   * arguments @p T like in the previous general template. This is due to
+   * the fact that @p std::endl is actually an overloaded set of functions
+   * for @p std::ostream, @p std::wostream, and potentially more of this
+   * kind. This function is therefore necessary to pick one element from
+   * this overload set.
    */
   LogStream &operator<< (std::ostream& (*p) (std::ostream &));
 
+
   /**
-   * Determine an estimate for
-   * the memory consumption (in
-   * bytes) of this
-   * object. Since sometimes
-   * the size of objects can
-   * not be determined exactly
-   * (for example: what is the
-   * memory consumption of an
-   * STL <tt>std::map</tt> type with a
-   * certain number of
-   * elements?), this is only
-   * an estimate. however often
-   * quite close to the true
-   * value.
+   * Determine an estimate for the memory consumption (in bytes) of this
+   * object. Since sometimes the size of objects can not be determined
+   * exactly (for example: what is the memory consumption of an STL
+   * <tt>std::map</tt> type with a certain number of elements?), this is
+   * only an estimate. however often quite close to the true value.
    */
   std::size_t memory_consumption () const;
 
+
   /**
    * Exception.
    */
@@ -448,46 +370,36 @@ public:
 private:
 
   /**
-   * Stack of strings which are printed
-   * at the beginning of each line to
-   * allow identification where the
-   * output was generated.
+   * Stack of strings which are printed at the beginning of each line to
+   * allow identification where the output was generated.
    */
   std::stack<std::string> prefixes;
 
   /**
-   * Default stream, where the output
-   * is to go to. This stream defaults
-   * to <tt>std::cerr</tt>, but can be set to another
-   * stream through the constructor.
+   * Default stream, where the output is to go to. This stream defaults to
+   * <tt>std::cerr</tt>, but can be set to another stream through the
+   * constructor.
    */
   std::ostream  *std_out;
 
   /**
-   * Pointer to a stream, where a copy of
-   * the output is to go to. Usually, this
-   * will be a file stream.
+   * Pointer to a stream, where a copy of the output is to go to. Usually,
+   * this will be a file stream.
    *
-   * You can set and reset this stream
-   * by the <tt>attach</tt> function.
+   * You can set and reset this stream by the <tt>attach</tt> function.
    */
   std::ostream  *file;
 
   /**
-   * Value denoting the number of
-   * prefixes to be printed to the
-   * standard output. If more than
-   * this number of prefixes is
-   * pushed to the stack, then no
-   * output will be generated until
-   * the number of prefixes shrinks
+   * Value denoting the number of prefixes to be printed to the standard
+   * output. If more than this number of prefixes is pushed to the stack,
+   * then no output will be generated until the number of prefixes shrinks
    * back below this number.
    */
   unsigned int std_depth;
 
   /**
-   * Same for the maximum depth of
-   * prefixes for output to a file.
+   * Same for the maximum depth of prefixes for output to a file.
    */
   unsigned int file_depth;
 
@@ -507,53 +419,33 @@ private:
   double last_time;
 
   /**
-   * Threshold for printing double
-   * values. Every number with
-   * absolute value less than this
-   * is printed as zero.
+   * Threshold for printing double values. Every number with absolute value
+   * less than this is printed as zero.
    */
   double double_threshold;
 
   /**
-   * Threshold for printing float
-   * values. Every number with
-   * absolute value less than this
-   * is printed as zero.
+   * Threshold for printing float values. Every number with absolute value
+   * less than this is printed as zero.
    */
   float float_threshold;
 
   /**
-   * An offset added to every float
-   * or double number upon
-   * output. This is done after the
-   * number is compared to
-   * #double_threshold or #float_threshold,
-   * but before rounding.
+   * An offset added to every float or double number upon output. This is
+   * done after the number is compared to #double_threshold or
+   * #float_threshold, but before rounding.
    *
-   * This functionality was
-   * introduced to produce more
-   * reproducible floating point
-   * output for regression
-   * tests. The rationale is, that
-   * an exact output value is much
-   * more likely to be 1/8 than
-   * 0.124997. If we round to two
-   * digits though, 1/8 becomes
-   * unreliably either .12 or .13
-   * due to machine accuracy. On
-   * the other hand, if we add a
-   * something above machine
-   * accuracy first, we will always
-   * get .13.
+   * This functionality was introduced to produce more reproducible
+   * floating point output for regression tests. The rationale is, that an
+   * exact output value is much more likely to be 1/8 than 0.124997. If we
+   * round to two digits though, 1/8 becomes unreliably either .12 or .13
+   * due to machine accuracy. On the other hand, if we add a something
+   * above machine accuracy first, we will always get .13.
    *
-   * It is safe to leave this
-   * value equal to zero. For
-   * regression tests, the function
-   * test_mode() sets it to a
-   * reasonable value.
+   * It is safe to leave this value equal to zero. For regression tests,
+   * the function test_mode() sets it to a reasonable value.
    *
-   * The offset is relative to the
-   * magnitude of the number.
+   * The offset is relative to the magnitude of the number.
    */
   double offset;
 
@@ -563,49 +455,38 @@ private:
   bool print_thread_id;
 
   /**
-   * The value times() returned
-   * on initialization.
+   * The value times() returned on initialization.
    */
   double reference_time_val;
 
   /**
-   * The tms structure times()
-   * filled on initialization.
+   * The tms structure times() filled on initialization.
    */
   struct tms reference_tms;
 
   /**
-   * Original buffer of
-   * <tt>std::cerr</tt>. We store
-   * the address of that buffer
-   * when #log_cerr is called, and
-   * reset it to this value if
-   * #log_cerr is called a second
-   * time, or when the destructor
-   * of this class is run.
+   * Original buffer of <tt>std::cerr</tt>. We store the address of that
+   * buffer when #log_cerr is called, and reset it to this value if
+   * #log_cerr is called a second time, or when the destructor of this
+   * class is run.
    */
   std::streambuf *old_cerr;
 
   /**
-   * Print head of line. This prints
-   * optional time information and
-   * the contents of the prefix stack.
+   * A flag indicating whether output is currently at a new line
    */
-  void print_line_head ();
+  bool at_newline;
 
   /**
-   * Actually do the work of
-   * writing output. This function
-   * unifies the work that is
-   * common to the two
-   * <tt>operator<<</tt> functions.
+   * Print head of line. This prints optional time information and the
+   * contents of the prefix stack.
    */
-  template <typename T>
-  void print (const T &t);
+  void print_line_head ();
+
   /**
-   * Check if we are on a new line
-   * and print the header before
-   * the data.
+   * Internal wrapper around "thread local" outstreams. This private
+   * function will return the correct internal ostringstream buffer for
+   * operater<<.
    */
   std::ostringstream &get_stream();
 
@@ -615,9 +496,7 @@ private:
   typedef std::map<unsigned int, std_cxx1x::shared_ptr<std::ostringstream> > stream_map_type;
 
   /**
-   * We generate a stringstream for
-   * every process that sends log
-   * messages.
+   * We generate a stringstream for every process that sends log messages.
    */
   stream_map_type outstreams;
 
@@ -627,34 +506,13 @@ private:
 /* ----------------------------- Inline functions and templates ---------------- */
 
 
-template <class T>
-inline
-void
-LogStream::print (const T &t)
-{
-  // if the previous command was an
-  // <tt>std::endl</tt>, print the topmost
-  // prefix and a colon
-  std::ostringstream &stream = get_stream();
-  stream << t;
-  // print the rest of the message
-//   if (prefixes.size() <= std_depth)
-//     *std_out << t;
-
-//   if (file && (prefixes.size() <= file_depth))
-//     *file << t;
-}
-
-
-
 template <class T>
 inline
 LogStream &
 LogStream::operator<< (const T &t)
 {
-  // do the work that is common to
-  // the operator<< functions
-  print (t);
+  // print to the internal stringstream:
+  get_stream() << t;
   return *this;
 }
 
@@ -664,20 +522,16 @@ inline
 LogStream &
 LogStream::operator<< (const double t)
 {
-  // we have to make sure that we
-  // don't catch NaN's and +-Inf's
-  // with the test, because for these
-  // denormals all comparisons are
-  // always false. thus, for a NaN,
-  // both t<=0 and t>=0 are false at
-  // the same time, which can't be
-  // said for any other number
+  // we have to make sure that we don't catch NaN's and +-Inf's with the
+  // test, because for these denormals all comparisons are always false.
+  // thus, for a NaN, both t<=0 and t>=0 are false at the same time, which
+  // can't be said for any other number
   if (! (t<=0) && !(t>=0))
-    print (t);
+    get_stream() << t;
   else if (std::fabs(t) < double_threshold)
-    print ('0');
+    get_stream() << '0';
   else
-    print(t*(1.+offset));
+    get_stream() << t*(1.+offset);
 
   return *this;
 }
@@ -688,20 +542,16 @@ inline
 LogStream &
 LogStream::operator<< (const float t)
 {
-  // we have to make sure that we
-  // don't catch NaN's and +-Inf's
-  // with the test, because for these
-  // denormals all comparisons are
-  // always false. thus, for a NaN,
-  // both t<=0 and t>=0 are false at
-  // the same time, which can't be
-  // said for any other number
+  // we have to make sure that we don't catch NaN's and +-Inf's with the
+  // test, because for these denormals all comparisons are always false.
+  // thus, for a NaN, both t<=0 and t>=0 are false at the same time, which
+  // can't be said for any other number
   if (! (t<=0) && !(t>=0))
-    print (t);
+    get_stream() << t;
   else if (std::fabs(t) < float_threshold)
-    print ('0');
+    get_stream() << '0';
   else
-    print(t*(1.+offset));
+    get_stream() << t*(1.+offset);
 
   return *this;
 }
index 475e30ffa5b6dc0a2ef8a1a21c853ceb04f566bd..0a1cf46faabdf48db70b49c07feee6b02264e9c6 100644 (file)
@@ -49,7 +49,7 @@ LogStream::LogStream()
   std_depth(10000), file_depth(10000),
   print_utime(false), diff_utime(false),
   last_time (0.), double_threshold(0.), float_threshold(0.),
-  offset(0), old_cerr(0)
+  offset(0), old_cerr(0), at_newline(true)
 {
   prefixes.push("DEAL:");
   std_out->setf(std::ios::showpoint | std::ios::left);
@@ -61,10 +61,8 @@ LogStream::LogStream()
 
 LogStream::~LogStream()
 {
-  // if there was anything left in
-  // the stream that is current to
-  // this thread, make sure we flush
-  // it before it gets lost
+  // if there was anything left in the stream that is current to this
+  // thread, make sure we flush it before it gets lost
   {
     const unsigned int id = Threads::this_thread_id();
     if ((outstreams.find(id) != outstreams.end())
@@ -73,42 +71,20 @@ LogStream::~LogStream()
         &&
         (outstreams[id]->str().length() > 0))
       {
-        // except the situation is
-        // not quite that simple. if
-        // this object is the
-        // 'deallog' object, then it
-        // is destroyed upon exit of
-        // the program. since it's
-        // defined in a shared
-        // library that depends on
-        // libstdc++.so, destruction
-        // happens before destruction
-        // of std::cout/cerr, but
-        // after all file variables
-        // defined in user programs
-        // have been destroyed. in
-        // other words, if we get
-        // here and the object being
-        // destroyed is 'deallog' and
-        // if 'deallog' is associated
-        // with a file stream, then
-        // we're in trouble: we'll
-        // try to write to a file
-        // that doesn't exist any
-        // more, and we're likely
-        // going to crash (this is
-        // tested by
-        // base/log_crash_01). rather
-        // than letting it come to
-        // this, print a message to
-        // the screen (note that we
-        // can't issue an assertion
-        // here either since Assert
-        // may want to write to
-        // 'deallog' itself, and
-        // AssertThrow will throw an
-        // exception that can't be
-        // caught)
+        // except the situation is not quite that simple. if this object is
+        // the 'deallog' object, then it is destroyed upon exit of the
+        // program. since it's defined in a shared library that depends on
+        // libstdc++.so, destruction happens before destruction of
+        // std::cout/cerr, but after all file variables defined in user
+        // programs have been destroyed. in other words, if we get here and
+        // the object being destroyed is 'deallog' and if 'deallog' is
+        // associated with a file stream, then we're in trouble: we'll try
+        // to write to a file that doesn't exist any more, and we're likely
+        // going to crash (this is tested by base/log_crash_01). rather
+        // than letting it come to this, print a message to the screen
+        // (note that we can't issue an assertion here either since Assert
+        // may want to write to 'deallog' itself, and AssertThrow will
+        // throw an exception that can't be caught)
         if ((this == &deallog) && file)
           std::cerr << ("You still have content that was written to 'deallog' "
                         "but not flushed to the screen or a file while the "
@@ -125,18 +101,11 @@ LogStream::~LogStream()
   if (old_cerr)
     std::cerr.rdbuf(old_cerr);
 
-  // on some systems, destroying the
-  // outstreams objects of deallog
-  // triggers some sort of memory
-  // corruption, in particular when
-  // we also link with Trilinos;
-  // since this happens at the very
-  // end of the program, we take the
-  // liberty to simply not do it by
-  // putting that object into a
-  // deliberate memory leak and
-  // instead destroying an empty
-  // object
+  // on some systems, destroying the outstreams objects of deallog triggers
+  // some sort of memory corruption, in particular when we also link with
+  // Trilinos; since this happens at the very end of the program, we take
+  // the liberty to simply not do it by putting that object into a
+  // deliberate memory leak and instead destroying an empty object
 #ifdef DEAL_II_WITH_TRILINOS
   if (this == &deallog)
     {
@@ -170,19 +139,29 @@ LogStream::test_mode(bool on)
 LogStream &
 LogStream::operator<< (std::ostream& (*p) (std::ostream &))
 {
-  // do the work that is common to
-  // the operator<< functions
-  print (p);
+  std::ostringstream &stream = get_stream();
 
-  // next check whether this is the
-  // <tt>endl</tt> manipulator, and if so
-  // set a flag
+  // Print to the internal stringstream:
+  stream << p;
+
+  // Next check whether this is the <tt>flush</tt> or <tt>endl</tt>
+  // 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_endl)
+  if (p == p_flush || p == p_endl)
     {
       Threads::Mutex::ScopedLock lock(write_lock);
-      print_line_head();
-      std::ostringstream &stream = get_stream();
+
+      // Print the line head in case of a newline:
+      if (at_newline)
+        print_line_head();
+
+      if(p == p_flush)
+        at_newline = false;
+
+      if(p == p_endl)
+        at_newline = true;
+
       if (prefixes.size() <= std_depth)
         *std_out << stream.str();
 
@@ -192,6 +171,7 @@ LogStream::operator<< (std::ostream& (*p) (std::ostream &))
       // Start a new string
       stream.str("");
     }
+
   return *this;
 }
 
@@ -213,7 +193,6 @@ LogStream::get_stream()
 }
 
 
-
 void
 LogStream::attach(std::ostream &o)
 {

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.