Skip to content

Commit 1ee94a1

Browse files
committed
std: Flush when buffered writers are dropped
It's still not entirely clear what should happen if there was an error when flushing, but I'm deferring that decision to #12628. I believe that it's crucial for the usefulness of buffered writers to be able to flush on drop. It's just too easy to forget to flush them in small one-off use cases. cc #12628
1 parent 3d117cf commit 1ee94a1

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

src/libstd/io/buffered.rs

+25-14
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use cmp;
1414
use container::Container;
1515
use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
1616
use iter::ExactSize;
17-
use option::{Some, None};
17+
use ops::Drop;
18+
use option::{Some, None, Option};
1819
use result::{Ok, Err};
1920
use vec::{OwnedVector, ImmutableVector, MutableVector};
2021
use vec;
@@ -115,7 +116,7 @@ impl<R: Reader> Reader for BufferedReader<R> {
115116

116117
/// Wraps a Writer and buffers output to it
117118
///
118-
/// Note that `BufferedWriter` will NOT flush its buffer when dropped.
119+
/// This writer will be flushed when it is dropped.
119120
///
120121
/// # Example
121122
///
@@ -130,7 +131,7 @@ impl<R: Reader> Reader for BufferedReader<R> {
130131
/// writer.flush();
131132
/// ```
132133
pub struct BufferedWriter<W> {
133-
priv inner: W,
134+
priv inner: Option<W>,
134135
priv buf: ~[u8],
135136
priv pos: uint
136137
}
@@ -142,7 +143,7 @@ impl<W: Writer> BufferedWriter<W> {
142143
let mut buf = vec::with_capacity(cap);
143144
unsafe { buf.set_len(cap); }
144145
BufferedWriter {
145-
inner: inner,
146+
inner: Some(inner),
146147
buf: buf,
147148
pos: 0
148149
}
@@ -155,7 +156,7 @@ impl<W: Writer> BufferedWriter<W> {
155156

156157
fn flush_buf(&mut self) -> IoResult<()> {
157158
if self.pos != 0 {
158-
let ret = self.inner.write(self.buf.slice_to(self.pos));
159+
let ret = self.inner.get_mut_ref().write(self.buf.slice_to(self.pos));
159160
self.pos = 0;
160161
ret
161162
} else {
@@ -167,15 +168,15 @@ impl<W: Writer> BufferedWriter<W> {
167168
///
168169
/// This type does not expose the ability to get a mutable reference to the
169170
/// underlying reader because that could possibly corrupt the buffer.
170-
pub fn get_ref<'a>(&'a self) -> &'a W { &self.inner }
171+
pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.get_ref() }
171172

172173
/// Unwraps this buffer, returning the underlying writer.
173174
///
174175
/// The buffer is flushed before returning the writer.
175176
pub fn unwrap(mut self) -> W {
176-
// FIXME: is failing the right thing to do if flushing fails?
177+
// FIXME(#12628): is failing the right thing to do if flushing fails?
177178
self.flush_buf().unwrap();
178-
self.inner
179+
self.inner.take_unwrap()
179180
}
180181
}
181182

@@ -186,7 +187,7 @@ impl<W: Writer> Writer for BufferedWriter<W> {
186187
}
187188

188189
if buf.len() > self.buf.len() {
189-
self.inner.write(buf)
190+
self.inner.get_mut_ref().write(buf)
190191
} else {
191192
let dst = self.buf.mut_slice_from(self.pos);
192193
vec::bytes::copy_memory(dst, buf);
@@ -196,14 +197,24 @@ impl<W: Writer> Writer for BufferedWriter<W> {
196197
}
197198

198199
fn flush(&mut self) -> IoResult<()> {
199-
self.flush_buf().and_then(|()| self.inner.flush())
200+
self.flush_buf().and_then(|()| self.inner.get_mut_ref().flush())
201+
}
202+
}
203+
204+
#[unsafe_destructor]
205+
impl<W: Writer> Drop for BufferedWriter<W> {
206+
fn drop(&mut self) {
207+
if self.inner.is_some() {
208+
// FIXME(#12628): should this error be ignored?
209+
let _ = self.flush_buf();
210+
}
200211
}
201212
}
202213

203214
/// Wraps a Writer and buffers output to it, flushing whenever a newline (`0x0a`,
204215
/// `'\n'`) is detected.
205216
///
206-
/// Note that this structure does NOT flush the output when dropped.
217+
/// This writer will be flushed when it is dropped.
207218
pub struct LineBufferedWriter<W> {
208219
priv inner: BufferedWriter<W>,
209220
}
@@ -256,13 +267,13 @@ impl<W> InternalBufferedWriter<W> {
256267

257268
impl<W: Reader> Reader for InternalBufferedWriter<W> {
258269
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
259-
self.get_mut_ref().inner.read(buf)
270+
self.get_mut_ref().inner.get_mut_ref().read(buf)
260271
}
261272
}
262273

263-
/// Wraps a Stream and buffers input and output to and from it
274+
/// Wraps a Stream and buffers input and output to and from it.
264275
///
265-
/// Note that `BufferedStream` will NOT flush its output buffer when dropped.
276+
/// The output half will be flushed when this stream is dropped.
266277
///
267278
/// # Example
268279
///

0 commit comments

Comments
 (0)