about summary refs log tree commit diff
path: root/library/std/src/sync
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@dend.ro>2024-08-13 17:58:52 +0300
committerLaurențiu Nicola <lnicola@dend.ro>2024-08-13 17:58:52 +0300
commit28af7e09581c3b39cdbf2850df2f157690ab7e56 (patch)
tree76c5e72c0570998ece04f11ac90e09b5d2613abc /library/std/src/sync
parentddb8551e03a1310a841da05b0418b49fd6287482 (diff)
parent80eb5a8e910e5185d47cdefe3732d839c78a5e7e (diff)
Merge from rust-lang/rust
Diffstat (limited to 'library/std/src/sync')
-rw-r--r--library/std/src/sync/lazy_lock.rs5
-rw-r--r--library/std/src/sync/lazy_lock/tests.rs15
-rw-r--r--library/std/src/sync/mod.rs19
-rw-r--r--library/std/src/sync/mpmc/array.rs1
-rw-r--r--library/std/src/sync/mpmc/context.rs1
-rw-r--r--library/std/src/sync/mpmc/counter.rs3
-rw-r--r--library/std/src/sync/mpmc/error.rs4
-rw-r--r--library/std/src/sync/mpmc/list.rs1
-rw-r--r--library/std/src/sync/mpmc/mod.rs3
-rw-r--r--library/std/src/sync/mpmc/waker.rs1
-rw-r--r--library/std/src/sync/mpmc/zero.rs1
-rw-r--r--library/std/src/sync/mpsc/mod.rs3
-rw-r--r--library/std/src/sync/mpsc/sync_tests.rs3
-rw-r--r--library/std/src/sync/mpsc/tests.rs3
-rw-r--r--library/std/src/sync/once.rs43
-rw-r--r--library/std/src/sync/once/tests.rs50
-rw-r--r--library/std/src/sync/once_lock.rs36
-rw-r--r--library/std/src/sync/once_lock/tests.rs14
-rw-r--r--library/std/src/sync/poison.rs5
-rw-r--r--library/std/src/sync/rwlock.rs4
-rw-r--r--library/std/src/sync/rwlock/tests.rs7
21 files changed, 160 insertions, 62 deletions
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 18906aceffa..953aef40e7b 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -1,3 +1,4 @@
+use super::once::ExclusiveState;
 use crate::cell::UnsafeCell;
 use crate::mem::ManuallyDrop;
 use crate::ops::Deref;
@@ -5,8 +6,6 @@ use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::sync::Once;
 use crate::{fmt, ptr};
 
-use super::once::ExclusiveState;
-
 // We use the state of a Once as discriminant value. Upon creation, the state is
 // "incomplete" and `f` contains the initialization closure. In the first call to
 // `call_once`, `f` is taken and run. If it succeeds, `value` is set and the state
@@ -175,7 +174,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
 }
 
 impl<T, F> LazyLock<T, F> {
-    /// Get the inner value if it has already been initialized.
+    /// Gets the inner value if it has already been initialized.
     fn get(&self) -> Option<&T> {
         if self.once.is_completed() {
             // SAFETY:
diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/src/sync/lazy_lock/tests.rs
index a5d4e25c596..8a6ab4ac4fd 100644
--- a/library/std/src/sync/lazy_lock/tests.rs
+++ b/library/std/src/sync/lazy_lock/tests.rs
@@ -1,13 +1,8 @@
-use crate::{
-    cell::LazyCell,
-    panic,
-    sync::{
-        atomic::{AtomicUsize, Ordering::SeqCst},
-        Mutex,
-    },
-    sync::{LazyLock, OnceLock},
-    thread,
-};
+use crate::cell::LazyCell;
+use crate::sync::atomic::AtomicUsize;
+use crate::sync::atomic::Ordering::SeqCst;
+use crate::sync::{LazyLock, Mutex, OnceLock};
+use crate::{panic, thread};
 
 fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
     thread::spawn(f).join().unwrap()
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 9a38c42f43a..d0ba8cc3b47 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -159,16 +159,19 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::sync::{Arc, Weak};
-#[stable(feature = "rust1", since = "1.0.0")]
 pub use core::sync::atomic;
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 pub use core::sync::Exclusive;
 
 #[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::sync::{Arc, Weak};
+
+#[stable(feature = "rust1", since = "1.0.0")]
 pub use self::barrier::{Barrier, BarrierWaitResult};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::condvar::{Condvar, WaitTimeoutResult};
+#[stable(feature = "lazy_cell", since = "1.80.0")]
+pub use self::lazy_lock::LazyLock;
 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
 pub use self::mutex::MappedMutexGuard;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -176,21 +179,17 @@ pub use self::mutex::{Mutex, MutexGuard};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
 pub use self::once::{Once, OnceState, ONCE_INIT};
+#[stable(feature = "once_cell", since = "1.70.0")]
+pub use self::once_lock::OnceLock;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult};
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
 pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 
-#[stable(feature = "lazy_cell", since = "1.80.0")]
-pub use self::lazy_lock::LazyLock;
-#[stable(feature = "once_cell", since = "1.70.0")]
-pub use self::once_lock::OnceLock;
-
-#[unstable(feature = "reentrant_lock", issue = "121440")]
-pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
-
 pub mod mpsc;
 
 mod barrier;
diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs
index 185319add74..34acd9c9a94 100644
--- a/library/std/src/sync/mpmc/array.rs
+++ b/library/std/src/sync/mpmc/array.rs
@@ -13,7 +13,6 @@ use super::error::*;
 use super::select::{Operation, Selected, Token};
 use super::utils::{Backoff, CachePadded};
 use super::waker::SyncWaker;
-
 use crate::cell::UnsafeCell;
 use crate::mem::MaybeUninit;
 use crate::ptr;
diff --git a/library/std/src/sync/mpmc/context.rs b/library/std/src/sync/mpmc/context.rs
index bbfc6ce00ff..8db3c9896eb 100644
--- a/library/std/src/sync/mpmc/context.rs
+++ b/library/std/src/sync/mpmc/context.rs
@@ -2,7 +2,6 @@
 
 use super::select::Selected;
 use super::waker::current_thread_id;
-
 use crate::cell::Cell;
 use crate::ptr;
 use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
diff --git a/library/std/src/sync/mpmc/counter.rs b/library/std/src/sync/mpmc/counter.rs
index 3478cf41dc9..d1bfe612f53 100644
--- a/library/std/src/sync/mpmc/counter.rs
+++ b/library/std/src/sync/mpmc/counter.rs
@@ -1,6 +1,5 @@
-use crate::ops;
-use crate::process;
 use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
+use crate::{ops, process};
 
 /// Reference counter internals.
 struct Counter<C> {
diff --git a/library/std/src/sync/mpmc/error.rs b/library/std/src/sync/mpmc/error.rs
index 33b2bff8534..e3aec7e7623 100644
--- a/library/std/src/sync/mpmc/error.rs
+++ b/library/std/src/sync/mpmc/error.rs
@@ -1,7 +1,5 @@
-use crate::error;
-use crate::fmt;
-
 pub use crate::sync::mpsc::{RecvError, RecvTimeoutError, SendError, TryRecvError, TrySendError};
+use crate::{error, fmt};
 
 /// An error returned from the [`send_timeout`] method.
 ///
diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs
index edac7a0cb18..bbe205cad04 100644
--- a/library/std/src/sync/mpmc/list.rs
+++ b/library/std/src/sync/mpmc/list.rs
@@ -5,7 +5,6 @@ use super::error::*;
 use super::select::{Operation, Selected, Token};
 use super::utils::{Backoff, CachePadded};
 use super::waker::SyncWaker;
-
 use crate::cell::UnsafeCell;
 use crate::marker::PhantomData;
 use crate::mem::MaybeUninit;
diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs
index 2068dda393a..c640e07348e 100644
--- a/library/std/src/sync/mpmc/mod.rs
+++ b/library/std/src/sync/mpmc/mod.rs
@@ -40,10 +40,11 @@ mod utils;
 mod waker;
 mod zero;
 
+pub use error::*;
+
 use crate::fmt;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::time::{Duration, Instant};
-pub use error::*;
 
 /// Creates a channel of unbounded capacity.
 ///
diff --git a/library/std/src/sync/mpmc/waker.rs b/library/std/src/sync/mpmc/waker.rs
index 9aab1b9417e..fb877887f9c 100644
--- a/library/std/src/sync/mpmc/waker.rs
+++ b/library/std/src/sync/mpmc/waker.rs
@@ -2,7 +2,6 @@
 
 use super::context::Context;
 use super::select::{Operation, Selected};
-
 use crate::ptr;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sync::Mutex;
diff --git a/library/std/src/sync/mpmc/zero.rs b/library/std/src/sync/mpmc/zero.rs
index 6d1c9d64e7a..2b82eeda3d5 100644
--- a/library/std/src/sync/mpmc/zero.rs
+++ b/library/std/src/sync/mpmc/zero.rs
@@ -7,7 +7,6 @@ use super::error::*;
 use super::select::{Operation, Selected, Token};
 use super::utils::Backoff;
 use super::waker::Waker;
-
 use crate::cell::UnsafeCell;
 use crate::marker::PhantomData;
 use crate::sync::atomic::{AtomicBool, Ordering};
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index feee6948db4..26d5b9515a2 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -148,10 +148,9 @@ mod sync_tests;
 // not exposed publicly, but if you are curious about the implementation,
 // that's where everything is.
 
-use crate::error;
-use crate::fmt;
 use crate::sync::mpmc;
 use crate::time::{Duration, Instant};
+use crate::{error, fmt};
 
 /// The receiving half of Rust's [`channel`] (or [`sync_channel`]) type.
 /// This half can only be owned by one thread.
diff --git a/library/std/src/sync/mpsc/sync_tests.rs b/library/std/src/sync/mpsc/sync_tests.rs
index 945de280f40..49b65c8efe6 100644
--- a/library/std/src/sync/mpsc/sync_tests.rs
+++ b/library/std/src/sync/mpsc/sync_tests.rs
@@ -1,8 +1,7 @@
 use super::*;
-use crate::env;
 use crate::rc::Rc;
 use crate::sync::mpmc::SendTimeoutError;
-use crate::thread;
+use crate::{env, thread};
 
 pub fn stress_factor() -> usize {
     match env::var("RUST_TEST_STRESS") {
diff --git a/library/std/src/sync/mpsc/tests.rs b/library/std/src/sync/mpsc/tests.rs
index ac1a804cf9c..13892fa0d18 100644
--- a/library/std/src/sync/mpsc/tests.rs
+++ b/library/std/src/sync/mpsc/tests.rs
@@ -1,6 +1,5 @@
 use super::*;
-use crate::env;
-use crate::thread;
+use crate::{env, thread};
 
 pub fn stress_factor() -> usize {
     match env::var("RUST_TEST_STRESS") {
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index 9d969af8c6d..bf595fdea2d 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -70,7 +70,7 @@ pub(crate) enum ExclusiveState {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[deprecated(
     since = "1.38.0",
-    note = "the `new` function is now preferred",
+    note = "the `Once::new()` function is now preferred",
     suggestion = "Once::new()"
 )]
 pub const ONCE_INIT: Once = Once::new();
@@ -264,6 +264,47 @@ impl Once {
         self.inner.is_completed()
     }
 
+    /// Blocks the current thread until initialization has completed.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// #![feature(once_wait)]
+    ///
+    /// use std::sync::Once;
+    /// use std::thread;
+    ///
+    /// static READY: Once = Once::new();
+    ///
+    /// let thread = thread::spawn(|| {
+    ///     READY.wait();
+    ///     println!("everything is ready");
+    /// });
+    ///
+    /// READY.call_once(|| println!("performing setup"));
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// If this [`Once`] has been poisoned because an initialization closure has
+    /// panicked, this method will also panic. Use [`wait_force`](Self::wait_force)
+    /// if this behaviour is not desired.
+    #[unstable(feature = "once_wait", issue = "127527")]
+    pub fn wait(&self) {
+        if !self.inner.is_completed() {
+            self.inner.wait(false);
+        }
+    }
+
+    /// Blocks the current thread until initialization has completed, ignoring
+    /// poisoning.
+    #[unstable(feature = "once_wait", issue = "127527")]
+    pub fn wait_force(&self) {
+        if !self.inner.is_completed() {
+            self.inner.wait(true);
+        }
+    }
+
     /// Returns the current state of the `Once` instance.
     ///
     /// Since this takes a mutable reference, no initialization can currently
diff --git a/library/std/src/sync/once/tests.rs b/library/std/src/sync/once/tests.rs
index 0c35597e11c..ce96468aeb6 100644
--- a/library/std/src/sync/once/tests.rs
+++ b/library/std/src/sync/once/tests.rs
@@ -1,7 +1,9 @@
 use super::Once;
-use crate::panic;
+use crate::sync::atomic::AtomicBool;
+use crate::sync::atomic::Ordering::Relaxed;
 use crate::sync::mpsc::channel;
-use crate::thread;
+use crate::time::Duration;
+use crate::{panic, thread};
 
 #[test]
 fn smoke_once() {
@@ -114,3 +116,47 @@ fn wait_for_force_to_finish() {
     assert!(t1.join().is_ok());
     assert!(t2.join().is_ok());
 }
+
+#[test]
+fn wait() {
+    for _ in 0..50 {
+        let val = AtomicBool::new(false);
+        let once = Once::new();
+
+        thread::scope(|s| {
+            for _ in 0..4 {
+                s.spawn(|| {
+                    once.wait();
+                    assert!(val.load(Relaxed));
+                });
+            }
+
+            once.call_once(|| val.store(true, Relaxed));
+        });
+    }
+}
+
+#[test]
+fn wait_on_poisoned() {
+    let once = Once::new();
+
+    panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err();
+    panic::catch_unwind(|| once.wait()).unwrap_err();
+}
+
+#[test]
+fn wait_force_on_poisoned() {
+    let once = Once::new();
+
+    thread::scope(|s| {
+        panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err();
+
+        s.spawn(|| {
+            thread::sleep(Duration::from_millis(100));
+
+            once.call_once_force(|_| {});
+        });
+
+        once.wait_force();
+    })
+}
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index 94955beaf37..56cf877ddc6 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -167,6 +167,34 @@ impl<T> OnceLock<T> {
         }
     }
 
+    /// Blocks the current thread until the cell is initialized.
+    ///
+    /// # Example
+    ///
+    /// Waiting for a computation on another thread to finish:
+    /// ```rust
+    /// #![feature(once_wait)]
+    ///
+    /// use std::thread;
+    /// use std::sync::OnceLock;
+    ///
+    /// let value = OnceLock::new();
+    ///
+    /// thread::scope(|s| {
+    ///     s.spawn(|| value.set(1 + 1));
+    ///
+    ///     let result = value.wait();
+    ///     assert_eq!(result, &2);
+    /// })
+    /// ```
+    #[inline]
+    #[unstable(feature = "once_wait", issue = "127527")]
+    pub fn wait(&self) -> &T {
+        self.once.wait_force();
+
+        unsafe { self.get_unchecked() }
+    }
+
     /// Sets the contents of this cell to `value`.
     ///
     /// May block if another thread is currently attempting to initialize the cell. The cell is
@@ -281,9 +309,7 @@ impl<T> OnceLock<T> {
     /// Gets the mutable reference of the contents of the cell, initializing
     /// it with `f` if the cell was empty.
     ///
-    /// Many threads may call `get_mut_or_init` concurrently with different
-    /// initializing functions, but it is guaranteed that only one function
-    /// will be executed.
+    /// This method never blocks.
     ///
     /// # Panics
     ///
@@ -373,6 +399,8 @@ impl<T> OnceLock<T> {
     /// it with `f` if the cell was empty. If the cell was empty and `f` failed,
     /// an error is returned.
     ///
+    /// This method never blocks.
+    ///
     /// # Panics
     ///
     /// If `f` panics, the panic is propagated to the caller, and
@@ -578,7 +606,7 @@ impl<T: Clone> Clone for OnceLock<T> {
 
 #[stable(feature = "once_cell", since = "1.70.0")]
 impl<T> From<T> for OnceLock<T> {
-    /// Create a new cell with its contents set to `value`.
+    /// Creates a new cell with its contents set to `value`.
     ///
     /// # Example
     ///
diff --git a/library/std/src/sync/once_lock/tests.rs b/library/std/src/sync/once_lock/tests.rs
index d5d32e73d88..176830c6748 100644
--- a/library/std/src/sync/once_lock/tests.rs
+++ b/library/std/src/sync/once_lock/tests.rs
@@ -1,12 +1,8 @@
-use crate::{
-    panic,
-    sync::OnceLock,
-    sync::{
-        atomic::{AtomicUsize, Ordering::SeqCst},
-        mpsc::channel,
-    },
-    thread,
-};
+use crate::sync::atomic::AtomicUsize;
+use crate::sync::atomic::Ordering::SeqCst;
+use crate::sync::mpsc::channel;
+use crate::sync::OnceLock;
+use crate::{panic, thread};
 
 fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
     thread::spawn(f).join().unwrap()
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index f4975088b37..da66a088e51 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -1,6 +1,5 @@
 use crate::error::Error;
 use crate::fmt;
-
 #[cfg(panic = "unwind")]
 use crate::sync::atomic::{AtomicBool, Ordering};
 #[cfg(panic = "unwind")]
@@ -31,13 +30,13 @@ impl Flag {
         }
     }
 
-    /// Check the flag for an unguarded borrow, where we only care about existing poison.
+    /// Checks the flag for an unguarded borrow, where we only care about existing poison.
     #[inline]
     pub fn borrow(&self) -> LockResult<()> {
         if self.get() { Err(PoisonError::new(())) } else { Ok(()) }
     }
 
-    /// Check the flag for a guarded borrow, where we may also set poison when `done`.
+    /// Checks the flag for a guarded borrow, where we may also set poison when `done`.
     #[inline]
     pub fn guard(&self) -> LockResult<Guard> {
         let ret = Guard {
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index a4ec52a4abe..d995a16e056 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -573,7 +573,7 @@ impl<T> From<T> for RwLock<T> {
 }
 
 impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
-    /// Create a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
+    /// Creates a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
     // SAFETY: if and only if `lock.inner.read()` (or `lock.inner.try_read()`) has been
     // successfully called from the same thread before instantiating this object.
     unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockReadGuard<'rwlock, T>> {
@@ -585,7 +585,7 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
 }
 
 impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
-    /// Create a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`.
+    /// Creates a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`.
     // SAFETY: if and only if `lock.inner.write()` (or `lock.inner.try_write()`) has been
     // successfully called from the same thread before instantiating this object.
     unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> {
diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/rwlock/tests.rs
index 9cc5e7a3a60..37a2e41641a 100644
--- a/library/std/src/sync/rwlock/tests.rs
+++ b/library/std/src/sync/rwlock/tests.rs
@@ -1,3 +1,5 @@
+use rand::Rng;
+
 use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sync::mpsc::channel;
 use crate::sync::{
@@ -5,7 +7,6 @@ use crate::sync::{
     TryLockError,
 };
 use crate::thread;
-use rand::Rng;
 
 #[derive(Eq, PartialEq, Debug)]
 struct NonCopy(i32);
@@ -20,6 +21,10 @@ fn smoke() {
 }
 
 #[test]
+// FIXME: On macOS we use a provenance-incorrect implementation and Miri
+// catches that issue with a chance of around 1/1000.
+// See <https://github.com/rust-lang/rust/issues/121950> for details.
+#[cfg_attr(all(miri, target_os = "macos"), ignore)]
 fn frob() {
     const N: u32 = 10;
     const M: usize = if cfg!(miri) { 100 } else { 1000 };