@@ -7,7 +7,7 @@ use crate::io::prelude::*;
7
7
8
8
use crate :: cell:: { Cell , RefCell } ;
9
9
use crate :: fmt;
10
- use crate :: io:: { self , BufReader , IoSlice , IoSliceMut , LineWriter , Lines } ;
10
+ use crate :: io:: { self , buffered :: SwitchWriter , BufReader , BufferMode , IoSlice , IoSliceMut , Lines } ;
11
11
use crate :: lazy:: SyncOnceCell ;
12
12
use crate :: pin:: Pin ;
13
13
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
@@ -524,10 +524,7 @@ impl fmt::Debug for StdinLock<'_> {
524
524
/// [`io::stdout`]: stdout
525
525
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
526
526
pub 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 > > > > ,
531
528
}
532
529
533
530
/// A locked reference to the [`Stdout`] handle.
@@ -549,10 +546,10 @@ pub struct Stdout {
549
546
#[ must_use = "if unused stdout will immediately unlock" ]
550
547
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
551
548
pub struct StdoutLock < ' a > {
552
- inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < StdoutRaw > > > ,
549
+ inner : ReentrantMutexGuard < ' a , RefCell < SwitchWriter < StdoutRaw > > > ,
553
550
}
554
551
555
- static STDOUT : SyncOnceCell < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > = SyncOnceCell :: new ( ) ;
552
+ static STDOUT : SyncOnceCell < ReentrantMutex < RefCell < SwitchWriter < StdoutRaw > > > > = SyncOnceCell :: new ( ) ;
556
553
557
554
/// Constructs a new handle to the standard output of the current process.
558
555
///
@@ -605,7 +602,12 @@ static STDOUT: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Sy
605
602
pub fn stdout ( ) -> Stdout {
606
603
Stdout {
607
604
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
+ } ,
609
611
|mutex| unsafe { mutex. init ( ) } ,
610
612
) ,
611
613
}
@@ -614,13 +616,14 @@ pub fn stdout() -> Stdout {
614
616
pub fn cleanup ( ) {
615
617
if let Some ( instance) = STDOUT . get ( ) {
616
618
// Flush the data and disable buffering during shutdown
617
- // by replacing the line writer by one with zero
618
- // buffering capacity.
619
619
// We use try_lock() instead of lock(), because someone
620
620
// might have leaked a StdoutLock, which would
621
621
// otherwise cause a deadlock here.
622
622
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
+ }
624
627
}
625
628
}
626
629
}
@@ -713,6 +716,20 @@ impl Write for &Stdout {
713
716
}
714
717
}
715
718
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
+
716
733
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
717
734
impl Write for StdoutLock < ' _ > {
718
735
fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
@@ -734,6 +751,8 @@ impl Write for StdoutLock<'_> {
734
751
fn write_all_vectored ( & mut self , bufs : & mut [ IoSlice < ' _ > ] ) -> io:: Result < ( ) > {
735
752
self . inner . borrow_mut ( ) . write_all_vectored ( bufs)
736
753
}
754
+ // Don't specialize write_fmt because we need to be sure we don't
755
+ // reentrantly call borrow_mut
737
756
}
738
757
739
758
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
0 commit comments