Add support to raw_ostream for sizing the buffer according to the
authorDan Gohman <gohman@apple.com>
Thu, 13 Aug 2009 17:27:29 +0000 (17:27 +0000)
committerDan Gohman <gohman@apple.com>
Thu, 13 Aug 2009 17:27:29 +0000 (17:27 +0000)
needs of the underlying output mechanism. raw_fd_ostream now uses
st_blksize from fstat to determine a buffer size.

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

include/llvm/Support/raw_ostream.h
lib/Support/raw_ostream.cpp

index 5d6d59f1d7fcf72a20262bc32455bccd7ccc76a0..b1b96f231695b6bbf80d7912e7bdb895c36952fa 100644 (file)
@@ -96,16 +96,26 @@ public:
   // Configuration Interface
   //===--------------------------------------------------------------------===//
 
-  /// SetBufferSize - Set the internal buffer size to the specified amount
-  /// instead of the default.
-  void SetBufferSize(size_t Size=4096);
+  /// SetBuffered - Set the stream to be buffered, with an automatically
+  /// determined buffer size.
+  void SetBuffered();
 
-  size_t GetBufferSize() const {
+  /// SetBufferrSize - Set the stream to be buffered, using the
+  /// specified buffer size.
+  void SetBufferSize(size_t Size);
+
+  size_t GetBufferSize() {
+    // If we're supposed to be buffered but haven't actually gotten around
+    // to allocating the buffer yet, return the value that would be used.
+    if (!Unbuffered && !OutBufStart)
+      return preferred_buffer_size();
+
+    // Otherwise just return the size of the allocated buffer.
     return OutBufEnd - OutBufStart;
   }
 
-  /// SetUnbuffered - Set the streams buffering status. When
-  /// unbuffered the stream will flush after every write. This routine
+  /// SetUnbuffered - Set the stream to be unbuffered. When
+  /// unbuffered, the stream will flush after every write. This routine
   /// will also flush the buffer immediately when the stream is being
   /// set to unbuffered.
   void SetUnbuffered();
@@ -233,6 +243,10 @@ private:
   virtual uint64_t current_pos() = 0;
 
 protected:
+  /// preferred_buffer_size - Return an efficient buffer size for the
+  /// underlying output mechanism.
+  virtual size_t preferred_buffer_size();
+
   /// error_detected - Set the flag indicating that an output error has
   /// been encountered.
   void error_detected() { Error = true; }
@@ -273,6 +287,9 @@ class raw_fd_ostream : public raw_ostream {
   /// counting the bytes currently in the buffer.
   virtual uint64_t current_pos() { return pos; }
 
+  /// preferred_buffer_size - Determine an efficient buffer size.
+  virtual size_t preferred_buffer_size();
+
 public:
   /// raw_fd_ostream - Open the specified file for writing. If an
   /// error occurs, information about the error is put into ErrorInfo,
index 2a2458d61a394a593e8b3967894b28ed0b771b1a..c6d609bfc74256294930952dc262caaf01313dd6 100644 (file)
@@ -20,6 +20,8 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <ostream>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #if defined(HAVE_UNISTD_H)
 # include <unistd.h>
@@ -63,6 +65,16 @@ raw_ostream::~raw_ostream() {
 // An out of line virtual method to provide a home for the class vtable.
 void raw_ostream::handle() {}
 
+size_t raw_ostream::preferred_buffer_size() {
+  // BUFSIZ is intended to be a reasonable default.
+  return BUFSIZ;
+}
+
+void raw_ostream::SetBuffered() {
+  // Ask the subclass to determine an appropriate buffer size.
+  SetBufferSize(preferred_buffer_size());
+}
+
 void raw_ostream::SetBufferSize(size_t Size) {
   assert(Size >= 64 &&
          "Buffer size must be somewhat large for invariants to hold");
@@ -172,7 +184,7 @@ raw_ostream &raw_ostream::write(unsigned char C) {
     }
     
     if (!OutBufStart)
-      SetBufferSize();
+      SetBuffered();
     else
       flush_nonempty();
   }
@@ -190,7 +202,7 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {
         return *this;
       }
       // Set up a buffer and start over.
-      SetBufferSize();
+      SetBuffered();
       return write(Ptr, Size);
     }
     // Write out the data in buffer-sized blocks until the remainder
@@ -353,6 +365,17 @@ uint64_t raw_fd_ostream::seek(uint64_t off) {
   return pos;  
 }
 
+size_t raw_fd_ostream::preferred_buffer_size() {
+#if !defined(_MSC_VER) // Windows reportedly doesn't have st_blksize.
+  assert(FD >= 0 && "File not yet open!");
+  struct stat statbuf;
+  if (fstat(FD, &statbuf) == 0)
+    return statbuf.st_blksize;
+  error_detected();
+#endif
+  return raw_ostream::preferred_buffer_size();
+}
+
 raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
                                          bool bg) {
   if (sys::Process::ColorNeedsFlush())