llvm.org GIT mirror llvm / d17d74b
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 Daniel Dunbar 10 years ago
2 changed file(s) with 30 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
3030 /// a chunk at a time.
3131 class raw_ostream {
3232 private:
33 /// \invariant { The buffer is uninitialized (OutBufStart,
34 /// OutBufEnd, and OutBufCur are non-zero), or none of them are zero
35 /// and there are at least 64 total bytes in the buffer. }
36
33 /// The buffer is handled in such a way that the buffer is
34 /// uninitialized, unbuffered, or out of space when OutBufCur >=
35 /// OutBufEnd. Thus a single comparison suffices to determine if we
36 /// need to take the slow path to write a single character.
37 ///
38 /// The buffer is in one of three states:
39 /// 1. Unbuffered (Unbuffered == true)
40 /// 1. Uninitialized (Unbuffered == false && OutBufStart == 0).
41 /// 2. Buffered (Unbuffered == false && OutBufStart != 0 &&
42 /// OutBufEnd - OutBufStart >= 64).
3743 char *OutBufStart, *OutBufEnd, *OutBufCur;
3844 bool Unbuffered;
3945
5359
5460 /// SetBufferSize - Set the internal buffer size to the specified amount
5561 /// instead of the default.
56 void SetBufferSize(unsigned Size) {
62 void SetBufferSize(unsigned Size=4096) {
5763 assert(Size >= 64 &&
5864 "Buffer size must be somewhat large for invariants to hold");
5965 flush();
6268 OutBufStart = new char[Size];
6369 OutBufEnd = OutBufStart+Size;
6470 OutBufCur = OutBufStart;
71 Unbuffered = false;
6572 }
6673
6774 /// SetUnbuffered - Set the streams buffering status. When
6875 /// unbuffered the stream will flush after every write. This routine
6976 /// will also flush the buffer immediately when the stream is being
7077 /// set to unbuffered.
71 void SetUnbuffered(bool unbuffered) {
72 Unbuffered = unbuffered;
73 if (Unbuffered)
74 flush();
78 void SetUnbuffered() {
79 flush();
80
81 delete [] OutBufStart;
82 OutBufStart = OutBufEnd = OutBufCur = 0;
83 Unbuffered = true;
7584 }
7685
7786 unsigned GetNumBytesInBuffer() const {
91100 if (OutBufCur >= OutBufEnd)
92101 return write(C);
93102 *OutBufCur++ = C;
94 if (Unbuffered)
95 flush_nonempty();
96103 return *this;
97104 }
98105
100107 if (OutBufCur >= OutBufEnd)
101108 return write(C);
102109 *OutBufCur++ = C;
103 if (Unbuffered)
104 flush_nonempty();
105110 return *this;
106111 }
107112
109114 if (OutBufCur >= OutBufEnd)
110115 return write(C);
111116 *OutBufCur++ = C;
112 if (Unbuffered)
113 flush_nonempty();
114117 return *this;
115118 }
116119
122122 }
123123
124124 raw_ostream &raw_ostream::write(unsigned char C) {
125 if (Unbuffered) {
126 write_impl(reinterpret_cast(&C), 1);
127 return *this;
128 }
129
125130 if (!OutBufStart)
126 SetBufferSize(4096);
131 SetBufferSize();
127132 else if (OutBufCur >= OutBufEnd)
128133 flush_nonempty();
129134
132137 }
133138
134139 raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
140 if (Unbuffered) {
141 write_impl(Ptr, Size);
142 return *this;
143 }
144
135145 if (!OutBufStart)
136 SetBufferSize(4096);
146 SetBufferSize();
137147 else if (OutBufCur+Size > OutBufEnd)
138148 flush_nonempty();
139149
160170 }
161171 OutBufCur += Size;
162172
163 if (Unbuffered)
164 flush();
165173 return *this;
166174 }
167175