Skip to content

Commit

Permalink
Remove wrapper type handling absent raw standard streams
Browse files Browse the repository at this point in the history
Raw standard streams are always available.  Remove unused wrapper type
that was supposed to be responsible for handling their absence.
  • Loading branch information
tmiasko committed Aug 21, 2020
1 parent 4a00421 commit 78e0946
Showing 1 changed file with 33 additions and 100 deletions.
133 changes: 33 additions & 100 deletions library/std/src/io/stdio.rs
Expand Up @@ -83,11 +83,11 @@ const fn stderr_raw() -> StderrRaw {

impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
handle_ebadf(self.0.read(buf), 0)
}

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.0.read_vectored(bufs)
handle_ebadf(self.0.read_vectored(bufs), 0)
}

#[inline]
Expand All @@ -101,25 +101,22 @@ impl Read for StdinRaw {
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.read_to_end(buf)
handle_ebadf(self.0.read_to_end(buf), 0)
}

fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
self.0.read_to_string(buf)
}

fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
self.0.read_exact(buf)
handle_ebadf(self.0.read_to_string(buf), 0)
}
}

impl Write for StdoutRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
handle_ebadf(self.0.write(buf), buf.len())
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs)
let total = bufs.iter().map(|b| b.len()).sum();
handle_ebadf(self.0.write_vectored(bufs), total)
}

#[inline]
Expand All @@ -128,29 +125,30 @@ impl Write for StdoutRaw {
}

fn flush(&mut self) -> io::Result<()> {
self.0.flush()
handle_ebadf(self.0.flush(), ())
}

fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.0.write_all(buf)
handle_ebadf(self.0.write_all(buf), ())
}

fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
self.0.write_all_vectored(bufs)
handle_ebadf(self.0.write_all_vectored(bufs), ())
}

fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
self.0.write_fmt(fmt)
handle_ebadf(self.0.write_fmt(fmt), ())
}
}

impl Write for StderrRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
handle_ebadf(self.0.write(buf), buf.len())
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs)
let total = bufs.iter().map(|b| b.len()).sum();
handle_ebadf(self.0.write_vectored(bufs), total)
}

#[inline]
Expand All @@ -159,80 +157,19 @@ impl Write for StderrRaw {
}

fn flush(&mut self) -> io::Result<()> {
self.0.flush()
handle_ebadf(self.0.flush(), ())
}

fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.0.write_all(buf)
handle_ebadf(self.0.write_all(buf), ())
}

fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
self.0.write_all_vectored(bufs)
handle_ebadf(self.0.write_all_vectored(bufs), ())
}

fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
self.0.write_fmt(fmt)
}
}

enum Maybe<T> {
Real(T),
Fake,
}

impl<W: io::Write> io::Write for Maybe<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match *self {
Maybe::Real(ref mut w) => handle_ebadf(w.write(buf), buf.len()),
Maybe::Fake => Ok(buf.len()),
}
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let total = bufs.iter().map(|b| b.len()).sum();
match self {
Maybe::Real(w) => handle_ebadf(w.write_vectored(bufs), total),
Maybe::Fake => Ok(total),
}
}

#[inline]
fn is_write_vectored(&self) -> bool {
match self {
Maybe::Real(w) => w.is_write_vectored(),
Maybe::Fake => true,
}
}

fn flush(&mut self) -> io::Result<()> {
match *self {
Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
Maybe::Fake => Ok(()),
}
}
}

impl<R: io::Read> io::Read for Maybe<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match *self {
Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0),
Maybe::Fake => Ok(0),
}
}

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
match self {
Maybe::Real(r) => handle_ebadf(r.read_vectored(bufs), 0),
Maybe::Fake => Ok(0),
}
}

#[inline]
fn is_read_vectored(&self) -> bool {
match self {
Maybe::Real(w) => w.is_read_vectored(),
Maybe::Fake => true,
}
handle_ebadf(self.0.write_fmt(fmt), ())
}
}

Expand Down Expand Up @@ -277,7 +214,7 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdin {
inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
inner: Arc<Mutex<BufReader<StdinRaw>>>,
}

/// A locked reference to the `Stdin` handle.
Expand Down Expand Up @@ -308,7 +245,7 @@ pub struct Stdin {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdinLock<'a> {
inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
inner: MutexGuard<'a, BufReader<StdinRaw>>,
}

/// Constructs a new handle to the standard input of the current process.
Expand Down Expand Up @@ -352,14 +289,14 @@ pub struct StdinLock<'a> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = Lazy::new();
return Stdin {
inner: unsafe { INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown") },
};

fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
// This must not reentrantly access `INSTANCE`
let stdin = Maybe::Real(stdin_raw());
let stdin = stdin_raw();
Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin)))
}
}
Expand Down Expand Up @@ -536,7 +473,7 @@ pub struct Stdout {
// FIXME: this should be LineWriter or BufWriter depending on the state of
// stdout (tty or not). Note that if this is not line buffered it
// should also flush-on-panic or some form of flush-on-abort.
inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
inner: Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
}

/// A locked reference to the `Stdout` handle.
Expand All @@ -550,7 +487,7 @@ pub struct Stdout {
/// an error.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdoutLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
}

/// Constructs a new handle to the standard output of the current process.
Expand Down Expand Up @@ -594,14 +531,14 @@ pub struct StdoutLock<'a> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Lazy::new();
return Stdout {
inner: unsafe { INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown") },
};

fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> {
// This must not reentrantly access `INSTANCE`
let stdout = Maybe::Real(stdout_raw());
let stdout = stdout_raw();
unsafe {
let ret = Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))));
ret.init();
Expand Down Expand Up @@ -711,7 +648,7 @@ impl fmt::Debug for StdoutLock<'_> {
/// an error.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
inner: &'static ReentrantMutex<RefCell<Maybe<StderrRaw>>>,
inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
}

/// A locked reference to the `Stderr` handle.
Expand All @@ -725,7 +662,7 @@ pub struct Stderr {
/// an error.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StderrLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
}

/// Constructs a new handle to the standard error of the current process.
Expand Down Expand Up @@ -774,18 +711,14 @@ pub fn stderr() -> Stderr {
//
// This has the added benefit of allowing `stderr` to be usable during
// process shutdown as well!
static INSTANCE: ReentrantMutex<RefCell<Maybe<StderrRaw>>> =
unsafe { ReentrantMutex::new(RefCell::new(Maybe::Fake)) };
static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) };

// When accessing stderr we need one-time initialization of the reentrant
// mutex, followed by one-time detection of whether we actually have a
// stderr handle or not. Afterwards we can just always use the now-filled-in
// `INSTANCE` value.
// mutex. Afterwards we can just always use the now-filled-in `INSTANCE` value.
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
INSTANCE.init();
let stderr = stderr_raw();
*INSTANCE.lock().borrow_mut() = Maybe::Real(stderr);
});
Stderr { inner: &INSTANCE }
}
Expand Down

0 comments on commit 78e0946

Please sign in to comment.