@@ -7,7 +7,7 @@ use crate::io::prelude::*;
77
88use crate :: cell:: { Cell , RefCell } ;
99use crate :: fmt;
10- use crate :: io:: { self , BufReader , IoSlice , IoSliceMut , LineWriter , Lines } ;
10+ use crate :: io:: { self , buffered :: SwitchWriter , BufReader , BufferMode , IoSlice , IoSliceMut , Lines } ;
1111use crate :: lazy:: SyncOnceCell ;
1212use crate :: pin:: Pin ;
1313use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
@@ -524,10 +524,7 @@ impl fmt::Debug for StdinLock<'_> {
524524/// [`io::stdout`]: stdout
525525#[ stable( feature = "rust1" , since = "1.0.0" ) ]
526526pub struct Stdout {
527- // FIXME: this should be LineWriter or BufWriter depending on the state of
528- // stdout (tty or not). Note that if this is not line buffered it
529- // should also flush-on-panic or some form of flush-on-abort.
530- inner : Pin < & ' static ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > ,
527+ inner : Pin < & ' static ReentrantMutex < RefCell < SwitchWriter < StdoutRaw > > > > ,
531528}
532529
533530/// A locked reference to the [`Stdout`] handle.
@@ -549,10 +546,10 @@ pub struct Stdout {
549546#[ must_use = "if unused stdout will immediately unlock" ]
550547#[ stable( feature = "rust1" , since = "1.0.0" ) ]
551548pub struct StdoutLock < ' a > {
552- inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < StdoutRaw > > > ,
549+ inner : ReentrantMutexGuard < ' a , RefCell < SwitchWriter < StdoutRaw > > > ,
553550}
554551
555- static STDOUT : SyncOnceCell < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > = SyncOnceCell :: new ( ) ;
552+ static STDOUT : SyncOnceCell < ReentrantMutex < RefCell < SwitchWriter < StdoutRaw > > > > = SyncOnceCell :: new ( ) ;
556553
557554/// Constructs a new handle to the standard output of the current process.
558555///
@@ -605,7 +602,12 @@ static STDOUT: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Sy
605602pub fn stdout ( ) -> Stdout {
606603 Stdout {
607604 inner : Pin :: static_ref ( & STDOUT ) . get_or_init_pin (
608- || unsafe { ReentrantMutex :: new ( RefCell :: new ( LineWriter :: new ( stdout_raw ( ) ) ) ) } ,
605+ || unsafe {
606+ ReentrantMutex :: new ( RefCell :: new ( SwitchWriter :: new (
607+ stdout_raw ( ) ,
608+ stdio:: default_stdout_buffer_mode ( ) ,
609+ ) ) )
610+ } ,
609611 |mutex| unsafe { mutex. init ( ) } ,
610612 ) ,
611613 }
@@ -614,13 +616,14 @@ pub fn stdout() -> Stdout {
614616pub fn cleanup ( ) {
615617 if let Some ( instance) = STDOUT . get ( ) {
616618 // Flush the data and disable buffering during shutdown
617- // by replacing the line writer by one with zero
618- // buffering capacity.
619619 // We use try_lock() instead of lock(), because someone
620620 // might have leaked a StdoutLock, which would
621621 // otherwise cause a deadlock here.
622622 if let Some ( lock) = Pin :: static_ref ( instance) . try_lock ( ) {
623- * lock. borrow_mut ( ) = LineWriter :: with_capacity ( 0 , stdout_raw ( ) ) ;
623+ if let Ok ( mut instance) = lock. try_borrow_mut ( ) {
624+ let _ = instance. flush ( ) ;
625+ instance. set_mode ( BufferMode :: Immediate ) ;
626+ }
624627 }
625628 }
626629}
@@ -713,6 +716,20 @@ impl Write for &Stdout {
713716 }
714717}
715718
719+ impl StdoutLock < ' _ > {
720+ /// Get the current global stdout buffering mode
721+ #[ unstable( feature = "stdout_switchable_buffering" , issue = "78515" ) ]
722+ pub fn buffer_mode ( & self ) -> BufferMode {
723+ self . inner . borrow ( ) . mode ( )
724+ }
725+
726+ /// Set the current global stdout buffering mode
727+ #[ unstable( feature = "stdout_switchable_buffering" , issue = "78515" ) ]
728+ pub fn set_buffer_mode ( & mut self , mode : BufferMode ) {
729+ self . inner . borrow_mut ( ) . set_mode ( mode)
730+ }
731+ }
732+
716733#[ stable( feature = "rust1" , since = "1.0.0" ) ]
717734impl Write for StdoutLock < ' _ > {
718735 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
@@ -734,6 +751,8 @@ impl Write for StdoutLock<'_> {
734751 fn write_all_vectored ( & mut self , bufs : & mut [ IoSlice < ' _ > ] ) -> io:: Result < ( ) > {
735752 self . inner . borrow_mut ( ) . write_all_vectored ( bufs)
736753 }
754+ // Don't specialize write_fmt because we need to be sure we don't
755+ // reentrantly call borrow_mut
737756}
738757
739758#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
0 commit comments