diff options
Diffstat (limited to 'vendor/once_cell/src')
-rw-r--r-- | vendor/once_cell/src/imp_cs.rs | 2 | ||||
-rw-r--r-- | vendor/once_cell/src/imp_pl.rs | 4 | ||||
-rw-r--r-- | vendor/once_cell/src/imp_std.rs | 20 | ||||
-rw-r--r-- | vendor/once_cell/src/lib.rs | 163 | ||||
-rw-r--r-- | vendor/once_cell/src/race.rs | 2 |
5 files changed, 104 insertions, 87 deletions
diff --git a/vendor/once_cell/src/imp_cs.rs b/vendor/once_cell/src/imp_cs.rs index 668f18ec6..04018f119 100644 --- a/vendor/once_cell/src/imp_cs.rs +++ b/vendor/once_cell/src/imp_cs.rs @@ -63,7 +63,7 @@ impl<T> OnceCell<T> { pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); // SAFETY: The caller ensures that the value is initialized and access synchronized. - crate::unwrap_unchecked(self.value.borrow(CriticalSection::new()).get()) + self.value.borrow(CriticalSection::new()).get().unwrap_unchecked() } #[inline] diff --git a/vendor/once_cell/src/imp_pl.rs b/vendor/once_cell/src/imp_pl.rs index 84d859386..37a85547d 100644 --- a/vendor/once_cell/src/imp_pl.rs +++ b/vendor/once_cell/src/imp_pl.rs @@ -58,7 +58,7 @@ impl<T> OnceCell<T> { // but that is more complicated // - finally, if it returns Ok, we store the value and store the flag with // `Release`, which synchronizes with `Acquire`s. - let f = unsafe { crate::unwrap_unchecked(f.take()) }; + let f = unsafe { f.take().unwrap_unchecked() }; match f() { Ok(value) => unsafe { // Safe b/c we have a unique access and no panic may happen @@ -101,7 +101,7 @@ impl<T> OnceCell<T> { pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); let slot = &*self.value.get(); - crate::unwrap_unchecked(slot.as_ref()) + slot.as_ref().unwrap_unchecked() } /// Gets the mutable reference to the underlying value. diff --git a/vendor/once_cell/src/imp_std.rs b/vendor/once_cell/src/imp_std.rs index 5761f0184..3b9e6d205 100644 --- a/vendor/once_cell/src/imp_std.rs +++ b/vendor/once_cell/src/imp_std.rs @@ -5,7 +5,6 @@ use std::{ cell::{Cell, UnsafeCell}, - marker::PhantomData, panic::{RefUnwindSafe, UnwindSafe}, sync::atomic::{AtomicBool, AtomicPtr, Ordering}, thread::{self, Thread}, @@ -22,7 +21,6 @@ pub(crate) struct OnceCell<T> { // State is encoded in two low bits. Only `INCOMPLETE` and `RUNNING` states // allow waiters. queue: AtomicPtr<Waiter>, - _marker: PhantomData<*mut Waiter>, value: UnsafeCell<Option<T>>, } @@ -39,19 +37,11 @@ impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {} impl<T> OnceCell<T> { pub(crate) const fn new() -> OnceCell<T> { - OnceCell { - queue: AtomicPtr::new(INCOMPLETE_PTR), - _marker: PhantomData, - value: UnsafeCell::new(None), - } + OnceCell { queue: AtomicPtr::new(INCOMPLETE_PTR), value: UnsafeCell::new(None) } } pub(crate) const fn with_value(value: T) -> OnceCell<T> { - OnceCell { - queue: AtomicPtr::new(COMPLETE_PTR), - _marker: PhantomData, - value: UnsafeCell::new(Some(value)), - } + OnceCell { queue: AtomicPtr::new(COMPLETE_PTR), value: UnsafeCell::new(Some(value)) } } /// Safety: synchronizes with store to value via Release/(Acquire|SeqCst). @@ -78,7 +68,7 @@ impl<T> OnceCell<T> { initialize_or_wait( &self.queue, Some(&mut || { - let f = unsafe { crate::unwrap_unchecked(f.take()) }; + let f = unsafe { f.take().unwrap_unchecked() }; match f() { Ok(value) => { unsafe { *slot = Some(value) }; @@ -109,7 +99,7 @@ impl<T> OnceCell<T> { pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); let slot = &*self.value.get(); - crate::unwrap_unchecked(slot.as_ref()) + slot.as_ref().unwrap_unchecked() } /// Gets the mutable reference to the underlying value. @@ -209,7 +199,7 @@ fn initialize_or_wait(queue: &AtomicPtr<Waiter>, mut init: Option<&mut dyn FnMut return; } (INCOMPLETE, None) | (RUNNING, _) => { - wait(&queue, curr_queue); + wait(queue, curr_queue); curr_queue = queue.load(Ordering::Acquire); } _ => debug_assert!(false), diff --git a/vendor/once_cell/src/lib.rs b/vendor/once_cell/src/lib.rs index c2061f89f..db7e19a8a 100644 --- a/vendor/once_cell/src/lib.rs +++ b/vendor/once_cell/src/lib.rs @@ -1,8 +1,10 @@ //! # Overview //! -//! `once_cell` provides two new cell-like types, [`unsync::OnceCell`] and [`sync::OnceCell`]. A `OnceCell` -//! might store arbitrary non-`Copy` types, can be assigned to at most once and provides direct access -//! to the stored contents. The core API looks *roughly* like this (and there's much more inside, read on!): +//! `once_cell` provides two new cell-like types, [`unsync::OnceCell`] and +//! [`sync::OnceCell`]. A `OnceCell` might store arbitrary non-`Copy` types, can +//! be assigned to at most once and provides direct access to the stored +//! contents. The core API looks *roughly* like this (and there's much more +//! inside, read on!): //! //! ```rust,ignore //! impl<T> OnceCell<T> { @@ -12,11 +14,12 @@ //! } //! ``` //! -//! Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires only a shared reference. -//! Because of the single assignment restriction `get` can return a `&T` instead of `Ref<T>` -//! or `MutexGuard<T>`. +//! Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires +//! only a shared reference. Because of the single assignment restriction `get` +//! can return a `&T` instead of `Ref<T>` or `MutexGuard<T>`. //! -//! The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait), while the `unsync` one is not. +//! The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait), +//! while the `unsync` one is not. //! //! [`unsync::OnceCell`]: unsync/struct.OnceCell.html //! [`sync::OnceCell`]: sync/struct.OnceCell.html @@ -79,7 +82,8 @@ //! } //! ``` //! -//! There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to streamline this pattern: +//! There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to +//! streamline this pattern: //! //! ```rust //! use std::{sync::Mutex, collections::HashMap}; @@ -120,7 +124,8 @@ //! ``` //! //! If you need a lazy field in a struct, you probably should use `OnceCell` -//! directly, because that will allow you to access `self` during initialization. +//! directly, because that will allow you to access `self` during +//! initialization. //! //! ```rust //! use std::{fs, path::PathBuf}; @@ -156,7 +161,8 @@ //! } //! ``` //! -//! This macro can be useful to avoid the "compile regex on every loop iteration" problem. +//! This macro can be useful to avoid the "compile regex on every loop +//! iteration" problem. //! //! ## Runtime `include_bytes!` //! @@ -243,7 +249,7 @@ //! let b = B::default(); //! a.b.init(&b); //! b.a.init(&a); -//! +//! //! let _a = &a.b.a.b.a; //! } //! ``` @@ -262,23 +268,28 @@ //! |`Mutex<T>` | `MutexGuard<T>` | may deadlock at runtime, may block the thread | //! |`sync::OnceCell<T>` | `&T` | assignable only once, may block the thread | //! -//! Technically, calling `get_or_init` will also cause a panic or a deadlock if it recursively calls -//! itself. However, because the assignment can happen only once, such cases should be more rare than -//! equivalents with `RefCell` and `Mutex`. +//! Technically, calling `get_or_init` will also cause a panic or a deadlock if +//! it recursively calls itself. However, because the assignment can happen only +//! once, such cases should be more rare than equivalents with `RefCell` and +//! `Mutex`. //! //! # Minimum Supported `rustc` Version //! //! This crate's minimum supported `rustc` version is `1.56.0`. //! -//! If only the `std` feature is enabled, MSRV will be updated conservatively, supporting at least latest 8 versions of the compiler. -//! When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable. -//! In both cases, increasing MSRV is *not* considered a semver-breaking change. +//! If only the `std` feature is enabled, MSRV will be updated conservatively, +//! supporting at least latest 8 versions of the compiler. When using other +//! features, like `parking_lot`, MSRV might be updated more frequently, up to +//! the latest stable. In both cases, increasing MSRV is *not* considered a +//! semver-breaking change. //! //! # Implementation details //! -//! The implementation is based on the [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) -//! and [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and [`std::sync::Once`]. In some sense, -//! `once_cell` just streamlines and unifies those APIs. +//! The implementation is based on the +//! [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) and +//! [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and +//! [`std::sync::Once`]. In some sense, `once_cell` just streamlines and unifies +//! those APIs. //! //! To implement a sync flavor of `OnceCell`, this crates uses either a custom //! re-implementation of `std::sync::Once` or `parking_lot::Mutex`. This is @@ -292,46 +303,66 @@ //! //! # F.A.Q. //! -//! **Should I use lazy_static or once_cell?** +//! **Should I use the sync or unsync flavor?** //! -//! To the first approximation, `once_cell` is both more flexible and more convenient than `lazy_static` -//! and should be preferred. +//! Because Rust compiler checks thread safety for you, it's impossible to +//! accidentally use `unsync` where `sync` is required. So, use `unsync` in +//! single-threaded code and `sync` in multi-threaded. It's easy to switch +//! between the two if code becomes multi-threaded later. //! -//! Unlike `once_cell`, `lazy_static` supports spinlock-based implementation of blocking which works with -//! `#![no_std]`. +//! At the moment, `unsync` has an additional benefit that reentrant +//! initialization causes a panic, which might be easier to debug than a +//! deadlock. //! -//! `lazy_static` has received significantly more real world testing, but `once_cell` is also a widely -//! used crate. +//! **Does this crate support async?** //! -//! **Should I use the sync or unsync flavor?** +//! No, but you can use +//! [`async_once_cell`](https://crates.io/crates/async_once_cell) instead. //! -//! Because Rust compiler checks thread safety for you, it's impossible to accidentally use `unsync` where -//! `sync` is required. So, use `unsync` in single-threaded code and `sync` in multi-threaded. It's easy -//! to switch between the two if code becomes multi-threaded later. +//! **Does this crate support `no_std`?** //! -//! At the moment, `unsync` has an additional benefit that reentrant initialization causes a panic, which -//! might be easier to debug than a deadlock. +//! Yes, but with caveats. `OnceCell` is a synchronization primitive which +//! _semantically_ relies on blocking. `OnceCell` guarantees that at most one +//! `f` will be called to compute the value. If two threads of execution call +//! `get_or_init` concurrently, one of them has to wait. //! -//! **Does this crate support async?** +//! Waiting fundamentally requires OS support. Execution environment needs to +//! understand who waits on whom to prevent deadlocks due to priority inversion. +//! You _could_ make code to compile by blindly using pure spinlocks, but the +//! runtime behavior would be subtly wrong. +//! +//! Given these constraints, `once_cell` provides the following options: //! -//! No, but you can use [`async_once_cell`](https://crates.io/crates/async_once_cell) instead. +//! - The `race` module provides similar, but distinct synchronization primitive +//! which is compatible with `no_std`. With `race`, the `f` function can be +//! called multiple times by different threads, but only one thread will win +//! to install the value. +//! - `critical-section` feature (with a `-`, not `_`) uses `critical_section` +//! to implement blocking. //! //! **Can I bring my own mutex?** //! -//! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to allow just that. +//! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to +//! allow just that. +//! +//! **Should I use `std::cell::OnceCell`, `once_cell`, or `lazy_static`?** +//! +//! If you can use `std` version (your MSRV is at least 1.70, and you don't need +//! extra features `once_cell` provides), use `std`. Otherwise, use `once_cell`. +//! Don't use `lazy_static`. //! //! # Related crates //! +//! * Most of this crate's functionality is available in `std` starting with +//! Rust 1.70. See `std::cell::OnceCell` and `std::sync::OnceLock`. //! * [double-checked-cell](https://github.com/niklasf/double-checked-cell) //! * [lazy-init](https://crates.io/crates/lazy-init) //! * [lazycell](https://crates.io/crates/lazycell) //! * [mitochondria](https://crates.io/crates/mitochondria) //! * [lazy_static](https://crates.io/crates/lazy_static) //! * [async_once_cell](https://crates.io/crates/async_once_cell) -//! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring your own mutex) -//! -//! Most of this crate's functionality is available in `std` in nightly Rust. -//! See the [tracking issue](https://github.com/rust-lang/rust/issues/74465). +//! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring +//! your own mutex) #![cfg_attr(not(feature = "std"), no_std)] @@ -359,8 +390,6 @@ pub mod unsync { panic::{RefUnwindSafe, UnwindSafe}, }; - use super::unwrap_unchecked; - /// A cell which can be written to only once. It is not thread safe. /// /// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&` @@ -532,7 +561,7 @@ pub mod unsync { // checked that slot is currently `None`, so this write // maintains the `inner`'s invariant. *slot = Some(value); - Ok(unsafe { unwrap_unchecked(slot.as_ref()) }) + Ok(unsafe { slot.as_ref().unwrap_unchecked() }) } /// Gets the contents of the cell, initializing it with `f` @@ -605,7 +634,7 @@ pub mod unsync { // `assert`, while keeping `set/get` would be sound, but it seems // better to panic, rather than to silently use an old value. assert!(self.set(val).is_ok(), "reentrant init"); - Ok(unsafe { unwrap_unchecked(self.get()) }) + Ok(unsafe { self.get().unwrap_unchecked() }) } /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. @@ -638,7 +667,7 @@ pub mod unsync { /// cell = OnceCell::new(); /// ``` pub fn take(&mut self) -> Option<T> { - mem::replace(self, Self::default()).into_inner() + mem::take(self).into_inner() } /// Consumes the `OnceCell`, returning the wrapped value. @@ -765,8 +794,14 @@ pub mod unsync { /// assert_eq!(*lazy, 92); /// ``` pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T { - Self::force(this); - Self::get_mut(this).unwrap_or_else(|| unreachable!()) + if this.cell.get_mut().is_none() { + let value = match this.init.get_mut().take() { + Some(f) => f(), + None => panic!("Lazy instance has previously been poisoned"), + }; + this.cell = OnceCell::with_value(value); + } + this.cell.get_mut().unwrap_or_else(|| unreachable!()) } /// Gets the reference to the result of this lazy value if @@ -813,8 +848,7 @@ pub mod unsync { impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> { fn deref_mut(&mut self) -> &mut T { - Lazy::force(self); - self.cell.get_mut().unwrap_or_else(|| unreachable!()) + Lazy::force_mut(self) } } @@ -836,7 +870,7 @@ pub mod sync { panic::RefUnwindSafe, }; - use super::{imp::OnceCell as Imp, unwrap_unchecked}; + use super::imp::OnceCell as Imp; /// A thread-safe cell which can be written to only once. /// @@ -1047,7 +1081,7 @@ pub mod sync { /// ``` pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { let mut value = Some(value); - let res = self.get_or_init(|| unsafe { unwrap_unchecked(value.take()) }); + let res = self.get_or_init(|| unsafe { value.take().unwrap_unchecked() }); match value { None => Ok(res), Some(value) => Err((res, value)), @@ -1163,7 +1197,7 @@ pub mod sync { /// cell = OnceCell::new(); /// ``` pub fn take(&mut self) -> Option<T> { - mem::replace(self, Self::default()).into_inner() + mem::take(self).into_inner() } /// Consumes the `OnceCell`, returning the wrapped value. Returns @@ -1293,8 +1327,14 @@ pub mod sync { /// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92); /// ``` pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T { - Self::force(this); - Self::get_mut(this).unwrap_or_else(|| unreachable!()) + if this.cell.get_mut().is_none() { + let value = match this.init.get_mut().take() { + Some(f) => f(), + None => panic!("Lazy instance has previously been poisoned"), + }; + this.cell = OnceCell::with_value(value); + } + this.cell.get_mut().unwrap_or_else(|| unreachable!()) } /// Gets the reference to the result of this lazy value if @@ -1341,8 +1381,7 @@ pub mod sync { impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> { fn deref_mut(&mut self) -> &mut T { - Lazy::force(self); - self.cell.get_mut().unwrap_or_else(|| unreachable!()) + Lazy::force_mut(self) } } @@ -1373,15 +1412,3 @@ pub mod sync { #[cfg(feature = "race")] pub mod race; - -// Remove once MSRV is at least 1.58. -#[inline] -unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T { - match val { - Some(value) => value, - None => { - debug_assert!(false); - core::hint::unreachable_unchecked() - } - } -} diff --git a/vendor/once_cell/src/race.rs b/vendor/once_cell/src/race.rs index ee3d51a58..fe36fa174 100644 --- a/vendor/once_cell/src/race.rs +++ b/vendor/once_cell/src/race.rs @@ -351,7 +351,7 @@ mod once_box { Ordering::AcqRel, Ordering::Acquire, ); - if let Err(_) = exchange { + if exchange.is_err() { let value = unsafe { Box::from_raw(ptr) }; return Err(value); } |