@@ -8,7 +8,6 @@ use crate::io::prelude::*;
88use crate :: cell:: { Cell , RefCell } ;
99use crate :: fmt;
1010use crate :: io:: { self , BufReader , IoSlice , IoSliceMut , LineWriter , Lines } ;
11- use crate :: pin:: Pin ;
1211use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
1312use crate :: sync:: { Arc , Mutex , MutexGuard , OnceLock } ;
1413use crate :: sys:: stdio;
@@ -526,7 +525,7 @@ pub struct Stdout {
526525 // FIXME: this should be LineWriter or BufWriter depending on the state of
527526 // stdout (tty or not). Note that if this is not line buffered it
528527 // should also flush-on-panic or some form of flush-on-abort.
529- inner : Pin < & ' static ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > ,
528+ inner : & ' static ReentrantMutex < RefCell < Option < LineWriter < StdoutRaw > > > > ,
530529}
531530
532531/// A locked reference to the [`Stdout`] handle.
@@ -548,10 +547,11 @@ pub struct Stdout {
548547#[ must_use = "if unused stdout will immediately unlock" ]
549548#[ stable( feature = "rust1" , since = "1.0.0" ) ]
550549pub struct StdoutLock < ' a > {
551- inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < StdoutRaw > > > ,
550+ inner : ReentrantMutexGuard < ' a , RefCell < Option < LineWriter < StdoutRaw > > > > ,
552551}
553552
554- static STDOUT : OnceLock < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > = OnceLock :: new ( ) ;
553+ static STDOUT : ReentrantMutex < RefCell < Option < LineWriter < StdoutRaw > > > > =
554+ ReentrantMutex :: new ( RefCell :: new ( None ) ) ;
555555
556556/// Constructs a new handle to the standard output of the current process.
557557///
@@ -602,25 +602,18 @@ static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLo
602602#[ must_use]
603603#[ stable( feature = "rust1" , since = "1.0.0" ) ]
604604pub fn stdout ( ) -> Stdout {
605- Stdout {
606- inner : Pin :: static_ref ( & STDOUT ) . get_or_init_pin (
607- || unsafe { ReentrantMutex :: new ( RefCell :: new ( LineWriter :: new ( stdout_raw ( ) ) ) ) } ,
608- |mutex| unsafe { mutex. init ( ) } ,
609- ) ,
610- }
605+ Stdout { inner : & STDOUT }
611606}
612607
613608pub fn cleanup ( ) {
614- if let Some ( instance) = STDOUT . get ( ) {
615- // Flush the data and disable buffering during shutdown
616- // by replacing the line writer by one with zero
617- // buffering capacity.
618- // We use try_lock() instead of lock(), because someone
619- // might have leaked a StdoutLock, which would
620- // otherwise cause a deadlock here.
621- if let Some ( lock) = Pin :: static_ref ( instance) . try_lock ( ) {
622- * lock. borrow_mut ( ) = LineWriter :: with_capacity ( 0 , stdout_raw ( ) ) ;
623- }
609+ // Flush the data and disable buffering during shutdown
610+ // by replacing the line writer by one with zero
611+ // buffering capacity.
612+ // We use try_lock() instead of lock(), because someone
613+ // might have leaked a StdoutLock, which would
614+ // otherwise cause a deadlock here.
615+ if let Some ( lock) = STDOUT . try_lock ( ) {
616+ * lock. borrow_mut ( ) = Some ( LineWriter :: with_capacity ( 0 , stdout_raw ( ) ) ) ;
624617 }
625618}
626619
@@ -670,7 +663,7 @@ impl Write for Stdout {
670663 }
671664 #[ inline]
672665 fn is_write_vectored ( & self ) -> bool {
673- io :: Write :: is_write_vectored ( & & * self )
666+ stdout_raw ( ) . is_write_vectored ( )
674667 }
675668 fn flush ( & mut self ) -> io:: Result < ( ) > {
676669 ( & * self ) . flush ( )
@@ -696,7 +689,7 @@ impl Write for &Stdout {
696689 }
697690 #[ inline]
698691 fn is_write_vectored ( & self ) -> bool {
699- self . lock ( ) . is_write_vectored ( )
692+ stdout_raw ( ) . is_write_vectored ( )
700693 }
701694 fn flush ( & mut self ) -> io:: Result < ( ) > {
702695 self . lock ( ) . flush ( )
@@ -712,26 +705,37 @@ impl Write for &Stdout {
712705 }
713706}
714707
708+ impl StdoutLock < ' _ > {
709+ #[ inline]
710+ fn with_inner < F , R > ( & mut self , f : F ) -> R
711+ where
712+ F : FnOnce ( & mut LineWriter < StdoutRaw > ) -> R ,
713+ {
714+ let mut inner = self . inner . borrow_mut ( ) ;
715+ f ( inner. get_or_insert_with ( || LineWriter :: new ( stdout_raw ( ) ) ) )
716+ }
717+ }
718+
715719#[ stable( feature = "rust1" , since = "1.0.0" ) ]
716720impl Write for StdoutLock < ' _ > {
717721 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
718- self . inner . borrow_mut ( ) . write ( buf)
722+ self . with_inner ( |stdout| stdout . write ( buf) )
719723 }
720724 fn write_vectored ( & mut self , bufs : & [ IoSlice < ' _ > ] ) -> io:: Result < usize > {
721- self . inner . borrow_mut ( ) . write_vectored ( bufs)
725+ self . with_inner ( |stdout| stdout . write_vectored ( bufs) )
722726 }
723727 #[ inline]
724728 fn is_write_vectored ( & self ) -> bool {
725- self . inner . borrow_mut ( ) . is_write_vectored ( )
729+ stdout_raw ( ) . is_write_vectored ( )
726730 }
727731 fn flush ( & mut self ) -> io:: Result < ( ) > {
728- self . inner . borrow_mut ( ) . flush ( )
732+ self . with_inner ( |stdout| stdout . flush ( ) )
729733 }
730734 fn write_all ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
731- self . inner . borrow_mut ( ) . write_all ( buf)
735+ self . with_inner ( |stdout| stdout . write_all ( buf) )
732736 }
733737 fn write_all_vectored ( & mut self , bufs : & mut [ IoSlice < ' _ > ] ) -> io:: Result < ( ) > {
734- self . inner . borrow_mut ( ) . write_all_vectored ( bufs)
738+ self . with_inner ( |stdout| stdout . write_all_vectored ( bufs) )
735739 }
736740}
737741
@@ -761,7 +765,7 @@ impl fmt::Debug for StdoutLock<'_> {
761765/// standard library or via raw Windows API calls, will fail.
762766#[ stable( feature = "rust1" , since = "1.0.0" ) ]
763767pub struct Stderr {
764- inner : Pin < & ' static ReentrantMutex < RefCell < StderrRaw > > > ,
768+ inner : & ' static ReentrantMutex < RefCell < StderrRaw > > ,
765769}
766770
767771/// A locked reference to the [`Stderr`] handle.
@@ -834,16 +838,12 @@ pub struct StderrLock<'a> {
834838#[ stable( feature = "rust1" , since = "1.0.0" ) ]
835839pub fn stderr ( ) -> Stderr {
836840 // Note that unlike `stdout()` we don't use `at_exit` here to register a
837- // destructor. Stderr is not buffered , so there's no need to run a
841+ // destructor. Stderr is not buffered, so there's no need to run a
838842 // destructor for flushing the buffer
839- static INSTANCE : OnceLock < ReentrantMutex < RefCell < StderrRaw > > > = OnceLock :: new ( ) ;
843+ static INSTANCE : ReentrantMutex < RefCell < StderrRaw > > =
844+ ReentrantMutex :: new ( RefCell :: new ( stderr_raw ( ) ) ) ;
840845
841- Stderr {
842- inner : Pin :: static_ref ( & INSTANCE ) . get_or_init_pin (
843- || unsafe { ReentrantMutex :: new ( RefCell :: new ( stderr_raw ( ) ) ) } ,
844- |mutex| unsafe { mutex. init ( ) } ,
845- ) ,
846- }
846+ Stderr { inner : & INSTANCE }
847847}
848848
849849impl Stderr {
0 commit comments