Rollup merge of #147125 - connortsui20:poison-once-remove, r=tgross35
move `once` module out of `poison` From https://github.com/rust-lang/rust/issues/134645#issuecomment-3324577500, since `Once` will not have a non-poisoning variant, we remove it from the `poison` module. Additionally: 1. Renames `once::ExclusiveState` to `OnceExclusiveState` since it was a bit confusing reading just `ExclusiveState` where it is used. 2. Reorders a few module definitions and re-exports in `library/std/src/sync/mod.rs` for clarity. Also, once this is merged, I think that we can begin the process of stabilizing [`sync_poison_mod`](https://github.com/rust-lang/rust/issues/134646)
This commit is contained in:
commit
79e46694de
7 changed files with 102 additions and 97 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use super::poison::once::ExclusiveState;
|
||||
use super::once::OnceExclusiveState;
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::ops::{Deref, DerefMut};
|
||||
|
|
@ -140,14 +140,18 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
|||
pub fn into_inner(mut this: Self) -> Result<T, F> {
|
||||
let state = this.once.state();
|
||||
match state {
|
||||
ExclusiveState::Poisoned => panic_poisoned(),
|
||||
OnceExclusiveState::Poisoned => panic_poisoned(),
|
||||
state => {
|
||||
let this = ManuallyDrop::new(this);
|
||||
let data = unsafe { ptr::read(&this.data) }.into_inner();
|
||||
match state {
|
||||
ExclusiveState::Incomplete => Err(ManuallyDrop::into_inner(unsafe { data.f })),
|
||||
ExclusiveState::Complete => Ok(ManuallyDrop::into_inner(unsafe { data.value })),
|
||||
ExclusiveState::Poisoned => unreachable!(),
|
||||
OnceExclusiveState::Incomplete => {
|
||||
Err(ManuallyDrop::into_inner(unsafe { data.f }))
|
||||
}
|
||||
OnceExclusiveState::Complete => {
|
||||
Ok(ManuallyDrop::into_inner(unsafe { data.value }))
|
||||
}
|
||||
OnceExclusiveState::Poisoned => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -189,7 +193,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
|||
impl<T, F> Drop for PoisonOnPanic<'_, T, F> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
self.0.once.set_state(ExclusiveState::Poisoned);
|
||||
self.0.once.set_state(OnceExclusiveState::Poisoned);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +204,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
|||
let guard = PoisonOnPanic(this);
|
||||
let data = f();
|
||||
guard.0.data.get_mut().value = ManuallyDrop::new(data);
|
||||
guard.0.once.set_state(ExclusiveState::Complete);
|
||||
guard.0.once.set_state(OnceExclusiveState::Complete);
|
||||
core::mem::forget(guard);
|
||||
// SAFETY: We put the value there above.
|
||||
unsafe { &mut this.data.get_mut().value }
|
||||
|
|
@ -208,11 +212,11 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
|||
|
||||
let state = this.once.state();
|
||||
match state {
|
||||
ExclusiveState::Poisoned => panic_poisoned(),
|
||||
OnceExclusiveState::Poisoned => panic_poisoned(),
|
||||
// SAFETY: The `Once` states we completed the initialization.
|
||||
ExclusiveState::Complete => unsafe { &mut this.data.get_mut().value },
|
||||
OnceExclusiveState::Complete => unsafe { &mut this.data.get_mut().value },
|
||||
// SAFETY: The state is `Incomplete`.
|
||||
ExclusiveState::Incomplete => unsafe { really_init_mut(this) },
|
||||
OnceExclusiveState::Incomplete => unsafe { really_init_mut(this) },
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +297,7 @@ impl<T, F> LazyLock<T, F> {
|
|||
match state {
|
||||
// SAFETY:
|
||||
// The closure has been run successfully, so `value` has been initialized.
|
||||
ExclusiveState::Complete => Some(unsafe { &mut this.data.get_mut().value }),
|
||||
OnceExclusiveState::Complete => Some(unsafe { &mut this.data.get_mut().value }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -332,11 +336,13 @@ impl<T, F> LazyLock<T, F> {
|
|||
impl<T, F> Drop for LazyLock<T, F> {
|
||||
fn drop(&mut self) {
|
||||
match self.once.state() {
|
||||
ExclusiveState::Incomplete => unsafe { ManuallyDrop::drop(&mut self.data.get_mut().f) },
|
||||
ExclusiveState::Complete => unsafe {
|
||||
OnceExclusiveState::Incomplete => unsafe {
|
||||
ManuallyDrop::drop(&mut self.data.get_mut().f)
|
||||
},
|
||||
OnceExclusiveState::Complete => unsafe {
|
||||
ManuallyDrop::drop(&mut self.data.get_mut().value)
|
||||
},
|
||||
ExclusiveState::Poisoned => {}
|
||||
OnceExclusiveState::Poisoned => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@
|
|||
//! most one thread at a time is able to access some data.
|
||||
//!
|
||||
//! - [`Once`]: Used for a thread-safe, one-time global initialization routine.
|
||||
//! Mostly useful for implementing other types like `OnceLock`.
|
||||
//! Mostly useful for implementing other types like [`OnceLock`].
|
||||
//!
|
||||
//! - [`OnceLock`]: Used for thread-safe, one-time initialization of a
|
||||
//! variable, with potentially different initializers based on the caller.
|
||||
|
|
@ -181,7 +181,24 @@ pub use alloc_crate::sync::UniqueArc;
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::sync::{Arc, Weak};
|
||||
|
||||
// FIXME(sync_nonpoison,sync_poison_mod): remove all `#[doc(inline)]` once the modules are stabilized.
|
||||
#[unstable(feature = "mpmc_channel", issue = "126840")]
|
||||
pub mod mpmc;
|
||||
pub mod mpsc;
|
||||
|
||||
pub(crate) mod once; // `pub(crate)` for the `sys::sync::once` implementations and `LazyLock`.
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::once::{Once, OnceState};
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(inline)]
|
||||
#[expect(deprecated)]
|
||||
pub use self::once::ONCE_INIT;
|
||||
|
||||
mod barrier;
|
||||
mod lazy_lock;
|
||||
mod once_lock;
|
||||
mod reentrant_lock;
|
||||
|
||||
// These exist only in one flavor: no poisoning.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -193,47 +210,36 @@ pub use self::once_lock::OnceLock;
|
|||
#[unstable(feature = "reentrant_lock", issue = "121440")]
|
||||
pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
|
||||
|
||||
// These make sense and exist only with poisoning.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(inline)]
|
||||
pub use self::poison::{LockResult, PoisonError};
|
||||
|
||||
// These (should) exist in both flavors: with and without poisoning.
|
||||
// FIXME(sync_nonpoison): implement nonpoison versions:
|
||||
// * Mutex (nonpoison_mutex)
|
||||
// * Condvar (nonpoison_condvar)
|
||||
// * Once (nonpoison_once)
|
||||
// * RwLock (nonpoison_rwlock)
|
||||
// The historical default is the version with poisoning.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(inline)]
|
||||
pub use self::poison::{
|
||||
Mutex, MutexGuard, TryLockError, TryLockResult,
|
||||
Condvar,
|
||||
Once, OnceState,
|
||||
RwLock, RwLockReadGuard, RwLockWriteGuard,
|
||||
};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(inline)]
|
||||
#[expect(deprecated)]
|
||||
pub use self::poison::ONCE_INIT;
|
||||
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
|
||||
#[doc(inline)]
|
||||
pub use self::poison::{MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};
|
||||
|
||||
#[unstable(feature = "mpmc_channel", issue = "126840")]
|
||||
pub mod mpmc;
|
||||
pub mod mpsc;
|
||||
// Note: in the future we will change the default version in `std::sync` to the non-poisoning
|
||||
// version over an edition.
|
||||
// See https://github.com/rust-lang/rust/issues/134645#issuecomment-3324577500 for more details.
|
||||
|
||||
#[unstable(feature = "sync_nonpoison", issue = "134645")]
|
||||
pub mod nonpoison;
|
||||
#[unstable(feature = "sync_poison_mod", issue = "134646")]
|
||||
pub mod poison;
|
||||
|
||||
mod barrier;
|
||||
mod lazy_lock;
|
||||
mod once_lock;
|
||||
mod reentrant_lock;
|
||||
// FIXME(sync_poison_mod): remove all `#[doc(inline)]` once the modules are stabilized.
|
||||
|
||||
// These exist only with poisoning.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(inline)]
|
||||
pub use self::poison::{LockResult, PoisonError};
|
||||
|
||||
// These exist in both flavors: with and without poisoning.
|
||||
// The historical default is the version with poisoning.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(inline)]
|
||||
pub use self::poison::{
|
||||
TryLockError, TryLockResult,
|
||||
Mutex, MutexGuard,
|
||||
RwLock, RwLockReadGuard, RwLockWriteGuard,
|
||||
Condvar,
|
||||
};
|
||||
|
||||
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
|
||||
#[doc(inline)]
|
||||
pub use self::poison::{MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};
|
||||
|
||||
/// A type indicating whether a timed wait on a condition variable returned
|
||||
/// due to a time out or not.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ pub struct OnceState {
|
|||
pub(crate) inner: sys::OnceState,
|
||||
}
|
||||
|
||||
pub(crate) enum ExclusiveState {
|
||||
/// Used for the internal implementation of `sys::sync::once` on different platforms and the
|
||||
/// [`LazyLock`](crate::sync::LazyLock) implementation.
|
||||
pub(crate) enum OnceExclusiveState {
|
||||
Incomplete,
|
||||
Poisoned,
|
||||
Complete,
|
||||
|
|
@ -310,7 +312,7 @@ impl Once {
|
|||
/// be running, so the state must be either "incomplete", "poisoned" or
|
||||
/// "complete".
|
||||
#[inline]
|
||||
pub(crate) fn state(&mut self) -> ExclusiveState {
|
||||
pub(crate) fn state(&mut self) -> OnceExclusiveState {
|
||||
self.inner.state()
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +322,7 @@ impl Once {
|
|||
/// be running, so the state must be either "incomplete", "poisoned" or
|
||||
/// "complete".
|
||||
#[inline]
|
||||
pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
|
||||
pub(crate) fn set_state(&mut self, new_state: OnceExclusiveState) {
|
||||
self.inner.set_state(new_state);
|
||||
}
|
||||
}
|
||||
|
|
@ -13,8 +13,8 @@
|
|||
//! the panics are recognized reliably or on a best-effort basis depend on the
|
||||
//! primitive. See [Overview](#overview) below.
|
||||
//!
|
||||
//! For the alternative implementations that do not employ poisoning,
|
||||
//! see [`std::sync::nonpoison`].
|
||||
//! The synchronization objects in this module have alternative implementations that do not employ
|
||||
//! poisoning in the [`std::sync::nonpoison`] module.
|
||||
//!
|
||||
//! [`std::sync::nonpoison`]: crate::sync::nonpoison
|
||||
//!
|
||||
|
|
@ -42,14 +42,6 @@
|
|||
//! [`Mutex::lock()`] returns a [`LockResult`], providing a way to deal with
|
||||
//! the poisoned state. See [`Mutex`'s documentation](Mutex#poisoning) for more.
|
||||
//!
|
||||
//! - [`Once`]: A thread-safe way to run a piece of code only once.
|
||||
//! Mostly useful for implementing one-time global initialization.
|
||||
//!
|
||||
//! [`Once`] is reliably poisoned if the piece of code passed to
|
||||
//! [`Once::call_once()`] or [`Once::call_once_force()`] panics.
|
||||
//! When in poisoned state, subsequent calls to [`Once::call_once()`] will panic too.
|
||||
//! [`Once::call_once_force()`] can be used to clear the poisoned state.
|
||||
//!
|
||||
//! - [`RwLock`]: Provides a mutual exclusion mechanism which allows
|
||||
//! multiple readers at the same time, while allowing only one
|
||||
//! writer at a time. In some cases, this can be more efficient than
|
||||
|
|
@ -59,6 +51,11 @@
|
|||
//! Note, however, that an `RwLock` may only be poisoned if a panic occurs
|
||||
//! while it is locked exclusively (write mode). If a panic occurs in any reader,
|
||||
//! then the lock will not be poisoned.
|
||||
//!
|
||||
//! Note that the [`Once`] type also employs poisoning, but since it has non-poisoning `force`
|
||||
//! methods available on it, there is no separate `nonpoison` and `poison` version.
|
||||
//!
|
||||
//! [`Once`]: crate::sync::Once
|
||||
|
||||
// If we are not unwinding, `PoisonError` is uninhabited.
|
||||
#![cfg_attr(not(panic = "unwind"), expect(unreachable_code))]
|
||||
|
|
@ -69,11 +66,6 @@ pub use self::condvar::Condvar;
|
|||
pub use self::mutex::MappedMutexGuard;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::mutex::{Mutex, MutexGuard};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[expect(deprecated)]
|
||||
pub use self::once::ONCE_INIT;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::once::{Once, OnceState};
|
||||
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
|
||||
pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -88,7 +80,6 @@ use crate::thread;
|
|||
mod condvar;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
mod mutex;
|
||||
pub(crate) mod once;
|
||||
mod rwlock;
|
||||
|
||||
pub(crate) struct Flag {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::cell::Cell;
|
||||
use crate::sync as public;
|
||||
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
|
||||
use crate::sync::poison::once::ExclusiveState;
|
||||
use crate::sync::once::OnceExclusiveState;
|
||||
use crate::sys::futex::{Futex, Primitive, futex_wait, futex_wake_all};
|
||||
|
||||
// On some platforms, the OS is very nice and handles the waiter queue for us.
|
||||
|
|
@ -83,21 +83,21 @@ impl Once {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn state(&mut self) -> ExclusiveState {
|
||||
pub(crate) fn state(&mut self) -> OnceExclusiveState {
|
||||
match *self.state_and_queued.get_mut() {
|
||||
INCOMPLETE => ExclusiveState::Incomplete,
|
||||
POISONED => ExclusiveState::Poisoned,
|
||||
COMPLETE => ExclusiveState::Complete,
|
||||
INCOMPLETE => OnceExclusiveState::Incomplete,
|
||||
POISONED => OnceExclusiveState::Poisoned,
|
||||
COMPLETE => OnceExclusiveState::Complete,
|
||||
_ => unreachable!("invalid Once state"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
|
||||
pub(crate) fn set_state(&mut self, new_state: OnceExclusiveState) {
|
||||
*self.state_and_queued.get_mut() = match new_state {
|
||||
ExclusiveState::Incomplete => INCOMPLETE,
|
||||
ExclusiveState::Poisoned => POISONED,
|
||||
ExclusiveState::Complete => COMPLETE,
|
||||
OnceExclusiveState::Incomplete => INCOMPLETE,
|
||||
OnceExclusiveState::Poisoned => POISONED,
|
||||
OnceExclusiveState::Complete => COMPLETE,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::cell::Cell;
|
||||
use crate::sync as public;
|
||||
use crate::sync::poison::once::ExclusiveState;
|
||||
use crate::sync::once::OnceExclusiveState;
|
||||
|
||||
pub struct Once {
|
||||
state: Cell<State>,
|
||||
|
|
@ -45,21 +45,21 @@ impl Once {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn state(&mut self) -> ExclusiveState {
|
||||
pub(crate) fn state(&mut self) -> OnceExclusiveState {
|
||||
match self.state.get() {
|
||||
State::Incomplete => ExclusiveState::Incomplete,
|
||||
State::Poisoned => ExclusiveState::Poisoned,
|
||||
State::Complete => ExclusiveState::Complete,
|
||||
State::Incomplete => OnceExclusiveState::Incomplete,
|
||||
State::Poisoned => OnceExclusiveState::Poisoned,
|
||||
State::Complete => OnceExclusiveState::Complete,
|
||||
_ => unreachable!("invalid Once state"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
|
||||
pub(crate) fn set_state(&mut self, new_state: OnceExclusiveState) {
|
||||
self.state.set(match new_state {
|
||||
ExclusiveState::Incomplete => State::Incomplete,
|
||||
ExclusiveState::Poisoned => State::Poisoned,
|
||||
ExclusiveState::Complete => State::Complete,
|
||||
OnceExclusiveState::Incomplete => State::Incomplete,
|
||||
OnceExclusiveState::Poisoned => State::Poisoned,
|
||||
OnceExclusiveState::Complete => State::Complete,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
use crate::cell::Cell;
|
||||
use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release};
|
||||
use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr};
|
||||
use crate::sync::poison::once::ExclusiveState;
|
||||
use crate::sync::once::OnceExclusiveState;
|
||||
use crate::thread::{self, Thread};
|
||||
use crate::{fmt, ptr, sync as public};
|
||||
|
||||
|
|
@ -131,21 +131,21 @@ impl Once {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn state(&mut self) -> ExclusiveState {
|
||||
pub(crate) fn state(&mut self) -> OnceExclusiveState {
|
||||
match self.state_and_queue.get_mut().addr() {
|
||||
INCOMPLETE => ExclusiveState::Incomplete,
|
||||
POISONED => ExclusiveState::Poisoned,
|
||||
COMPLETE => ExclusiveState::Complete,
|
||||
INCOMPLETE => OnceExclusiveState::Incomplete,
|
||||
POISONED => OnceExclusiveState::Poisoned,
|
||||
COMPLETE => OnceExclusiveState::Complete,
|
||||
_ => unreachable!("invalid Once state"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
|
||||
pub(crate) fn set_state(&mut self, new_state: OnceExclusiveState) {
|
||||
*self.state_and_queue.get_mut() = match new_state {
|
||||
ExclusiveState::Incomplete => ptr::without_provenance_mut(INCOMPLETE),
|
||||
ExclusiveState::Poisoned => ptr::without_provenance_mut(POISONED),
|
||||
ExclusiveState::Complete => ptr::without_provenance_mut(COMPLETE),
|
||||
OnceExclusiveState::Incomplete => ptr::without_provenance_mut(INCOMPLETE),
|
||||
OnceExclusiveState::Poisoned => ptr::without_provenance_mut(POISONED),
|
||||
OnceExclusiveState::Complete => ptr::without_provenance_mut(COMPLETE),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue