about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorPavel Grigorenko <GrigorenkoPV@ya.ru>2024-12-23 19:36:41 +0300
committerPavel Grigorenko <GrigorenkoPV@ya.ru>2025-01-02 15:21:41 +0300
commitee2ad4dfb1b7d3a07604efc6d9eb618d0fe3bf7d (patch)
tree363fdace20c9ca422a1571a205e7b9bd4803c5af /library/std/src
parent41b579660c0af700d42abe5b71856098db007783 (diff)
downloadrust-ee2ad4dfb1b7d3a07604efc6d9eb618d0fe3bf7d.tar.gz
rust-ee2ad4dfb1b7d3a07604efc6d9eb618d0fe3bf7d.zip
Move some things to `std::sync::poison` and reexport them in `std::sync`
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/sync/barrier.rs1
-rw-r--r--library/std/src/sync/lazy_lock.rs3
-rw-r--r--library/std/src/sync/mod.rs56
-rw-r--r--library/std/src/sync/once_lock.rs1
-rw-r--r--library/std/src/sync/poison.rs87
-rw-r--r--library/std/src/sync/poison/condvar.rs (renamed from library/std/src/sync/condvar.rs)4
-rw-r--r--library/std/src/sync/poison/condvar/tests.rs (renamed from library/std/src/sync/condvar/tests.rs)0
-rw-r--r--library/std/src/sync/poison/mutex.rs (renamed from library/std/src/sync/mutex.rs)0
-rw-r--r--library/std/src/sync/poison/mutex/tests.rs (renamed from library/std/src/sync/mutex/tests.rs)0
-rw-r--r--library/std/src/sync/poison/once.rs (renamed from library/std/src/sync/once.rs)0
-rw-r--r--library/std/src/sync/poison/once/tests.rs (renamed from library/std/src/sync/once/tests.rs)0
-rw-r--r--library/std/src/sync/poison/rwlock.rs (renamed from library/std/src/sync/rwlock.rs)0
-rw-r--r--library/std/src/sync/poison/rwlock/tests.rs (renamed from library/std/src/sync/rwlock/tests.rs)0
-rw-r--r--library/std/src/sys/sync/once/futex.rs2
-rw-r--r--library/std/src/sys/sync/once/no_threads.rs2
-rw-r--r--library/std/src/sys/sync/once/queue.rs2
16 files changed, 131 insertions, 27 deletions
diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs
index 14e4a9abe6f..862753e4765 100644
--- a/library/std/src/sync/barrier.rs
+++ b/library/std/src/sync/barrier.rs
@@ -2,6 +2,7 @@
 mod tests;
 
 use crate::fmt;
+// FIXME(nonpoison_mutex,nonpoison_condvar): switch to nonpoison versions once they are available
 use crate::sync::{Condvar, Mutex};
 
 /// A barrier enables multiple threads to synchronize the beginning
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 40510f56134..1e4f9b79e0f 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -1,4 +1,4 @@
-use super::once::ExclusiveState;
+use super::poison::once::ExclusiveState;
 use crate::cell::UnsafeCell;
 use crate::mem::ManuallyDrop;
 use crate::ops::Deref;
@@ -63,6 +63,7 @@ union Data<T, F> {
 /// ```
 #[stable(feature = "lazy_cell", since = "1.80.0")]
 pub struct LazyLock<T, F = fn() -> T> {
+    // FIXME(nonpoison_once): if possible, switch to nonpoison version once it is available
     once: Once,
     data: UnsafeCell<Data<T, F>>,
 }
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 0fb77331293..5b50a3c6ccf 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -167,6 +167,10 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+// No formatting: this file is just re-exports, and their order is worth preserving.
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+// These come from `core` & `alloc` and only in one flavor: no poisoning.
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
 pub use core::sync::Exclusive;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -175,40 +179,54 @@ pub use core::sync::atomic;
 #[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.
+
+// These exist only in one flavor: no poisoning.
 #[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")]
-pub use self::mutex::{Mutex, MutexGuard};
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-pub use self::once::{ONCE_INIT, Once, OnceState};
 #[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};
+
+// These make sense and exist only with poisoning.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
+#[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, WaitTimeoutResult,
+    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;
 
+#[unstable(feature = "sync_poison_mod", issue = "134646")]
+pub mod poison;
+
 mod barrier;
-mod condvar;
 mod lazy_lock;
-mod mutex;
-pub(crate) mod once;
 mod once_lock;
-mod poison;
 mod reentrant_lock;
-mod rwlock;
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index 0ae3cf4df36..49f2dafd8fd 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -101,6 +101,7 @@ use crate::sync::Once;
 /// ```
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub struct OnceLock<T> {
+    // FIXME(nonpoison_once): switch to nonpoison version once it is available
     once: Once,
     // Whether or not the value is initialized is tracked by `once.is_completed()`.
     value: UnsafeCell<MaybeUninit<T>>,
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index 9eb900c2103..1b8809734b8 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -1,3 +1,78 @@
+//! Synchronization objects that employ poisoning.
+//!
+//! # Poisoning
+//!
+//! All synchronization objects in this module implement a strategy called "poisoning"
+//! where if a thread panics while holding the exclusive access granted by the primitive,
+//! the state of the primitive is set to "poisoned".
+//! This information is then propagated to all other threads
+//! to signify that the data protected by this primitive is likely tainted
+//! (some invariant is not being upheld).
+//!
+//! The specifics of how this "poisoned" state affects other threads
+//! depend on the primitive. See [#Overview] bellow.
+//!
+//! For the alternative implementations that do not employ poisoning,
+//! see `std::sys::nonpoisoning`.
+//!
+//! # Overview
+//!
+//! Below is a list of synchronization objects provided by this module
+//! with a high-level overview for each object and a description
+//! of how it employs "poisoning".
+//!
+//! - [`Condvar`]: Condition Variable, providing the ability to block
+//!   a thread while waiting for an event to occur.
+//!
+//!   Condition variables are typically associated with
+//!   a boolean predicate (a condition) and a mutex.
+//!   This implementation is associated with [`poison::Mutex`](Mutex),
+//!   which employs poisoning.
+//!   For this reason, [`Condvar::wait()`] will return a [`LockResult`],
+//!   just like [`poison::Mutex::lock()`](Mutex::lock) does.
+//!
+//! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at
+//!   most one thread at a time is able to access some data.
+//!
+//!   [`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 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
+//!   a mutex.
+//!
+//!   This implementation, like [`Mutex`], will become poisoned on a panic.
+//!   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.
+
+// FIXME(sync_nonpoison) add links to sync::nonpoison to the doc comment above.
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::condvar::{Condvar, WaitTimeoutResult};
+#[unstable(feature = "mapped_lock_guards", issue = "117108")]
+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")]
+pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 use crate::error::Error;
 use crate::fmt;
 #[cfg(panic = "unwind")]
@@ -5,7 +80,13 @@ use crate::sync::atomic::{AtomicBool, Ordering};
 #[cfg(panic = "unwind")]
 use crate::thread;
 
-pub struct Flag {
+mod condvar;
+#[stable(feature = "rust1", since = "1.0.0")]
+mod mutex;
+pub(crate) mod once;
+mod rwlock;
+
+pub(crate) struct Flag {
     #[cfg(panic = "unwind")]
     failed: AtomicBool,
 }
@@ -78,7 +159,7 @@ impl Flag {
 }
 
 #[derive(Clone)]
-pub struct Guard {
+pub(crate) struct Guard {
     #[cfg(panic = "unwind")]
     panicking: bool,
 }
@@ -316,7 +397,7 @@ impl<T> Error for TryLockError<T> {
     }
 }
 
-pub fn map_result<T, U, F>(result: LockResult<T>, f: F) -> LockResult<U>
+pub(crate) fn map_result<T, U, F>(result: LockResult<T>, f: F) -> LockResult<U>
 where
     F: FnOnce(T) -> U,
 {
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/poison/condvar.rs
index 44ffcb528d9..a6e2389c93b 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/poison/condvar.rs
@@ -2,7 +2,7 @@
 mod tests;
 
 use crate::fmt;
-use crate::sync::{LockResult, MutexGuard, PoisonError, mutex, poison};
+use crate::sync::poison::{self, LockResult, MutexGuard, PoisonError, mutex};
 use crate::sys::sync as sys;
 use crate::time::{Duration, Instant};
 
@@ -16,6 +16,8 @@ use crate::time::{Duration, Instant};
 #[stable(feature = "wait_timeout", since = "1.5.0")]
 pub struct WaitTimeoutResult(bool);
 
+// FIXME(sync_nonpoison): `WaitTimeoutResult` is actually poisoning-agnostic, it seems.
+// Should we take advantage of this fact?
 impl WaitTimeoutResult {
     /// Returns `true` if the wait was known to have timed out.
     ///
diff --git a/library/std/src/sync/condvar/tests.rs b/library/std/src/sync/poison/condvar/tests.rs
index f9e9066bc92..f9e9066bc92 100644
--- a/library/std/src/sync/condvar/tests.rs
+++ b/library/std/src/sync/poison/condvar/tests.rs
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/poison/mutex.rs
index e28c2090afe..e28c2090afe 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/poison/mutex.rs
diff --git a/library/std/src/sync/mutex/tests.rs b/library/std/src/sync/poison/mutex/tests.rs
index 395c8aada08..395c8aada08 100644
--- a/library/std/src/sync/mutex/tests.rs
+++ b/library/std/src/sync/poison/mutex/tests.rs
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/poison/once.rs
index 27db4b634fb..27db4b634fb 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/poison/once.rs
diff --git a/library/std/src/sync/once/tests.rs b/library/std/src/sync/poison/once/tests.rs
index ce96468aeb6..ce96468aeb6 100644
--- a/library/std/src/sync/once/tests.rs
+++ b/library/std/src/sync/poison/once/tests.rs
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/poison/rwlock.rs
index 1519baf99a8..1519baf99a8 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/poison/rwlock.rs
diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/poison/rwlock/tests.rs
index 057c2f1a5d7..057c2f1a5d7 100644
--- a/library/std/src/sync/rwlock/tests.rs
+++ b/library/std/src/sync/poison/rwlock/tests.rs
diff --git a/library/std/src/sys/sync/once/futex.rs b/library/std/src/sys/sync/once/futex.rs
index 10bfa81a6d7..539f0fe89ea 100644
--- a/library/std/src/sys/sync/once/futex.rs
+++ b/library/std/src/sys/sync/once/futex.rs
@@ -1,7 +1,7 @@
 use crate::cell::Cell;
 use crate::sync as public;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sync::once::ExclusiveState;
+use crate::sync::poison::once::ExclusiveState;
 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.
diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs
index 88a1d50361e..2568059cfe3 100644
--- a/library/std/src/sys/sync/once/no_threads.rs
+++ b/library/std/src/sys/sync/once/no_threads.rs
@@ -1,6 +1,6 @@
 use crate::cell::Cell;
 use crate::sync as public;
-use crate::sync::once::ExclusiveState;
+use crate::sync::poison::once::ExclusiveState;
 
 pub struct Once {
     state: Cell<State>,
diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs
index 5beff4ce683..fde1e0ca510 100644
--- a/library/std/src/sys/sync/once/queue.rs
+++ b/library/std/src/sys/sync/once/queue.rs
@@ -58,7 +58,7 @@
 use crate::cell::Cell;
 use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release};
 use crate::sync::atomic::{AtomicBool, AtomicPtr};
-use crate::sync::once::ExclusiveState;
+use crate::sync::poison::once::ExclusiveState;
 use crate::thread::{self, Thread};
 use crate::{fmt, ptr, sync as public};