summaryrefslogtreecommitdiffstats
path: root/vendor/once_cell/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:29 +0000
commit631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch)
treea1b87c8f8cad01cf18f7c5f57a08f102771ed303 /vendor/once_cell/src
parentAdding debian version 1.69.0+dfsg1-1. (diff)
downloadrustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.tar.xz
rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/once_cell/src')
-rw-r--r--vendor/once_cell/src/lib.rs5
-rw-r--r--vendor/once_cell/src/race.rs47
2 files changed, 39 insertions, 13 deletions
diff --git a/vendor/once_cell/src/lib.rs b/vendor/once_cell/src/lib.rs
index 83149ac4f..c2061f89f 100644
--- a/vendor/once_cell/src/lib.rs
+++ b/vendor/once_cell/src/lib.rs
@@ -454,7 +454,10 @@ pub mod unsync {
/// Returns `None` if the cell is empty.
#[inline]
pub fn get(&self) -> Option<&T> {
- // Safe due to `inner`'s invariant
+ // Safe due to `inner`'s invariant of being written to at most once.
+ // Had multiple writes to `inner` been allowed, a reference to the
+ // value we return now would become dangling by a write of a
+ // different value later.
unsafe { &*self.inner.get() }.as_ref()
}
diff --git a/vendor/once_cell/src/race.rs b/vendor/once_cell/src/race.rs
index dff5847c8..ee3d51a58 100644
--- a/vendor/once_cell/src/race.rs
+++ b/vendor/once_cell/src/race.rs
@@ -24,10 +24,11 @@ use atomic_polyfill as atomic;
#[cfg(not(feature = "critical-section"))]
use core::sync::atomic;
-use atomic::{AtomicUsize, Ordering};
+use atomic::{AtomicPtr, AtomicUsize, Ordering};
use core::cell::UnsafeCell;
use core::marker::PhantomData;
use core::num::NonZeroUsize;
+use core::ptr;
/// A thread-safe cell which can be written to only once.
#[derive(Default, Debug)]
@@ -176,7 +177,7 @@ impl OnceBool {
/// A thread-safe cell which can be written to only once.
pub struct OnceRef<'a, T> {
- inner: OnceNonZeroUsize,
+ inner: AtomicPtr<T>,
ghost: PhantomData<UnsafeCell<&'a T>>,
}
@@ -198,12 +199,13 @@ impl<'a, T> Default for OnceRef<'a, T> {
impl<'a, T> OnceRef<'a, T> {
/// Creates a new empty cell.
pub const fn new() -> OnceRef<'a, T> {
- OnceRef { inner: OnceNonZeroUsize::new(), ghost: PhantomData }
+ OnceRef { inner: AtomicPtr::new(ptr::null_mut()), ghost: PhantomData }
}
/// Gets a reference to the underlying value.
pub fn get(&self) -> Option<&'a T> {
- self.inner.get().map(|ptr| unsafe { &*(ptr.get() as *const T) })
+ let ptr = self.inner.load(Ordering::Acquire);
+ unsafe { ptr.as_ref() }
}
/// Sets the contents of this cell to `value`.
@@ -211,8 +213,13 @@ impl<'a, T> OnceRef<'a, T> {
/// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
/// full.
pub fn set(&self, value: &'a T) -> Result<(), ()> {
- let ptr = NonZeroUsize::new(value as *const T as usize).unwrap();
- self.inner.set(ptr)
+ let ptr = value as *const T as *mut T;
+ let exchange =
+ self.inner.compare_exchange(ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire);
+ match exchange {
+ Ok(_) => Ok(()),
+ Err(_) => Err(()),
+ }
}
/// Gets the contents of the cell, initializing it with `f` if the cell was
@@ -225,9 +232,11 @@ impl<'a, T> OnceRef<'a, T> {
where
F: FnOnce() -> &'a T,
{
- let f = || NonZeroUsize::new(f() as *const T as usize).unwrap();
- let ptr = self.inner.get_or_init(f);
- unsafe { &*(ptr.get() as *const T) }
+ enum Void {}
+ match self.get_or_try_init(|| Ok::<&'a T, Void>(f())) {
+ Ok(val) => val,
+ Err(void) => match void {},
+ }
}
/// Gets the contents of the cell, initializing it with `f` if
@@ -241,9 +250,23 @@ impl<'a, T> OnceRef<'a, T> {
where
F: FnOnce() -> Result<&'a T, E>,
{
- let f = || f().map(|value| NonZeroUsize::new(value as *const T as usize).unwrap());
- let ptr = self.inner.get_or_try_init(f)?;
- unsafe { Ok(&*(ptr.get() as *const T)) }
+ let mut ptr = self.inner.load(Ordering::Acquire);
+
+ if ptr.is_null() {
+ // TODO replace with `cast_mut` when MSRV reaches 1.65.0 (also in `set`)
+ ptr = f()? as *const T as *mut T;
+ let exchange = self.inner.compare_exchange(
+ ptr::null_mut(),
+ ptr,
+ Ordering::AcqRel,
+ Ordering::Acquire,
+ );
+ if let Err(old) = exchange {
+ ptr = old;
+ }
+ }
+
+ Ok(unsafe { &*ptr })
}
/// ```compile_fail