From ed3ead013f40c65e2972c794a71b756237a31b46 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 27 Sep 2020 15:32:07 +0200 Subject: [PATCH] Relax memory ordering of LOCAL_STREAMS and document it. --- library/std/src/io/stdio.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 814e0dfda54b..df83c3298291 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -16,8 +16,6 @@ use crate::sys_common; use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use crate::thread::LocalKey; -static LOCAL_STREAMS: AtomicBool = AtomicBool::new(false); - thread_local! { /// Used by the test crate to capture the output of the print! and println! macros. static LOCAL_STDOUT: RefCell>> = { @@ -32,6 +30,20 @@ thread_local! { } } +/// Flag to indicate LOCAL_STDOUT and/or LOCAL_STDERR is used. +/// +/// If both are None and were never set on any thread, this flag is set to +/// false, and both LOCAL_STDOUT and LOCAL_STDOUT can be safely ignored on all +/// threads, saving some time and memory registering an unused thread local. +/// +/// Note about memory ordering: This contains information about whether two +/// thread local variables might be in use. Although this is a global flag, the +/// memory ordering between threads does not matter: we only want this flag to +/// have a consistent order between set_print/set_panic and print_to *within +/// the same thread*. Within the same thread, things always have a perfectly +/// consistent order. So Ordering::Relaxed is fine. +static LOCAL_STREAMS: AtomicBool = AtomicBool::new(false); + /// A handle to a raw instance of the standard input stream of this process. /// /// This handle is not synchronized or buffered in any fashion. Constructed via @@ -899,7 +911,7 @@ pub fn set_panic(sink: Option>) -> Option>) -> Option( T: Write, { let result = LOCAL_STREAMS - .load(Ordering::Acquire) + .load(Ordering::Relaxed) .then(|| { local_s .try_with(|s| {