aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2023-02-06 19:08:47 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-02-06 19:08:47 +0000
commit69d2c7b3f3e785560cbb335f7051bceebf97f24c (patch)
tree985643efd2373ac19cca331f0ae3209034124768
parent2f0f992ac613310e6583bae2a67c78db8d048be5 (diff)
parentc78c9dff44a4f09e9f32272ff362260f4dabce01 (diff)
downloadonce_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.json2
-rw-r--r--.github/workflows/ci.yaml5
-rw-r--r--Android.bp6
-rw-r--r--CHANGELOG.md4
-rw-r--r--Cargo.toml2
-rw-r--r--Cargo.toml.orig2
-rw-r--r--METADATA15
-rw-r--r--README.md2
-rw-r--r--src/lib.rs14
-rw-r--r--src/race.rs92
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
diff --git a/Android.bp b/Android.bp
index 59ae682..8ccac56 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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`,
diff --git a/Cargo.toml b/Cargo.toml
index 6587f4e..d2d7f19 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/METADATA b/METADATA
index ef462f7..61e5516 100644
--- a/METADATA
+++ b/METADATA
@@ -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
}
}
diff --git a/README.md b/README.md
index de65dbb..737f2de 100644
--- a/README.md
+++ b/README.md
@@ -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).
diff --git a/src/lib.rs b/src/lib.rs
index 41313f7..83149ac 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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;