use crate::fmt;
use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter};
use crate::lazy::SyncOnceCell;
+use crate::pin::Pin;
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{Mutex, MutexGuard};
use crate::sys::stdio;
// 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: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
+ inner: Pin<&'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
}
/// A locked reference to the `Stdout` handle.
pub fn stdout() -> Stdout {
static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> =
SyncOnceCell::new();
+
+ fn cleanup() {
+ if let Some(instance) = INSTANCE.get() {
+ // Flush the data and disable buffering during shutdown
+ // by replacing the line writer by one with zero
+ // buffering capacity.
+ // We use try_lock() instead of lock(), because someone
+ // might have leaked a StdoutLock, which would
+ // otherwise cause a deadlock here.
+ if let Some(lock) = Pin::static_ref(instance).try_lock() {
+ *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
+ }
+ }
+ }
+
Stdout {
- inner: INSTANCE.get_or_init(|| unsafe {
- let _ = sys_common::at_exit(|| {
- if let Some(instance) = INSTANCE.get() {
- // Flush the data and disable buffering during shutdown
- // by replacing the line writer by one with zero
- // buffering capacity.
- // We use try_lock() instead of lock(), because someone
- // might have leaked a StdoutLock, which would
- // otherwise cause a deadlock here.
- if let Some(lock) = instance.try_lock() {
- *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
- }
- }
- });
- let r = ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())));
- r.init();
- r
- }),
+ inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
+ || unsafe {
+ let _ = sys_common::at_exit(cleanup);
+ ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))
+ },
+ |mutex| unsafe { mutex.init() },
+ ),
}
}
/// an error.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
- inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
+ inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
}
/// A locked reference to the `Stderr` handle.
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
- // Note that unlike `stdout()` we don't use `Lazy` here which registers a
- // destructor. Stderr is not buffered nor does the `stderr_raw` type consume
- // any owned resources, so there's no need to run any destructors at some
- // point in the future.
- //
- // This has the added benefit of allowing `stderr` to be usable during
- // process shutdown as well!
+ // Note that unlike `stdout()` we don't use `at_exit` here to register a
+ // destructor. Stderr is not buffered , so there's no need to run a
+ // destructor for flushing the buffer
static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<StderrRaw>>> = SyncOnceCell::new();
Stderr {
- inner: INSTANCE.get_or_init(|| unsafe {
- let r = ReentrantMutex::new(RefCell::new(stderr_raw()));
- r.init();
- r
- }),
+ inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
+ || unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) },
+ |mutex| unsafe { mutex.init() },
+ ),
}
}