diff options
| author | Steven Fackler <sfackler@gmail.com> | 2017-05-14 21:29:18 -0400 |
|---|---|---|
| committer | Steven Fackler <sfackler@gmail.com> | 2017-06-20 20:26:22 -0700 |
| commit | ecbb896b9eb2acadefde57be493e4298c1aa04a3 (patch) | |
| tree | f46da3b3294c60abfb2343638c79f51124ac95c0 /src/libstd/sys_common | |
| parent | 445077963c55297ef1e196a3525723090fe80b22 (diff) | |
| download | rust-ecbb896b9eb2acadefde57be493e4298c1aa04a3.tar.gz rust-ecbb896b9eb2acadefde57be493e4298c1aa04a3.zip | |
Add `Read::initializer`.
This is an API that allows types to indicate that they can be passed buffers of uninitialized memory which can improve performance.
Diffstat (limited to 'src/libstd/sys_common')
| -rw-r--r-- | src/libstd/sys_common/io.rs | 129 | ||||
| -rw-r--r-- | src/libstd/sys_common/net.rs | 4 |
2 files changed, 0 insertions, 133 deletions
diff --git a/src/libstd/sys_common/io.rs b/src/libstd/sys_common/io.rs index 23daeeb5187..ab23936358e 100644 --- a/src/libstd/sys_common/io.rs +++ b/src/libstd/sys_common/io.rs @@ -7,51 +7,8 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use io; -use io::ErrorKind; -use io::Read; -use slice::from_raw_parts_mut; - pub const DEFAULT_BUF_SIZE: usize = 8 * 1024; -// Provides read_to_end functionality over an uninitialized buffer. -// This function is unsafe because it calls the underlying -// read function with a slice into uninitialized memory. The default -// implementation of read_to_end for readers will zero out new memory in -// the buf before passing it to read, but avoiding this zero can often -// lead to a fairly significant performance win. -// -// Implementations using this method have to adhere to two guarantees: -// * The implementation of read never reads the buffer provided. -// * The implementation of read correctly reports how many bytes were written. -pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec<u8>) -> io::Result<usize> { - - let start_len = buf.len(); - buf.reserve(16); - - // Always try to read into the empty space of the vector (from the length to the capacity). - // If the vector ever fills up then we reserve an extra byte which should trigger the normal - // reallocation routines for the vector, which will likely double the size. - // - // This function is similar to the read_to_end function in std::io, but the logic about - // reservations and slicing is different enough that this is duplicated here. - loop { - if buf.len() == buf.capacity() { - buf.reserve(1); - } - - let buf_slice = from_raw_parts_mut(buf.as_mut_ptr().offset(buf.len() as isize), - buf.capacity() - buf.len()); - - match r.read(buf_slice) { - Ok(0) => { return Ok(buf.len() - start_len); } - Ok(n) => { let len = buf.len() + n; buf.set_len(len); }, - Err(ref e) if e.kind() == ErrorKind::Interrupted => { } - Err(e) => { return Err(e); } - } - } -} - #[cfg(test)] #[allow(dead_code)] // not used on emscripten pub mod test { @@ -91,89 +48,3 @@ pub mod test { TempDir(ret) } } - -#[cfg(test)] -mod tests { - use io::prelude::*; - use super::*; - use io; - use io::{ErrorKind, Take, Repeat, repeat}; - use slice::from_raw_parts; - - struct ErrorRepeat { - lr: Take<Repeat> - } - - fn error_repeat(byte: u8, limit: u64) -> ErrorRepeat { - ErrorRepeat { lr: repeat(byte).take(limit) } - } - - impl Read for ErrorRepeat { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - let ret = self.lr.read(buf); - if let Ok(0) = ret { - return Err(io::Error::new(ErrorKind::Other, "")) - } - ret - } - } - - fn init_vec_data() -> Vec<u8> { - let mut vec = vec![10u8; 200]; - unsafe { vec.set_len(0); } - vec - } - - fn assert_all_eq(buf: &[u8], value: u8) { - for n in buf { - assert_eq!(*n, value); - } - } - - fn validate(buf: &Vec<u8>, good_read_len: usize) { - assert_all_eq(buf, 1u8); - let cap = buf.capacity(); - let end_slice = unsafe { from_raw_parts(buf.as_ptr().offset(good_read_len as isize), - cap - good_read_len) }; - assert_all_eq(end_slice, 10u8); - } - - #[test] - fn read_to_end_uninit_error() { - let mut er = error_repeat(1,100); - let mut vec = init_vec_data(); - if let Err(_) = unsafe { read_to_end_uninitialized(&mut er, &mut vec) } { - validate(&vec, 100); - } else { - assert!(false); - } - } - - #[test] - fn read_to_end_uninit_zero_len_vec() { - let mut er = repeat(1).take(100); - let mut vec = Vec::new(); - let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() }; - assert_all_eq(&vec, 1u8); - assert_eq!(vec.len(), n); - } - - #[test] - fn read_to_end_uninit_good() { - let mut er = repeat(1).take(100); - let mut vec = init_vec_data(); - let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() }; - validate(&vec, 100); - assert_eq!(vec.len(), n); - } - - #[bench] - #[cfg_attr(target_os = "emscripten", ignore)] - fn bench_uninitialized(b: &mut ::test::Bencher) { - b.iter(|| { - let mut lr = repeat(1).take(10000000); - let mut vec = Vec::with_capacity(1024); - unsafe { read_to_end_uninitialized(&mut lr, &mut vec) } - }); - } -} diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index a1897c8bd67..809b728379d 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -243,10 +243,6 @@ impl TcpStream { self.inner.read(buf) } - pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { - self.inner.read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result<usize> { let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t; let ret = cvt(unsafe { |
