From d17d74bb80d9da1712a066df40122e8584dad227 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 17 Mar 2009 01:13:35 +0000 Subject: [PATCH] raw_ostream: Rework implementation of unbuffered streams so outputting a single character requires only one branch to follow slow path. - Never use a buffer when writing on an unbuffered stream. - Move default buffer size to header. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67066 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/raw_ostream.h | 33 ++++++++++++++++-------------- lib/Support/raw_ostream.cpp | 16 +++++++++++---- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index aa6a8b9f9fe..4db6737f6d4 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -31,10 +31,16 @@ namespace llvm { /// a chunk at a time. class raw_ostream { private: - /// \invariant { The buffer is uninitialized (OutBufStart, - /// OutBufEnd, and OutBufCur are non-zero), or none of them are zero - /// and there are at least 64 total bytes in the buffer. } - + /// The buffer is handled in such a way that the buffer is + /// uninitialized, unbuffered, or out of space when OutBufCur >= + /// OutBufEnd. Thus a single comparison suffices to determine if we + /// need to take the slow path to write a single character. + /// + /// The buffer is in one of three states: + /// 1. Unbuffered (Unbuffered == true) + /// 1. Uninitialized (Unbuffered == false && OutBufStart == 0). + /// 2. Buffered (Unbuffered == false && OutBufStart != 0 && + /// OutBufEnd - OutBufStart >= 64). char *OutBufStart, *OutBufEnd, *OutBufCur; bool Unbuffered; @@ -54,7 +60,7 @@ public: /// SetBufferSize - Set the internal buffer size to the specified amount /// instead of the default. - void SetBufferSize(unsigned Size) { + void SetBufferSize(unsigned Size=4096) { assert(Size >= 64 && "Buffer size must be somewhat large for invariants to hold"); flush(); @@ -63,16 +69,19 @@ public: OutBufStart = new char[Size]; OutBufEnd = OutBufStart+Size; OutBufCur = OutBufStart; + Unbuffered = false; } /// SetUnbuffered - Set the streams buffering status. 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(bool unbuffered) { - Unbuffered = unbuffered; - if (Unbuffered) - flush(); + void SetUnbuffered() { + flush(); + + delete [] OutBufStart; + OutBufStart = OutBufEnd = OutBufCur = 0; + Unbuffered = true; } unsigned GetNumBytesInBuffer() const { @@ -92,8 +101,6 @@ public: if (OutBufCur >= OutBufEnd) return write(C); *OutBufCur++ = C; - if (Unbuffered) - flush_nonempty(); return *this; } @@ -101,8 +108,6 @@ public: if (OutBufCur >= OutBufEnd) return write(C); *OutBufCur++ = C; - if (Unbuffered) - flush_nonempty(); return *this; } @@ -110,8 +115,6 @@ public: if (OutBufCur >= OutBufEnd) return write(C); *OutBufCur++ = C; - if (Unbuffered) - flush_nonempty(); return *this; } diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index 3b33ad67b14..6aec9478fa2 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -123,8 +123,13 @@ void raw_ostream::flush_nonempty() { } raw_ostream &raw_ostream::write(unsigned char C) { + if (Unbuffered) { + write_impl(reinterpret_cast(&C), 1); + return *this; + } + if (!OutBufStart) - SetBufferSize(4096); + SetBufferSize(); else if (OutBufCur >= OutBufEnd) flush_nonempty(); @@ -133,8 +138,13 @@ raw_ostream &raw_ostream::write(unsigned char C) { } raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) { + if (Unbuffered) { + write_impl(Ptr, Size); + return *this; + } + if (!OutBufStart) - SetBufferSize(4096); + SetBufferSize(); else if (OutBufCur+Size > OutBufEnd) flush_nonempty(); @@ -161,8 +171,6 @@ raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) { } OutBufCur += Size; - if (Unbuffered) - flush(); return *this; }