Skip to content

Commit 9007792

Browse files
committed
Move some things to std::sync::poison and reexport them in std::sync
1 parent 85c3989 commit 9007792

File tree

18 files changed

+141
-30
lines changed

18 files changed

+141
-30
lines changed

library/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

library/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
}

library/std/src/sync/mod.rs

+44-19
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@
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+
174+
// These come from `core` & `alloc` and only in one flavor: no poisoning.
170175
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
171176
pub use core::sync::Exclusive;
172177
#[stable(feature = "rust1", since = "1.0.0")]
@@ -175,40 +180,60 @@ pub use core::sync::atomic;
175180
#[stable(feature = "rust1", since = "1.0.0")]
176181
pub use alloc_crate::sync::{Arc, Weak};
177182

183+
// FIXME(sync_nonpoison,sync_poison_mod): remove all `#[doc(inline)]` once the modules are stabilized.
184+
185+
// These exist only in one flavor: no poisoning.
178186
#[stable(feature = "rust1", since = "1.0.0")]
179187
pub use self::barrier::{Barrier, BarrierWaitResult};
180-
#[stable(feature = "rust1", since = "1.0.0")]
181-
pub use self::condvar::{Condvar, WaitTimeoutResult};
182188
#[stable(feature = "lazy_cell", since = "1.80.0")]
183189
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};
191190
#[stable(feature = "once_cell", since = "1.70.0")]
192191
pub use self::once_lock::OnceLock;
193-
#[stable(feature = "rust1", since = "1.0.0")]
194-
pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult};
195192
#[unstable(feature = "reentrant_lock", issue = "121440")]
196193
pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
197-
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
198-
pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
194+
195+
196+
// These make sense and exist only with poisoning.
197+
#[stable(feature = "rust1", since = "1.0.0")]
198+
#[doc(inline)]
199+
pub use self::poison::{LockResult, PoisonError};
200+
201+
202+
// These (should) exist in both flavors: with and without poisoning.
203+
// FIXME(sync_nonpoison): implement nonpoison versions:
204+
// * Mutex (nonpoison_mutex)
205+
// * Condvar (nonpoison_condvar)
206+
// * Once (nonpoison_once)
207+
// * RwLock (nonpoison_rwlock)
208+
209+
// FIXME(sync_nonpoison): conditionally select the default flavor based on edition(?).
210+
use self::poison as default_poison_flavor;
211+
212+
#[stable(feature = "rust1", since = "1.0.0")]
213+
#[doc(inline)]
214+
pub use default_poison_flavor::{
215+
Mutex, MutexGuard, TryLockError, TryLockResult,
216+
Condvar, WaitTimeoutResult,
217+
Once, OnceState,
218+
RwLock, RwLockReadGuard, RwLockWriteGuard,
219+
};
199220
#[stable(feature = "rust1", since = "1.0.0")]
200-
pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
221+
#[doc(inline)]
222+
#[expect(deprecated)]
223+
pub use default_poison_flavor::ONCE_INIT;
224+
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
225+
#[doc(inline)]
226+
pub use default_poison_flavor::{MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};
227+
201228

202229
#[unstable(feature = "mpmc_channel", issue = "126840")]
203230
pub mod mpmc;
204231
pub mod mpsc;
205232

233+
#[unstable(feature = "sync_poison_mod", issue = "134646")]
234+
pub mod poison;
235+
206236
mod barrier;
207-
mod condvar;
208237
mod lazy_lock;
209-
mod mutex;
210-
pub(crate) mod once;
211238
mod once_lock;
212-
mod poison;
213239
mod reentrant_lock;
214-
mod rwlock;

library/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>>,

library/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
{

library/std/src/sync/condvar.rs renamed to library/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.

library/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.

library/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>,

library/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

tests/ui/traits/const-traits/span-bug-issue-121418.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ LL | pub const fn new() -> std::sync::Mutex<dyn T> {}
2727
|
2828
= help: within `Mutex<(dyn T + 'static)>`, the trait `Sized` is not implemented for `(dyn T + 'static)`
2929
note: required because it appears within the type `Mutex<(dyn T + 'static)>`
30-
--> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
30+
--> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL
3131
= note: the return type of a function must have a statically known size
3232

3333
error: aborting due to 3 previous errors

tests/ui/typeck/assign-non-lval-derefmut.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ LL | x.lock().unwrap() += 1;
2020
| cannot use `+=` on type `MutexGuard<'_, usize>`
2121
|
2222
note: the foreign item type `MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
23-
--> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
23+
--> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL
2424
|
2525
= note: not implement `AddAssign<{integer}>`
2626
help: `+=` can be used on `usize` if you dereference the left-hand side
@@ -52,7 +52,7 @@ LL | y += 1;
5252
| cannot use `+=` on type `MutexGuard<'_, usize>`
5353
|
5454
note: the foreign item type `MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
55-
--> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
55+
--> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL
5656
|
5757
= note: not implement `AddAssign<{integer}>`
5858
help: `+=` can be used on `usize` if you dereference the left-hand side

0 commit comments

Comments
 (0)