raw_fd_ostream: Add a SetUseAtomicWrites() method (uses writev).
authorDaniel Dunbar <daniel@zuster.org>
Thu, 3 Feb 2011 03:32:32 +0000 (03:32 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 3 Feb 2011 03:32:32 +0000 (03:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124771 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 95904ea2f31eb00349dfc182ba408e200b7e0a18..6bfae5e298225499df05dd6b68f5e9006d5ecb99 100644 (file)
@@ -301,6 +301,10 @@ class raw_fd_ostream : public raw_ostream {
   ///
   bool Error;
 
+  /// Controls whether the stream should attempt to use atomic writes, when
+  /// possible.
+  bool UseAtomicWrites;
+
   uint64_t pos;
 
   /// write_impl - See raw_ostream::write_impl.
@@ -361,6 +365,16 @@ public:
   /// position to the offset specified from the beginning of the file.
   uint64_t seek(uint64_t off);
 
+  /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for
+  /// individual output routines where possible.
+  ///
+  /// Note that because raw_ostream's are typically buffered, this flag is only
+  /// sensible when used on unbuffered streams which will flush their output
+  /// immediately.
+  void SetUseAtomicWrites(bool Value) {
+    UseAtomicWrites = Value;
+  }
+
   virtual raw_ostream &changeColor(enum Colors colors, bool bold=false,
                                    bool bg=false);
   virtual raw_ostream &resetColor();
index e7d75e712860bc47188a126f2422d38a20b3cb35..80ea7407b44e577800e13decf62df6da63a46892 100644 (file)
@@ -32,6 +32,9 @@
 #if defined(HAVE_FCNTL_H)
 # include <fcntl.h>
 #endif
+#if defined(HAVE_SYS_UIO_H) && defined(HAVE_WRITEV)
+#  include <sys/uio.h>
+#endif
 
 #if defined(__CYGWIN__)
 #include <io.h>
@@ -375,7 +378,9 @@ void format_object_base::home() {
 /// stream should be immediately destroyed; the string will be empty
 /// if no error occurred.
 raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo,
-                               unsigned Flags) : Error(false), pos(0) {
+                               unsigned Flags)
+  : Error(false), UseAtomicWrites(false), pos(0)
+{
   assert(Filename != 0 && "Filename is null");
   // Verify that we don't have both "append" and "excl".
   assert((!(Flags & F_Excl) || !(Flags & F_Append)) &&
@@ -426,7 +431,7 @@ raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo,
 /// ShouldClose is true, this closes the file when the stream is destroyed.
 raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)
   : raw_ostream(unbuffered), FD(fd),
-    ShouldClose(shouldClose), Error(false) {
+    ShouldClose(shouldClose), Error(false), UseAtomicWrites(false) {
 #ifdef O_BINARY
   // Setting STDOUT and STDERR to binary mode is necessary in Win32
   // to avoid undesirable linefeed conversion.
@@ -467,7 +472,20 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
   pos += Size;
 
   do {
-    ssize_t ret = ::write(FD, Ptr, Size);
+    ssize_t ret;
+
+    // Check whether we should attempt to use atomic writes.
+    if (BUILTIN_EXPECT(!UseAtomicWrites, true)) {
+      ret = ::write(FD, Ptr, Size);
+    } else {
+      // Use ::writev() where available.
+#if defined(HAVE_WRITEV)
+      struct iovec IOV = { (void*) Ptr, Size };
+      ret = ::writev(FD, &IOV, 1);
+#else
+      ret = ::write(FD, Ptr, Size);
+#endif
+    }
 
     if (ret < 0) {
       // If it's a recoverable error, swallow it and retry the write.