diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-02-28 12:46:46 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-03-01 10:05:31 -0800 |
| commit | 1ee94a1336071fb0319b23a6c73b3d83ccd66bdf (patch) | |
| tree | 293425ff632ba752c5bca730584c7995224e31f0 /src/libstd | |
| parent | 3d117cf3ca9dc091dd605b33617c32c6019b0e2b (diff) | |
| download | rust-1ee94a1336071fb0319b23a6c73b3d83ccd66bdf.tar.gz rust-1ee94a1336071fb0319b23a6c73b3d83ccd66bdf.zip | |
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
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/buffered.rs | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index d1bd6ae13f4..5a69815fa29 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -14,7 +14,8 @@ use cmp; use container::Container; use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult}; use iter::ExactSize; -use option::{Some, None}; +use ops::Drop; +use option::{Some, None, Option}; use result::{Ok, Err}; use vec::{OwnedVector, ImmutableVector, MutableVector}; use vec; @@ -115,7 +116,7 @@ impl<R: Reader> Reader for BufferedReader<R> { /// Wraps a Writer and buffers output to it /// -/// Note that `BufferedWriter` will NOT flush its buffer when dropped. +/// This writer will be flushed when it is dropped. /// /// # Example /// @@ -130,7 +131,7 @@ impl<R: Reader> Reader for BufferedReader<R> { /// writer.flush(); /// ``` pub struct BufferedWriter<W> { - priv inner: W, + priv inner: Option<W>, priv buf: ~[u8], priv pos: uint } @@ -142,7 +143,7 @@ impl<W: Writer> BufferedWriter<W> { let mut buf = vec::with_capacity(cap); unsafe { buf.set_len(cap); } BufferedWriter { - inner: inner, + inner: Some(inner), buf: buf, pos: 0 } @@ -155,7 +156,7 @@ impl<W: Writer> BufferedWriter<W> { fn flush_buf(&mut self) -> IoResult<()> { if self.pos != 0 { - let ret = self.inner.write(self.buf.slice_to(self.pos)); + let ret = self.inner.get_mut_ref().write(self.buf.slice_to(self.pos)); self.pos = 0; ret } else { @@ -167,15 +168,15 @@ impl<W: Writer> BufferedWriter<W> { /// /// This type does not expose the ability to get a mutable reference to the /// underlying reader because that could possibly corrupt the buffer. - pub fn get_ref<'a>(&'a self) -> &'a W { &self.inner } + pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.get_ref() } /// Unwraps this buffer, returning the underlying writer. /// /// The buffer is flushed before returning the writer. pub fn unwrap(mut self) -> W { - // FIXME: is failing the right thing to do if flushing fails? + // FIXME(#12628): is failing the right thing to do if flushing fails? self.flush_buf().unwrap(); - self.inner + self.inner.take_unwrap() } } @@ -186,7 +187,7 @@ impl<W: Writer> Writer for BufferedWriter<W> { } if buf.len() > self.buf.len() { - self.inner.write(buf) + self.inner.get_mut_ref().write(buf) } else { let dst = self.buf.mut_slice_from(self.pos); vec::bytes::copy_memory(dst, buf); @@ -196,14 +197,24 @@ impl<W: Writer> Writer for BufferedWriter<W> { } fn flush(&mut self) -> IoResult<()> { - self.flush_buf().and_then(|()| self.inner.flush()) + self.flush_buf().and_then(|()| self.inner.get_mut_ref().flush()) + } +} + +#[unsafe_destructor] +impl<W: Writer> Drop for BufferedWriter<W> { + fn drop(&mut self) { + if self.inner.is_some() { + // FIXME(#12628): should this error be ignored? + let _ = self.flush_buf(); + } } } /// Wraps a Writer and buffers output to it, flushing whenever a newline (`0x0a`, /// `'\n'`) is detected. /// -/// Note that this structure does NOT flush the output when dropped. +/// This writer will be flushed when it is dropped. pub struct LineBufferedWriter<W> { priv inner: BufferedWriter<W>, } @@ -256,13 +267,13 @@ impl<W> InternalBufferedWriter<W> { impl<W: Reader> Reader for InternalBufferedWriter<W> { fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { - self.get_mut_ref().inner.read(buf) + self.get_mut_ref().inner.get_mut_ref().read(buf) } } -/// Wraps a Stream and buffers input and output to and from it +/// Wraps a Stream and buffers input and output to and from it. /// -/// Note that `BufferedStream` will NOT flush its output buffer when dropped. +/// The output half will be flushed when this stream is dropped. /// /// # Example /// |
