diff options
Diffstat (limited to 'library/std/src/sync')
| -rw-r--r-- | library/std/src/sync/lazy_lock.rs | 5 | ||||
| -rw-r--r-- | library/std/src/sync/lazy_lock/tests.rs | 15 | ||||
| -rw-r--r-- | library/std/src/sync/mod.rs | 19 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/array.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/context.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/counter.rs | 3 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/error.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/list.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/mod.rs | 3 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/waker.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/zero.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sync/mpsc/mod.rs | 3 | ||||
| -rw-r--r-- | library/std/src/sync/mpsc/sync_tests.rs | 3 | ||||
| -rw-r--r-- | library/std/src/sync/mpsc/tests.rs | 3 | ||||
| -rw-r--r-- | library/std/src/sync/once.rs | 43 | ||||
| -rw-r--r-- | library/std/src/sync/once/tests.rs | 50 | ||||
| -rw-r--r-- | library/std/src/sync/once_lock.rs | 36 | ||||
| -rw-r--r-- | library/std/src/sync/once_lock/tests.rs | 14 | ||||
| -rw-r--r-- | library/std/src/sync/poison.rs | 5 | ||||
| -rw-r--r-- | library/std/src/sync/rwlock.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sync/rwlock/tests.rs | 7 |
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 }; |
