@@ -10,22 +10,24 @@ use crate::fmt;
10
10
use crate :: io:: { self , BufReader , Initializer , IoSlice , IoSliceMut , LineWriter } ;
11
11
use crate :: lazy:: SyncOnceCell ;
12
12
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
13
- use crate :: sync:: { Mutex , MutexGuard } ;
13
+ use crate :: sync:: { Arc , Mutex , MutexGuard } ;
14
14
use crate :: sys:: stdio;
15
15
use crate :: sys_common;
16
16
use crate :: sys_common:: remutex:: { ReentrantMutex , ReentrantMutexGuard } ;
17
17
use crate :: thread:: LocalKey ;
18
18
19
+ type LocalStream = Arc < Mutex < dyn Write + Send > > ;
20
+
19
21
thread_local ! {
20
22
/// Used by the test crate to capture the output of the print! and println! macros.
21
- static LOCAL_STDOUT : RefCell <Option <Box <dyn LocalOutput > >> = {
23
+ static LOCAL_STDOUT : RefCell <Option <LocalStream >> = {
22
24
RefCell :: new( None )
23
25
}
24
26
}
25
27
26
28
thread_local ! {
27
29
/// Used by the test crate to capture the output of the eprint! and eprintln! macros, and panics.
28
- static LOCAL_STDERR : RefCell <Option <Box <dyn LocalOutput > >> = {
30
+ static LOCAL_STDERR : RefCell <Option <LocalStream >> = {
29
31
RefCell :: new( None )
30
32
}
31
33
}
@@ -888,18 +890,6 @@ impl fmt::Debug for StderrLock<'_> {
888
890
}
889
891
}
890
892
891
- /// A writer than can be cloned to new threads.
892
- #[ unstable(
893
- feature = "set_stdio" ,
894
- reason = "this trait may disappear completely or be replaced \
895
- with a more general mechanism",
896
- issue = "none"
897
- ) ]
898
- #[ doc( hidden) ]
899
- pub trait LocalOutput : Write + Send {
900
- fn clone_box ( & self ) -> Box < dyn LocalOutput > ;
901
- }
902
-
903
893
/// Resets the thread-local stderr handle to the specified writer
904
894
///
905
895
/// This will replace the current thread's stderr handle, returning the old
@@ -915,18 +905,17 @@ pub trait LocalOutput: Write + Send {
915
905
issue = "none"
916
906
) ]
917
907
#[ doc( hidden) ]
918
- pub fn set_panic ( sink : Option < Box < dyn LocalOutput > > ) -> Option < Box < dyn LocalOutput > > {
908
+ pub fn set_panic ( sink : Option < LocalStream > ) -> Option < LocalStream > {
919
909
use crate :: mem;
920
910
if sink. is_none ( ) && !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
921
911
// LOCAL_STDERR is definitely None since LOCAL_STREAMS is false.
922
912
return None ;
923
913
}
924
- let s = LOCAL_STDERR . with ( move |slot| mem :: replace ( & mut * slot . borrow_mut ( ) , sink ) ) . and_then (
925
- | mut s| {
926
- let _ = s. flush ( ) ;
914
+ let s =
915
+ LOCAL_STDERR . with ( move |slot| mem :: replace ( & mut * slot . borrow_mut ( ) , sink ) ) . and_then ( | s| {
916
+ let _ = s. lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) . flush ( ) ;
927
917
Some ( s)
928
- } ,
929
- ) ;
918
+ } ) ;
930
919
LOCAL_STREAMS . store ( true , Ordering :: Relaxed ) ;
931
920
s
932
921
}
@@ -946,35 +935,29 @@ pub fn set_panic(sink: Option<Box<dyn LocalOutput>>) -> Option<Box<dyn LocalOutp
946
935
issue = "none"
947
936
) ]
948
937
#[ doc( hidden) ]
949
- pub fn set_print ( sink : Option < Box < dyn LocalOutput > > ) -> Option < Box < dyn LocalOutput > > {
938
+ pub fn set_print ( sink : Option < LocalStream > ) -> Option < LocalStream > {
950
939
use crate :: mem;
951
940
if sink. is_none ( ) && !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
952
941
// LOCAL_STDOUT is definitely None since LOCAL_STREAMS is false.
953
942
return None ;
954
943
}
955
- let s = LOCAL_STDOUT . with ( move |slot| mem :: replace ( & mut * slot . borrow_mut ( ) , sink ) ) . and_then (
956
- | mut s| {
957
- let _ = s. flush ( ) ;
944
+ let s =
945
+ LOCAL_STDOUT . with ( move |slot| mem :: replace ( & mut * slot . borrow_mut ( ) , sink ) ) . and_then ( | s| {
946
+ let _ = s. lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) . flush ( ) ;
958
947
Some ( s)
959
- } ,
960
- ) ;
948
+ } ) ;
961
949
LOCAL_STREAMS . store ( true , Ordering :: Relaxed ) ;
962
950
s
963
951
}
964
952
965
- pub ( crate ) fn clone_io ( ) -> ( Option < Box < dyn LocalOutput > > , Option < Box < dyn LocalOutput > > ) {
953
+ pub ( crate ) fn clone_io ( ) -> ( Option < LocalStream > , Option < LocalStream > ) {
966
954
// Don't waste time when LOCAL_{STDOUT,STDERR} are definitely None.
967
955
if !LOCAL_STREAMS . load ( Ordering :: Relaxed ) {
968
956
return ( None , None ) ;
969
957
}
970
958
971
959
LOCAL_STDOUT . with ( |stdout| {
972
- LOCAL_STDERR . with ( |stderr| {
973
- (
974
- stdout. borrow ( ) . as_ref ( ) . map ( |o| o. clone_box ( ) ) ,
975
- stderr. borrow ( ) . as_ref ( ) . map ( |o| o. clone_box ( ) ) ,
976
- )
977
- } )
960
+ LOCAL_STDERR . with ( |stderr| ( stdout. borrow ( ) . clone ( ) , stderr. borrow ( ) . clone ( ) ) )
978
961
} )
979
962
}
980
963
@@ -990,7 +973,7 @@ pub(crate) fn clone_io() -> (Option<Box<dyn LocalOutput>>, Option<Box<dyn LocalO
990
973
/// However, if the actual I/O causes an error, this function does panic.
991
974
fn print_to < T > (
992
975
args : fmt:: Arguments < ' _ > ,
993
- local_s : & ' static LocalKey < RefCell < Option < Box < dyn LocalOutput > > > > ,
976
+ local_s : & ' static LocalKey < RefCell < Option < LocalStream > > > ,
994
977
global_s : fn ( ) -> T ,
995
978
label : & str ,
996
979
) where
@@ -1005,8 +988,8 @@ fn print_to<T>(
1005
988
// our printing recursively panics/prints, so the recursive
1006
989
// panic/print goes to the global sink instead of our local sink.
1007
990
let prev = s. borrow_mut ( ) . take ( ) ;
1008
- if let Some ( mut w) = prev {
1009
- let result = w. write_fmt ( args) ;
991
+ if let Some ( w) = prev {
992
+ let result = w. lock ( ) . unwrap_or_else ( |e| e . into_inner ( ) ) . write_fmt ( args) ;
1010
993
* s. borrow_mut ( ) = Some ( w) ;
1011
994
return result;
1012
995
}
0 commit comments