Skip to content

Commit b526b0d

Browse files
GrigorenkoPVgitbot
authored and
gitbot
committed
Move some things to std::sync::poison and reexport them in std::sync
1 parent adbb9b7 commit b526b0d

File tree

16 files changed

+131
-27
lines changed

16 files changed

+131
-27
lines changed

std/src/sync/barrier.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
mod tests;
33

44
use crate::fmt;
5+
// FIXME(nonpoison_mutex,nonpoison_condvar): switch to nonpoison versions once they are available
56
use crate::sync::{Condvar, Mutex};
67

78
/// A barrier enables multiple threads to synchronize the beginning

std/src/sync/lazy_lock.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::once::ExclusiveState;
1+
use super::poison::once::ExclusiveState;
22
use crate::cell::UnsafeCell;
33
use crate::mem::ManuallyDrop;
44
use crate::ops::Deref;
@@ -63,6 +63,7 @@ union Data<T, F> {
6363
/// ```
6464
#[stable(feature = "lazy_cell", since = "1.80.0")]
6565
pub struct LazyLock<T, F = fn() -> T> {
66+
// FIXME(nonpoison_once): if possible, switch to nonpoison version once it is available
6667
once: Once,
6768
data: UnsafeCell<Data<T, F>>,
6869
}

std/src/sync/mod.rs

+37-19
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@
167167
168168
#![stable(feature = "rust1", since = "1.0.0")]
169169

170+
// No formatting: this file is just re-exports, and their order is worth preserving.
171+
#![cfg_attr(rustfmt, rustfmt::skip)]
172+
173+
// These come from `core` & `alloc` and only in one flavor: no poisoning.
170174
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
171175
pub use core::sync::Exclusive;
172176
#[stable(feature = "rust1", since = "1.0.0")]
@@ -175,40 +179,54 @@ pub use core::sync::atomic;
175179
#[stable(feature = "rust1", since = "1.0.0")]
176180
pub use alloc_crate::sync::{Arc, Weak};
177181

182+
// FIXME(sync_nonpoison,sync_poison_mod): remove all `#[doc(inline)]` once the modules are stabilized.
183+
184+
// These exist only in one flavor: no poisoning.
178185
#[stable(feature = "rust1", since = "1.0.0")]
179186
pub use self::barrier::{Barrier, BarrierWaitResult};
180-
#[stable(feature = "rust1", since = "1.0.0")]
181-
pub use self::condvar::{Condvar, WaitTimeoutResult};
182187
#[stable(feature = "lazy_cell", since = "1.80.0")]
183188
pub use self::lazy_lock::LazyLock;
184-
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
185-
pub use self::mutex::MappedMutexGuard;
186-
#[stable(feature = "rust1", since = "1.0.0")]
187-
pub use self::mutex::{Mutex, MutexGuard};
188-
#[stable(feature = "rust1", since = "1.0.0")]
189-
#[allow(deprecated)]
190-
pub use self::once::{ONCE_INIT, Once, OnceState};
191189
#[stable(feature = "once_cell", since = "1.70.0")]
192190
pub use self::once_lock::OnceLock;
193-
#[stable(feature = "rust1", since = "1.0.0")]
194-
pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult};
195191
#[unstable(feature = "reentrant_lock", issue = "121440")]
196192
pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
197-
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
198-
pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
193+
194+
// These make sense and exist only with poisoning.
199195
#[stable(feature = "rust1", since = "1.0.0")]
200-
pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
196+
#[doc(inline)]
197+
pub use self::poison::{LockResult, PoisonError};
198+
199+
// These (should) exist in both flavors: with and without poisoning.
200+
// FIXME(sync_nonpoison): implement nonpoison versions:
201+
// * Mutex (nonpoison_mutex)
202+
// * Condvar (nonpoison_condvar)
203+
// * Once (nonpoison_once)
204+
// * RwLock (nonpoison_rwlock)
205+
// The historical default is the version with poisoning.
206+
#[stable(feature = "rust1", since = "1.0.0")]
207+
#[doc(inline)]
208+
pub use self::poison::{
209+
Mutex, MutexGuard, TryLockError, TryLockResult,
210+
Condvar, WaitTimeoutResult,
211+
Once, OnceState,
212+
RwLock, RwLockReadGuard, RwLockWriteGuard,
213+
};
214+
#[stable(feature = "rust1", since = "1.0.0")]
215+
#[doc(inline)]
216+
#[expect(deprecated)]
217+
pub use self::poison::ONCE_INIT;
218+
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
219+
#[doc(inline)]
220+
pub use self::poison::{MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};
201221

202222
#[unstable(feature = "mpmc_channel", issue = "126840")]
203223
pub mod mpmc;
204224
pub mod mpsc;
205225

226+
#[unstable(feature = "sync_poison_mod", issue = "134646")]
227+
pub mod poison;
228+
206229
mod barrier;
207-
mod condvar;
208230
mod lazy_lock;
209-
mod mutex;
210-
pub(crate) mod once;
211231
mod once_lock;
212-
mod poison;
213232
mod reentrant_lock;
214-
mod rwlock;

std/src/sync/once_lock.rs

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ use crate::sync::Once;
101101
/// ```
102102
#[stable(feature = "once_cell", since = "1.70.0")]
103103
pub struct OnceLock<T> {
104+
// FIXME(nonpoison_once): switch to nonpoison version once it is available
104105
once: Once,
105106
// Whether or not the value is initialized is tracked by `once.is_completed()`.
106107
value: UnsafeCell<MaybeUninit<T>>,

std/src/sync/poison.rs

+84-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,92 @@
1+
//! Synchronization objects that employ poisoning.
2+
//!
3+
//! # Poisoning
4+
//!
5+
//! All synchronization objects in this module implement a strategy called "poisoning"
6+
//! where if a thread panics while holding the exclusive access granted by the primitive,
7+
//! the state of the primitive is set to "poisoned".
8+
//! This information is then propagated to all other threads
9+
//! to signify that the data protected by this primitive is likely tainted
10+
//! (some invariant is not being upheld).
11+
//!
12+
//! The specifics of how this "poisoned" state affects other threads
13+
//! depend on the primitive. See [#Overview] bellow.
14+
//!
15+
//! For the alternative implementations that do not employ poisoning,
16+
//! see `std::sys::nonpoisoning`.
17+
//!
18+
//! # Overview
19+
//!
20+
//! Below is a list of synchronization objects provided by this module
21+
//! with a high-level overview for each object and a description
22+
//! of how it employs "poisoning".
23+
//!
24+
//! - [`Condvar`]: Condition Variable, providing the ability to block
25+
//! a thread while waiting for an event to occur.
26+
//!
27+
//! Condition variables are typically associated with
28+
//! a boolean predicate (a condition) and a mutex.
29+
//! This implementation is associated with [`poison::Mutex`](Mutex),
30+
//! which employs poisoning.
31+
//! For this reason, [`Condvar::wait()`] will return a [`LockResult`],
32+
//! just like [`poison::Mutex::lock()`](Mutex::lock) does.
33+
//!
34+
//! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at
35+
//! most one thread at a time is able to access some data.
36+
//!
37+
//! [`Mutex::lock()`] returns a [`LockResult`],
38+
//! providing a way to deal with the poisoned state.
39+
//! See [`Mutex`'s documentation](Mutex#poisoning) for more.
40+
//!
41+
//! - [`Once`]: A thread-safe way to run a piece of code only once.
42+
//! Mostly useful for implementing one-time global initialization.
43+
//!
44+
//! [`Once`] is poisoned if the piece of code passed to
45+
//! [`Once::call_once()`] or [`Once::call_once_force()`] panics.
46+
//! When in poisoned state, subsequent calls to [`Once::call_once()`] will panic too.
47+
//! [`Once::call_once_force()`] can be used to clear the poisoned state.
48+
//!
49+
//! - [`RwLock`]: Provides a mutual exclusion mechanism which allows
50+
//! multiple readers at the same time, while allowing only one
51+
//! writer at a time. In some cases, this can be more efficient than
52+
//! a mutex.
53+
//!
54+
//! This implementation, like [`Mutex`], will become poisoned on a panic.
55+
//! Note, however, that an `RwLock` may only be poisoned if a panic occurs
56+
//! while it is locked exclusively (write mode). If a panic occurs in any reader,
57+
//! then the lock will not be poisoned.
58+
59+
// FIXME(sync_nonpoison) add links to sync::nonpoison to the doc comment above.
60+
61+
#[stable(feature = "rust1", since = "1.0.0")]
62+
pub use self::condvar::{Condvar, WaitTimeoutResult};
63+
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
64+
pub use self::mutex::MappedMutexGuard;
65+
#[stable(feature = "rust1", since = "1.0.0")]
66+
pub use self::mutex::{Mutex, MutexGuard};
67+
#[stable(feature = "rust1", since = "1.0.0")]
68+
#[expect(deprecated)]
69+
pub use self::once::ONCE_INIT;
70+
#[stable(feature = "rust1", since = "1.0.0")]
71+
pub use self::once::{Once, OnceState};
72+
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
73+
pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
74+
#[stable(feature = "rust1", since = "1.0.0")]
75+
pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
176
use crate::error::Error;
277
use crate::fmt;
378
#[cfg(panic = "unwind")]
479
use crate::sync::atomic::{AtomicBool, Ordering};
580
#[cfg(panic = "unwind")]
681
use crate::thread;
782

8-
pub struct Flag {
83+
mod condvar;
84+
#[stable(feature = "rust1", since = "1.0.0")]
85+
mod mutex;
86+
pub(crate) mod once;
87+
mod rwlock;
88+
89+
pub(crate) struct Flag {
990
#[cfg(panic = "unwind")]
1091
failed: AtomicBool,
1192
}
@@ -78,7 +159,7 @@ impl Flag {
78159
}
79160

80161
#[derive(Clone)]
81-
pub struct Guard {
162+
pub(crate) struct Guard {
82163
#[cfg(panic = "unwind")]
83164
panicking: bool,
84165
}
@@ -316,7 +397,7 @@ impl<T> Error for TryLockError<T> {
316397
}
317398
}
318399

319-
pub fn map_result<T, U, F>(result: LockResult<T>, f: F) -> LockResult<U>
400+
pub(crate) fn map_result<T, U, F>(result: LockResult<T>, f: F) -> LockResult<U>
320401
where
321402
F: FnOnce(T) -> U,
322403
{

std/src/sync/condvar.rs renamed to std/src/sync/poison/condvar.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
mod tests;
33

44
use crate::fmt;
5-
use crate::sync::{LockResult, MutexGuard, PoisonError, mutex, poison};
5+
use crate::sync::poison::{self, LockResult, MutexGuard, PoisonError, mutex};
66
use crate::sys::sync as sys;
77
use crate::time::{Duration, Instant};
88

@@ -16,6 +16,8 @@ use crate::time::{Duration, Instant};
1616
#[stable(feature = "wait_timeout", since = "1.5.0")]
1717
pub struct WaitTimeoutResult(bool);
1818

19+
// FIXME(sync_nonpoison): `WaitTimeoutResult` is actually poisoning-agnostic, it seems.
20+
// Should we take advantage of this fact?
1921
impl WaitTimeoutResult {
2022
/// Returns `true` if the wait was known to have timed out.
2123
///
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

std/src/sys/sync/once/futex.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::cell::Cell;
22
use crate::sync as public;
33
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
4-
use crate::sync::once::ExclusiveState;
4+
use crate::sync::poison::once::ExclusiveState;
55
use crate::sys::futex::{Futex, Primitive, futex_wait, futex_wake_all};
66

77
// On some platforms, the OS is very nice and handles the waiter queue for us.

std/src/sys/sync/once/no_threads.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::cell::Cell;
22
use crate::sync as public;
3-
use crate::sync::once::ExclusiveState;
3+
use crate::sync::poison::once::ExclusiveState;
44

55
pub struct Once {
66
state: Cell<State>,

std/src/sys/sync/once/queue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
use crate::cell::Cell;
5959
use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release};
6060
use crate::sync::atomic::{AtomicBool, AtomicPtr};
61-
use crate::sync::once::ExclusiveState;
61+
use crate::sync::poison::once::ExclusiveState;
6262
use crate::thread::{self, Thread};
6363
use crate::{fmt, ptr, sync as public};
6464

0 commit comments

Comments
 (0)