diff options
author | Jeff Vander Stoep <jeffv@google.com> | 2023-02-06 19:08:47 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-02-06 19:08:47 +0000 |
commit | 69d2c7b3f3e785560cbb335f7051bceebf97f24c (patch) | |
tree | 985643efd2373ac19cca331f0ae3209034124768 | |
parent | 2f0f992ac613310e6583bae2a67c78db8d048be5 (diff) | |
parent | c78c9dff44a4f09e9f32272ff362260f4dabce01 (diff) | |
download | once_cell-69d2c7b3f3e785560cbb335f7051bceebf97f24c.tar.gz |
Upgrade once_cell to 1.17.0 am: c78c9dff44
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/once_cell/+/2419306
Change-Id: Ieca639ddb0ac56bf15ccb25ca8de86f5912e3bf2
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | .github/workflows/ci.yaml | 5 | ||||
-rw-r--r-- | Android.bp | 6 | ||||
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | METADATA | 15 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | src/lib.rs | 14 | ||||
-rw-r--r-- | src/race.rs | 92 |
10 files changed, 126 insertions, 18 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index c13fae3..1d9d16c 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "c3a3ede16dc5c11df6be06fabd842795504e74b7" + "sha1": "85e372f818fc07c3688ef431b8735778b4b9430b" }, "path_in_vcs": "" }
\ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7967bb9..6a998a8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,8 @@ jobs: - uses: actions/checkout@v2 with: fetch-depth: 0 # fetch tags for publish - + - uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 - run: cargo run -p xtask -- ci env: - CRATES_IO_TOKEN: ${{ secrets.CRATES_IO_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }} + MIRIFLAGS: -Zmiri-strict-provenance @@ -42,7 +42,7 @@ rust_library { host_supported: true, crate_name: "once_cell", cargo_env_compat: true, - cargo_pkg_version: "1.16.0", + cargo_pkg_version: "1.17.0", srcs: ["src/lib.rs"], edition: "2021", features: [ @@ -84,7 +84,7 @@ rust_test { host_supported: true, crate_name: "once_cell", cargo_env_compat: true, - cargo_pkg_version: "1.16.0", + cargo_pkg_version: "1.17.0", srcs: ["src/lib.rs"], test_suites: ["general-tests"], auto_gen_config: true, @@ -110,7 +110,7 @@ rust_test { host_supported: true, crate_name: "it", cargo_env_compat: true, - cargo_pkg_version: "1.16.0", + cargo_pkg_version: "1.17.0", srcs: ["tests/it.rs"], test_suites: ["general-tests"], auto_gen_config: true, diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cf6ea6..3f3a862 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ - +## 1.17.0 + +- Add `race::OnceRef` for storing a `&'a T`. + ## 1.16.0 - Add `no_std` implementation based on `critical-section`, @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.56" name = "once_cell" -version = "1.16.0" +version = "1.17.0" authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"] exclude = [ "*.png", diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 9a9a6df..5ceec5e 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "once_cell" -version = "1.16.0" +version = "1.17.0" authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"] license = "MIT OR Apache-2.0" edition = "2021" @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/once_cell +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md + name: "once_cell" description: "Single assignment cells and lazy values." third_party { @@ -7,14 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/once_cell/once_cell-1.16.0.crate" + value: "https://static.crates.io/crates/once_cell/once_cell-1.17.0.crate" } - version: "1.16.0" - # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same. + version: "1.17.0" license_type: NOTICE last_upgrade_date { - year: 2022 - month: 12 - day: 13 + year: 2023 + month: 2 + day: 3 } } @@ -51,6 +51,8 @@ More patterns and use-cases are in the [docs](https://docs.rs/once_cell/)! * [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) The API of `once_cell` is being proposed for inclusion in [`std`](https://github.com/rust-lang/rfcs/pull/2788). @@ -208,7 +208,6 @@ //! ``` //! use once_cell::sync::OnceCell; //! -//! #[derive(Debug)] //! pub struct LateInit<T> { cell: OnceCell<T> } //! //! impl<T> LateInit<T> { @@ -228,22 +227,24 @@ //! } //! } //! -//! #[derive(Default, Debug)] +//! #[derive(Default)] //! struct A<'a> { //! b: LateInit<&'a B<'a>>, //! } //! -//! #[derive(Default, Debug)] +//! #[derive(Default)] //! struct B<'a> { //! a: LateInit<&'a A<'a>> //! } //! +//! //! fn build_cycle() { //! let a = A::default(); //! let b = B::default(); //! a.b.init(&b); //! b.a.init(&a); -//! println!("{:?}", a.b.a.b.a); +//! +//! let _a = &a.b.a.b.a; //! } //! ``` //! @@ -315,6 +316,10 @@ //! //! No, but you can use [`async_once_cell`](https://crates.io/crates/async_once_cell) instead. //! +//! **Can I bring my own mutex?** +//! +//! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to allow just that. +//! //! # Related crates //! //! * [double-checked-cell](https://github.com/niklasf/double-checked-cell) @@ -323,6 +328,7 @@ //! * [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). diff --git a/src/race.rs b/src/race.rs index fd255c4..dff5847 100644 --- a/src/race.rs +++ b/src/race.rs @@ -25,6 +25,8 @@ use atomic_polyfill as atomic; use core::sync::atomic; use atomic::{AtomicUsize, Ordering}; +use core::cell::UnsafeCell; +use core::marker::PhantomData; use core::num::NonZeroUsize; /// A thread-safe cell which can be written to only once. @@ -172,6 +174,96 @@ impl OnceBool { } } +/// A thread-safe cell which can be written to only once. +pub struct OnceRef<'a, T> { + inner: OnceNonZeroUsize, + ghost: PhantomData<UnsafeCell<&'a T>>, +} + +// TODO: Replace UnsafeCell with SyncUnsafeCell once stabilized +unsafe impl<'a, T: Sync> Sync for OnceRef<'a, T> {} + +impl<'a, T> core::fmt::Debug for OnceRef<'a, T> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "OnceRef({:?})", self.inner) + } +} + +impl<'a, T> Default for OnceRef<'a, T> { + fn default() -> Self { + Self::new() + } +} + +impl<'a, T> OnceRef<'a, T> { + /// Creates a new empty cell. + pub const fn new() -> OnceRef<'a, T> { + OnceRef { inner: OnceNonZeroUsize::new(), 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) }) + } + + /// Sets the contents of this cell to `value`. + /// + /// 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) + } + + /// Gets the contents of the cell, initializing it with `f` if the cell was + /// empty. + /// + /// If several threads concurrently run `get_or_init`, more than one `f` can + /// be called. However, all threads will return the same value, produced by + /// some `f`. + pub fn get_or_init<F>(&self, f: F) -> &'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) } + } + + /// Gets the contents of the cell, initializing it with `f` if + /// the cell was empty. If the cell was empty and `f` failed, an + /// error is returned. + /// + /// If several threads concurrently run `get_or_init`, more than one `f` can + /// be called. However, all threads will return the same value, produced by + /// some `f`. + pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&'a T, E> + 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)) } + } + + /// ```compile_fail + /// use once_cell::race::OnceRef; + /// + /// let mut l = OnceRef::new(); + /// + /// { + /// let y = 2; + /// let mut r = OnceRef::new(); + /// r.set(&y).unwrap(); + /// core::mem::swap(&mut l, &mut r); + /// } + /// + /// // l now contains a dangling reference to y + /// eprintln!("uaf: {}", l.get().unwrap()); + /// ``` + fn _dummy() {} +} + #[cfg(feature = "alloc")] pub use self::once_box::OnceBox; |