about summary refs log tree commit diff
path: root/library/std
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2020-09-27 15:32:07 +0200
committerMara Bos <m-ou.se@m-ou.se>2020-09-27 16:04:25 +0200
commited3ead013f40c65e2972c794a71b756237a31b46 (patch)
treefb41a1e0d25cf184248617a5109cd35bd0e1915c /library/std
parent07fd17f7014de6dc209c7dc4de159a2a5acea173 (diff)
downloadrust-ed3ead013f40c65e2972c794a71b756237a31b46.tar.gz
rust-ed3ead013f40c65e2972c794a71b756237a31b46.zip
Relax memory ordering of LOCAL_STREAMS and document it.
Diffstat (limited to 'library/std')
-rw-r--r--library/std/src/io/stdio.rs22
1 files changed, 17 insertions, 5 deletions
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 814e0dfda54..df83c329829 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<Option<Box<dyn Write + Send>>> = {
@@ -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<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
             Some(s)
         },
     );
-    LOCAL_STREAMS.store(true, Ordering::Release);
+    LOCAL_STREAMS.store(true, Ordering::Relaxed);
     s
 }
 
@@ -926,7 +938,7 @@ pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
             Some(s)
         },
     );
-    LOCAL_STREAMS.store(true, Ordering::Release);
+    LOCAL_STREAMS.store(true, Ordering::Relaxed);
     s
 }
 
@@ -949,7 +961,7 @@ fn print_to<T>(
     T: Write,
 {
     let result = LOCAL_STREAMS
-        .load(Ordering::Acquire)
+        .load(Ordering::Relaxed)
         .then(|| {
             local_s
                 .try_with(|s| {