diff options
| author | Fenrir <[email protected]> | 2018-01-21 14:06:28 -0700 |
|---|---|---|
| committer | FenrirWolf <[email protected]> | 2018-01-21 19:16:33 -0700 |
| commit | 23be3f4885688e5e0011005e2295c75168854c0a (patch) | |
| tree | dd0850f9c73c489e114a761d5c0757f3dbec3a65 /ctr-std/src/io/stdio.rs | |
| parent | Update CI for Rust nightly-2017-12-01 + other fixes (diff) | |
| download | archived-ctru-rs-23be3f4885688e5e0011005e2295c75168854c0a.tar.xz archived-ctru-rs-23be3f4885688e5e0011005e2295c75168854c0a.zip | |
Recreate ctr-std from latest nightly
Diffstat (limited to 'ctr-std/src/io/stdio.rs')
| -rw-r--r-- | ctr-std/src/io/stdio.rs | 90 |
1 files changed, 52 insertions, 38 deletions
diff --git a/ctr-std/src/io/stdio.rs b/ctr-std/src/io/stdio.rs index e16e801..831688b 100644 --- a/ctr-std/src/io/stdio.rs +++ b/ctr-std/src/io/stdio.rs @@ -13,11 +13,11 @@ use io::prelude::*; use cell::RefCell; use fmt; use io::lazy::Lazy; -use io::{self, BufReader, LineWriter}; +use io::{self, Initializer, BufReader, LineWriter}; use sync::{Arc, Mutex, MutexGuard}; use sys::stdio; use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; -use thread::LocalKeyState; +use thread::{LocalKey, LocalKeyState}; /// Stdout used by print! and println! macros thread_local! { @@ -75,8 +75,10 @@ fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) } impl Read for StdinRaw { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { - self.0.read_to_end(buf) + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } impl Write for StdoutRaw { @@ -116,19 +118,11 @@ impl<R: io::Read> io::Read for Maybe<R> { Maybe::Fake => Ok(0) } } - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { - match *self { - Maybe::Real(ref mut r) => handle_ebadf(r.read_to_end(buf), 0), - Maybe::Fake => Ok(0) - } - } } fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> { - use sys::stdio::EBADF_ERR; - match r { - Err(ref e) if e.raw_os_error() == Some(EBADF_ERR) => Ok(default), + Err(ref e) if stdio::is_ebadf(e) => Ok(default), r => r } } @@ -294,6 +288,10 @@ impl Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.lock().read(buf) } + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { self.lock().read_to_end(buf) } @@ -310,8 +308,9 @@ impl<'a> Read for StdinLock<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.inner.read(buf) } - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { - self.inner.read_to_end(buf) + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() } } @@ -332,11 +331,11 @@ impl<'a> fmt::Debug for StdinLock<'a> { /// /// Each handle shares a global buffer of data to be written to the standard /// output stream. Access is also synchronized via a lock and explicit control -/// over locking is available via the [`lock()`] method. +/// over locking is available via the [`lock`] method. /// /// Created by the [`io::stdout`] method. /// -/// [`lock()`]: #method.lock +/// [`lock`]: #method.lock /// [`io::stdout`]: fn.stdout.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Stdout { @@ -659,41 +658,56 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { }) } -#[unstable(feature = "print", - reason = "implementation detail which may disappear or be replaced at any time", - issue = "0")] -#[doc(hidden)] -pub fn _print(args: fmt::Arguments) { - // As an implementation of the `println!` macro, we want to try our best to - // not panic wherever possible and get the output somewhere. There are - // currently two possible vectors for panics we take care of here: - // - // 1. If the TLS key for the local stdout has been destroyed, accessing it - // would cause a panic. Note that we just lump in the uninitialized case - // here for convenience, we're not trying to avoid a panic. - // 2. If the local stdout is currently in use (e.g. we're in the middle of - // already printing) then accessing again would cause a panic. - // - // If, however, the actual I/O causes an error, we do indeed panic. - let result = match LOCAL_STDOUT.state() { +/// Write `args` to output stream `local_s` if possible, `global_s` +/// otherwise. `label` identifies the stream in a panic message. +/// +/// This function is used to print error messages, so it takes extra +/// care to avoid causing a panic when `local_stream` is unusable. +/// For instance, if the TLS key for the local stream is uninitialized +/// or already destroyed, or if the local stream is locked by another +/// thread, it will just fall back to the global stream. +/// +/// However, if the actual I/O causes an error, this function does panic. +fn print_to<T>(args: fmt::Arguments, + local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>, + global_s: fn() -> T, + label: &str) where T: Write { + let result = match local_s.state() { LocalKeyState::Uninitialized | - LocalKeyState::Destroyed => stdout().write_fmt(args), + LocalKeyState::Destroyed => global_s().write_fmt(args), LocalKeyState::Valid => { - LOCAL_STDOUT.with(|s| { + local_s.with(|s| { if let Ok(mut borrowed) = s.try_borrow_mut() { if let Some(w) = borrowed.as_mut() { return w.write_fmt(args); } } - stdout().write_fmt(args) + global_s().write_fmt(args) }) } }; if let Err(e) = result { - panic!("failed printing to stdout: {}", e); + panic!("failed printing to {}: {}", label, e); } } +#[unstable(feature = "print_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "0")] +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + print_to(args, &LOCAL_STDOUT, stdout, "stdout"); +} + +#[unstable(feature = "print_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "0")] +#[doc(hidden)] +pub fn _eprint(args: fmt::Arguments) { + use panicking::LOCAL_STDERR; + print_to(args, &LOCAL_STDERR, stderr, "stderr"); +} + #[cfg(test)] mod tests { use thread; |