formatted_raw_ostream both is-a raw_ostream and has-a raw_ostream. This
authorDan Gohman <gohman@apple.com>
Thu, 16 Jul 2009 01:32:46 +0000 (01:32 +0000)
committerDan Gohman <gohman@apple.com>
Thu, 16 Jul 2009 01:32:46 +0000 (01:32 +0000)
means that two separate raw_ostreams are doing buffering before data is
sent to the underlying stream. Besides the inefficiency of redundant
buffering, the second level of buffering doesn't recieve flush()
requests.

Fix this by having formatted_raw_ostream set the underlying raw_ostream
to be unbuffered. This eliminates inefficiency due to redundant buffering,
and it makes the flush() disconnect harmless.

This fixes PR4559.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75883 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/FormattedStream.h

index 9658979352f9d0764c582de8c3089a071c1e3113..7260c3fba39b4d93e931fce35a1ff1b7907e097c 100644 (file)
@@ -33,7 +33,8 @@ namespace llvm
     const static bool PRESERVE_STREAM = false;
     
   private:
-    /// TheStream - The real stream we output to.
+    /// TheStream - The real stream we output to. We set it to be
+    /// unbuffered, since we're already doing our own buffering.
     ///
     raw_ostream *TheStream;
     /// DeleteStream - Do we need to delete TheStream in the
@@ -70,13 +71,27 @@ namespace llvm
     /// put into ErrorInfo, and the stream should be immediately
     /// destroyed; the string will be empty if no error occurred.
     ///
+    /// As a side effect, the given Stream is set to be Unbuffered.
+    /// This is because formatted_raw_ostream does its own buffering,
+    /// so it doesn't want another layer of buffering to be happening
+    /// underneath it.
+    ///
     /// \param Filename - The file to open. If this is "-" then the
     /// stream will use stdout instead.
     /// \param Binary - The file should be opened in binary mode on
     /// platforms that support this distinction.
     formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) 
-        : raw_ostream(), TheStream(&Stream), DeleteStream(Delete), Column(0) {}
-    explicit formatted_raw_ostream() 
+      : raw_ostream(), TheStream(&Stream), DeleteStream(Delete), Column(0) {
+      // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
+      // own buffering, and it doesn't need or want TheStream to do another
+      // layer of buffering underneath. Resize the buffer to what TheStream
+      // had been using, and tell TheStream not to do its own buffering.
+      TheStream->flush();
+      if (size_t BufferSize = TheStream->GetNumBytesInBuffer())
+        SetBufferSize(BufferSize);
+      TheStream->SetUnbuffered();
+    }
+    explicit formatted_raw_ostream()
       : raw_ostream(), TheStream(0), DeleteStream(false), Column(0) {}
 
     ~formatted_raw_ostream() {
@@ -87,6 +102,12 @@ namespace llvm
     void setStream(raw_ostream &Stream, bool Delete = false) {
       TheStream = &Stream;
       DeleteStream = Delete;
+
+      // Avoid double-buffering, as above.
+      TheStream->flush();
+      if (size_t BufferSize = TheStream->GetNumBytesInBuffer())
+        SetBufferSize(BufferSize);
+      TheStream->SetUnbuffered();
     }
 
     /// PadToColumn - Align the output to some column number.