aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 06:57:37 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 06:57:37 +0000
commit28850595ed8a23655f117d52bcb57a14380b5bfa (patch)
tree95353df6eca9bf63f57a86070e6fad69c6061276
parent1b2ea50fdcdeca62f23ac071631fdb6ac16c6953 (diff)
parentd529398d91731a676c57a2787081a9d0485957f2 (diff)
downloadonce_cell-android13-mainline-cellbroadcast-release.tar.gz
Change-Id: I84f69728a2054598f57f9edeb4a49fe3384714ff
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp56
-rw-r--r--CHANGELOG.md8
-rw-r--r--Cargo.toml17
-rw-r--r--Cargo.toml.orig11
-rw-r--r--METADATA8
-rw-r--r--TEST_MAPPING85
-rw-r--r--cargo2android.json4
-rw-r--r--patches/imp_std.rs.patch20
-rw-r--r--patches/it.rs.patch36
-rw-r--r--src/imp_std.rs2
-rw-r--r--src/lib.rs184
-rw-r--r--src/race.rs27
-rw-r--r--tests/it.rs4
14 files changed, 393 insertions, 76 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 5b3900a..f070bea 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "6286eac17124140813e01342642f4fc060664991"
- }
-}
+ "sha1": "44852cc72dbfbf57c5477a907ec0ab36527bc36b"
+ },
+ "path_in_vcs": ""
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 8c67ad3..7211fe6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -41,6 +41,8 @@ rust_library {
name: "libonce_cell",
host_supported: true,
crate_name: "once_cell",
+ cargo_env_compat: true,
+ cargo_pkg_version: "1.9.0",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
@@ -51,8 +53,62 @@ rust_library {
],
apex_available: [
"//apex_available:platform",
+ "com.android.compos",
"com.android.resolv",
"com.android.virt",
],
min_sdk_version: "29",
}
+
+rust_test {
+ name: "once_cell_test_src_lib",
+ host_supported: true,
+ crate_name: "once_cell",
+ cargo_env_compat: true,
+ cargo_pkg_version: "1.9.0",
+ srcs: ["src/lib.rs"],
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ test_options: {
+ unit_test: true,
+ },
+ edition: "2018",
+ features: [
+ "alloc",
+ "default",
+ "race",
+ "std",
+ ],
+ rustlibs: [
+ "libcrossbeam_utils",
+ "liblazy_static",
+ "libregex",
+ ],
+}
+
+rust_test {
+ name: "once_cell_test_tests_it",
+ host_supported: true,
+ crate_name: "it",
+ cargo_env_compat: true,
+ cargo_pkg_version: "1.9.0",
+ srcs: ["tests/it.rs"],
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ test_options: {
+ unit_test: true,
+ },
+ edition: "2018",
+ features: [
+ "alloc",
+ "default",
+ "race",
+ "std",
+ ],
+ rustlibs: [
+ "libcrossbeam_utils",
+ "liblazy_static",
+ "libonce_cell",
+ "libregex",
+ ],
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53fdf64..2c95053 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 1.9
+
+- Added an `atomic-polyfill` optional dependency to compile `race` on platforms without atomics
+
+## 1.8.0
+
+- Add `try_insert` API -- a version of `set` that returns a reference.
+
## 1.7.2
- Improve code size when using parking_lot feature.
diff --git a/Cargo.toml b/Cargo.toml
index 0d3797b..0a94bfc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,19 +3,18 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "once_cell"
-version = "1.7.2"
+version = "1.9.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
-exclude = ["*.png", "*.svg", "/Cargo.lock.min", "/.travis.yml", "/run-miri-tests.sh", "rustfmt.toml"]
+exclude = ["*.png", "*.svg", "/Cargo.lock.msrv", "/.travis.yml", "/run-miri-tests.sh", "rustfmt.toml"]
description = "Single assignment cells and lazy values."
documentation = "https://docs.rs/once_cell"
readme = "README.md"
@@ -53,6 +52,10 @@ required-features = ["std"]
[[example]]
name = "test_synchronization"
required-features = ["std"]
+[dependencies.atomic-polyfill]
+version = "0.1"
+optional = true
+
[dependencies.parking_lot]
version = "0.11"
optional = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 259e3b0..3b2d1aa 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "once_cell"
-version = "1.7.2"
+version = "1.9.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2018"
@@ -13,7 +13,7 @@ repository = "https://github.com/matklad/once_cell"
keywords = ["lazy", "static"]
categories = ["rust-patterns", "memory-management"]
-exclude = ["*.png", "*.svg", "/Cargo.lock.min", "/.travis.yml", "/run-miri-tests.sh", "rustfmt.toml"]
+exclude = ["*.png", "*.svg", "/Cargo.lock.msrv", "/.travis.yml", "/run-miri-tests.sh", "rustfmt.toml"]
[workspace]
members = ["xtask"]
@@ -24,6 +24,13 @@ members = ["xtask"]
# for up to 16 bytes smaller, depending on the size of the T.
parking_lot = { version = "0.11", optional = true, default_features = false }
+# To be used in order to enable the race feature on targets
+# that do not have atomics
+# *Warning:* This can be unsound. Please read the README of
+# [atomic-polyfill](https://github.com/embassy-rs/atomic-polyfill)
+# and make sure you understand all the implications
+atomic-polyfill = { version = "0.1", optional = true }
+
[dev-dependencies]
lazy_static = "1.0.0"
crossbeam-utils = "0.7.2"
diff --git a/METADATA b/METADATA
index 3c1b227..4b16d85 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/once_cell/once_cell-1.7.2.crate"
+ value: "https://static.crates.io/crates/once_cell/once_cell-1.9.0.crate"
}
- version: "1.7.2"
+ version: "1.9.0"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 4
+ year: 2022
+ month: 3
day: 1
}
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a4df736..febfdce 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,66 +1,99 @@
// Generated by update_crate_tests.py for tests that depend on this crate.
{
+ "imports": [
+ {
+ "path": "external/rust/crates/quiche"
+ },
+ {
+ "path": "external/rust/crates/ring"
+ },
+ {
+ "path": "external/rust/crates/thread_local"
+ },
+ {
+ "path": "external/rust/crates/webpki"
+ }
+ ],
"presubmit": [
{
+ "name": "ZipFuseTest"
+ },
+ {
+ "name": "apkdmverity.test"
+ },
+ {
+ "name": "authfs_device_test_src_lib"
+ },
+ {
"name": "doh_unit_test"
},
{
- "name": "quiche_device_test_src_lib"
+ "name": "keystore2_test"
},
{
- "name": "ring_device_test_src_lib",
- "options": [
- {
- "test-timeout": "100000"
- }
- ]
+ "name": "legacykeystore_test"
},
{
- "name": "ring_device_test_tests_aead_tests"
+ "name": "libapkverify.integration_test"
},
{
- "name": "ring_device_test_tests_agreement_tests"
+ "name": "libapkverify.test"
},
{
- "name": "ring_device_test_tests_constant_time_tests"
+ "name": "libidsig.test"
},
{
- "name": "ring_device_test_tests_digest_tests",
- "options": [
- {
- "test-timeout": "600000"
- }
- ]
+ "name": "microdroid_manager_test"
},
{
- "name": "ring_device_test_tests_ecdsa_tests"
+ "name": "once_cell_test_src_lib"
+ },
+ {
+ "name": "once_cell_test_tests_it"
+ },
+ {
+ "name": "virtualizationservice_device_test"
+ }
+ ],
+ "presubmit-rust": [
+ {
+ "name": "ZipFuseTest"
+ },
+ {
+ "name": "apkdmverity.test"
+ },
+ {
+ "name": "authfs_device_test_src_lib"
+ },
+ {
+ "name": "doh_unit_test"
},
{
- "name": "ring_device_test_tests_ed25519_tests"
+ "name": "keystore2_test"
},
{
- "name": "ring_device_test_tests_hkdf_tests"
+ "name": "legacykeystore_test"
},
{
- "name": "ring_device_test_tests_hmac_tests"
+ "name": "libapkverify.integration_test"
},
{
- "name": "ring_device_test_tests_pbkdf2_tests"
+ "name": "libapkverify.test"
},
{
- "name": "ring_device_test_tests_quic_tests"
+ "name": "libidsig.test"
},
{
- "name": "ring_device_test_tests_rand_tests"
+ "name": "microdroid_manager_test"
},
{
- "name": "ring_device_test_tests_rsa_tests"
+ "name": "once_cell_test_src_lib"
},
{
- "name": "ring_device_test_tests_signature_tests"
+ "name": "once_cell_test_tests_it"
},
{
- "name": "thread_local_device_test_src_lib"
+ "name": "virtualizationservice_device_test"
}
]
}
diff --git a/cargo2android.json b/cargo2android.json
index 2e8c0ea..506d866 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,11 +1,13 @@
{
"apex-available": [
"//apex_available:platform",
+ "com.android.compos",
"com.android.resolv",
"com.android.virt"
],
"dependencies": true,
"device": true,
"min-sdk-version": "29",
- "run": true
+ "run": true,
+ "tests": true
} \ No newline at end of file
diff --git a/patches/imp_std.rs.patch b/patches/imp_std.rs.patch
new file mode 100644
index 0000000..556297f
--- /dev/null
+++ b/patches/imp_std.rs.patch
@@ -0,0 +1,20 @@
+diff --git a/src/imp_std.rs b/src/imp_std.rs
+index d7dda96..f461c3d 100644
+--- a/src/imp_std.rs
++++ b/src/imp_std.rs
+@@ -299,6 +299,7 @@ mod tests {
+ }
+
+ #[test]
++ #[cfg(not(target_os = "android"))]
+ fn poison_bad() {
+ static O: OnceCell<()> = OnceCell::new();
+
+@@ -320,6 +321,7 @@ mod tests {
+ }
+
+ #[test]
++ #[cfg(not(target_os = "android"))]
+ fn wait_for_force_to_finish() {
+ static O: OnceCell<()> = OnceCell::new();
+
diff --git a/patches/it.rs.patch b/patches/it.rs.patch
new file mode 100644
index 0000000..8491db5
--- /dev/null
+++ b/patches/it.rs.patch
@@ -0,0 +1,36 @@
+diff --git a/tests/it.rs b/tests/it.rs
+index 81faaff..c769487 100644
+--- a/tests/it.rs
++++ b/tests/it.rs
+@@ -166,6 +166,7 @@ mod unsync {
+
+ #[test]
+ #[cfg(feature = "std")]
++ #[cfg(not(target_os = "android"))]
+ fn lazy_poisoning() {
+ let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
+ for _ in 0..2 {
+@@ -288,6 +289,7 @@ mod sync {
+ }
+
+ #[test]
++ #[cfg(not(target_os = "android"))]
+ fn get_or_try_init() {
+ let cell: OnceCell<String> = OnceCell::new();
+ assert!(cell.get().is_none());
+@@ -348,6 +350,7 @@ mod sync {
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // miri doesn't support processes
++ #[ignore = "Android: ignore for now. Need to compile these binaries separately."]
+ fn reentrant_init() {
+ let examples_dir = {
+ let mut exe = std::env::current_exe().unwrap();
+@@ -486,6 +489,7 @@ mod sync {
+ }
+
+ #[test]
++ #[cfg(not(target_os = "android"))]
+ fn lazy_poisoning() {
+ let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
+ for _ in 0..2 {
diff --git a/src/imp_std.rs b/src/imp_std.rs
index d7dda96..f461c3d 100644
--- a/src/imp_std.rs
+++ b/src/imp_std.rs
@@ -299,6 +299,7 @@ mod tests {
}
#[test]
+ #[cfg(not(target_os = "android"))]
fn poison_bad() {
static O: OnceCell<()> = OnceCell::new();
@@ -320,6 +321,7 @@ mod tests {
}
#[test]
+ #[cfg(not(target_os = "android"))]
fn wait_for_force_to_finish() {
static O: OnceCell<()> = OnceCell::new();
diff --git a/src/lib.rs b/src/lib.rs
index a455cb4..cb8bfc7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,7 +6,7 @@
//!
//! ```rust,ignore
//! impl<T> OnceCell<T> {
-//! fn new() -> OnceCell<T> { ... }
+//! const fn new() -> OnceCell<T> { ... }
//! fn set(&self, value: T) -> Result<(), T> { ... }
//! fn get(&self) -> Option<&T> { ... }
//! }
@@ -24,11 +24,11 @@
//! [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
//!
-//! # Patterns
+//! # Recipes
//!
//! `OnceCell` might be useful for a variety of patterns.
//!
-//! ## Safe Initialization of global data
+//! ## Safe Initialization of Global Data
//!
//! ```rust
//! use std::{env, io};
@@ -59,7 +59,7 @@
//! }
//! ```
//!
-//! ## Lazy initialized global data
+//! ## Lazy Initialized Global Data
//!
//! This is essentially the `lazy_static!` macro, but without a macro.
//!
@@ -97,6 +97,9 @@
//! }
//! ```
//!
+//! Note that the variable that holds `Lazy` is declared as `static`, *not*
+//! `const`. This is important: using `const` instead compiles, but works wrong.
+//!
//! [`sync::Lazy`]: sync/struct.Lazy.html
//! [`unsync::Lazy`]: unsync/struct.Lazy.html
//!
@@ -139,10 +142,9 @@
//! }
//! ```
//!
-//! ## Building block
+//! ## Lazily Compiled Regex
//!
-//! Naturally, it is possible to build other abstractions on top of `OnceCell`.
-//! For example, this is a `regex!` macro which takes a string literal and returns an
+//! This is a `regex!` macro which takes a string literal and returns an
//! *expression* that evaluates to a `&'static Regex`:
//!
//! ```
@@ -156,7 +158,51 @@
//!
//! This macro can be useful to avoid the "compile regex on every loop iteration" problem.
//!
-//! Another pattern would be a `LateInit` type for delayed initialization:
+//! ## Runtime `include_bytes!`
+//!
+//! The `include_bytes` macro is useful to include test resources, but it slows
+//! down test compilation a lot. An alternative is to load the resources at
+//! runtime:
+//!
+//! ```
+//! use std::path::Path;
+//!
+//! use once_cell::sync::OnceCell;
+//!
+//! pub struct TestResource {
+//! path: &'static str,
+//! cell: OnceCell<Vec<u8>>,
+//! }
+//!
+//! impl TestResource {
+//! pub const fn new(path: &'static str) -> TestResource {
+//! TestResource { path, cell: OnceCell::new() }
+//! }
+//! pub fn bytes(&self) -> &[u8] {
+//! self.cell.get_or_init(|| {
+//! let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
+//! let path = Path::new(dir.as_str()).join(self.path);
+//! std::fs::read(&path).unwrap_or_else(|_err| {
+//! panic!("failed to load test resource: {}", path.display())
+//! })
+//! }).as_slice()
+//! }
+//! }
+//!
+//! static TEST_IMAGE: TestResource = TestResource::new("test_data/lena.png");
+//!
+//! #[test]
+//! fn test_sobel_filter() {
+//! let rgb: &[u8] = TEST_IMAGE.bytes();
+//! // ...
+//! # drop(rgb);
+//! }
+//! ```
+//!
+//! ## `lateinit`
+//!
+//! `LateInit` type for delayed initialization. It is reminiscent of Kotlin's
+//! `lateinit` keyword and allows construction of cyclic data structures:
//!
//!
//! ```
@@ -291,10 +337,11 @@ mod imp;
#[path = "imp_std.rs"]
mod imp;
+/// Single-threaded version of `OnceCell`.
pub mod unsync {
use core::{
cell::{Cell, UnsafeCell},
- fmt, mem,
+ fmt, hint, mem,
ops::{Deref, DerefMut},
};
@@ -394,6 +441,18 @@ pub mod unsync {
/// Gets a mutable reference to the underlying value.
///
/// Returns `None` if the cell is empty.
+ ///
+ /// This method is allowed to violate the invariant of writing to a `OnceCell`
+ /// at most once because it requires `&mut` access to `self`. As with all
+ /// interior mutability, `&mut` access permits arbitrary modification:
+ ///
+ /// ```
+ /// use once_cell::unsync::OnceCell;
+ ///
+ /// let mut cell: OnceCell<u32> = OnceCell::new();
+ /// cell.set(92).unwrap();
+ /// cell = OnceCell::new();
+ /// ```
pub fn get_mut(&mut self) -> Option<&mut T> {
// Safe because we have unique access
unsafe { &mut *self.inner.get() }.as_mut()
@@ -417,9 +476,29 @@ pub mod unsync {
/// assert!(cell.get().is_some());
/// ```
pub fn set(&self, value: T) -> Result<(), T> {
- let slot = unsafe { &*self.inner.get() };
- if slot.is_some() {
- return Err(value);
+ match self.try_insert(value) {
+ Ok(_) => Ok(()),
+ Err((_, value)) => Err(value),
+ }
+ }
+
+ /// Like [`set`](Self::set), but also returns a referce to the final cell value.
+ ///
+ /// # Example
+ /// ```
+ /// use once_cell::unsync::OnceCell;
+ ///
+ /// let cell = OnceCell::new();
+ /// assert!(cell.get().is_none());
+ ///
+ /// assert_eq!(cell.try_insert(92), Ok(&92));
+ /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
+ ///
+ /// assert!(cell.get().is_some());
+ /// ```
+ pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
+ if let Some(old) = self.get() {
+ return Err((old, value));
}
let slot = unsafe { &mut *self.inner.get() };
// This is the only place where we set the slot, no races
@@ -427,7 +506,10 @@ pub mod unsync {
// checked that slot is currently `None`, so this write
// maintains the `inner`'s invariant.
*slot = Some(value);
- Ok(())
+ Ok(match &*slot {
+ Some(value) => value,
+ None => unsafe { hint::unreachable_unchecked() },
+ })
}
/// Gets the contents of the cell, initializing it with `f`
@@ -520,6 +602,18 @@ pub mod unsync {
/// assert_eq!(cell.take(), Some("hello".to_string()));
/// assert_eq!(cell.get(), None);
/// ```
+ ///
+ /// This method is allowed to violate the invariant of writing to a `OnceCell`
+ /// at most once because it requires `&mut` access to `self`. As with all
+ /// interior mutability, `&mut` access permits arbitrary modification:
+ ///
+ /// ```
+ /// use once_cell::unsync::OnceCell;
+ ///
+ /// let mut cell: OnceCell<u32> = OnceCell::new();
+ /// cell.set(92).unwrap();
+ /// cell = OnceCell::new();
+ /// ```
pub fn take(&mut self) -> Option<T> {
mem::replace(self, Self::default()).into_inner()
}
@@ -657,6 +751,7 @@ pub mod unsync {
}
}
+/// Thread-safe, blocking version of `OnceCell`.
#[cfg(feature = "std")]
pub mod sync {
use std::{
@@ -666,7 +761,7 @@ pub mod sync {
panic::RefUnwindSafe,
};
- use crate::imp::OnceCell as Imp;
+ use crate::{imp::OnceCell as Imp, take_unchecked};
/// A thread-safe cell which can be written to only once.
///
@@ -764,6 +859,18 @@ pub mod sync {
/// Gets the mutable reference to the underlying value.
///
/// Returns `None` if the cell is empty.
+ ///
+ /// This method is allowed to violate the invariant of writing to a `OnceCell`
+ /// at most once because it requires `&mut` access to `self`. As with all
+ /// interior mutability, `&mut` access permits arbitrary modification:
+ ///
+ /// ```
+ /// use once_cell::sync::OnceCell;
+ ///
+ /// let mut cell: OnceCell<u32> = OnceCell::new();
+ /// cell.set(92).unwrap();
+ /// cell = OnceCell::new();
+ /// ```
pub fn get_mut(&mut self) -> Option<&mut T> {
self.0.get_mut()
}
@@ -803,11 +910,33 @@ pub mod sync {
/// }
/// ```
pub fn set(&self, value: T) -> Result<(), T> {
+ match self.try_insert(value) {
+ Ok(_) => Ok(()),
+ Err((_, value)) => Err(value),
+ }
+ }
+
+ /// Like [`set`](Self::set), but also returns a reference to the final cell value.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use once_cell::unsync::OnceCell;
+ ///
+ /// let cell = OnceCell::new();
+ /// assert!(cell.get().is_none());
+ ///
+ /// assert_eq!(cell.try_insert(92), Ok(&92));
+ /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
+ ///
+ /// assert!(cell.get().is_some());
+ /// ```
+ pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
let mut value = Some(value);
- self.get_or_init(|| value.take().unwrap());
+ let res = self.get_or_init(|| unsafe { take_unchecked(&mut value) });
match value {
- None => Ok(()),
- Some(value) => Err(value),
+ None => Ok(res),
+ Some(value) => Err((res, value)),
}
}
@@ -906,6 +1035,18 @@ pub mod sync {
/// assert_eq!(cell.take(), Some("hello".to_string()));
/// assert_eq!(cell.get(), None);
/// ```
+ ///
+ /// This method is allowed to violate the invariant of writing to a `OnceCell`
+ /// at most once because it requires `&mut` access to `self`. As with all
+ /// interior mutability, `&mut` access permits arbitrary modification:
+ ///
+ /// ```
+ /// use once_cell::sync::OnceCell;
+ ///
+ /// let mut cell: OnceCell<u32> = OnceCell::new();
+ /// cell.set(92).unwrap();
+ /// cell = OnceCell::new();
+ /// ```
pub fn take(&mut self) -> Option<T> {
mem::replace(self, Self::default()).into_inner()
}
@@ -974,11 +1115,10 @@ pub mod sync {
}
}
- // We never create a `&F` from a `&Lazy<T, F>` so it is fine
- // to not impl `Sync` for `F`
- // we do create a `&mut Option<F>` in `force`, but this is
- // properly synchronized, so it only happens once
- // so it also does not contribute to this impl.
+ // We never create a `&F` from a `&Lazy<T, F>` so it is fine to not impl
+ // `Sync` for `F`. we do create a `&mut Option<F>` in `force`, but this is
+ // properly synchronized, so it only happens once so it also does not
+ // contribute to this impl.
unsafe impl<T, F: Send> Sync for Lazy<T, F> where OnceCell<T>: Sync {}
// auto-derived `Send` impl is OK.
diff --git a/src/race.rs b/src/race.rs
index e0dc8fc..3576420 100644
--- a/src/race.rs
+++ b/src/race.rs
@@ -1,4 +1,4 @@
-//! "First one wins" flavor of `OnceCell`.
+//! Thread-safe, non-blocking, "first one wins" flavor of `OnceCell`.
//!
//! If two threads race to initialize a type from the `race` module, they
//! don't block, execute initialization function together, but only one of
@@ -6,10 +6,13 @@
//!
//! This module does not require `std` feature.
-use core::{
- num::NonZeroUsize,
- sync::atomic::{AtomicUsize, Ordering},
-};
+#[cfg(feature = "atomic-polyfill")]
+use atomic_polyfill as atomic;
+#[cfg(not(feature = "atomic-polyfill"))]
+use core::sync::atomic;
+
+use atomic::{AtomicUsize, Ordering};
+use core::num::NonZeroUsize;
/// A thread-safe cell which can be written to only once.
#[derive(Default, Debug)]
@@ -160,21 +163,23 @@ pub use self::once_box::OnceBox;
#[cfg(feature = "alloc")]
mod once_box {
- use core::{
- marker::PhantomData,
- ptr,
- sync::atomic::{AtomicPtr, Ordering},
- };
+ use super::atomic::{AtomicPtr, Ordering};
+ use core::{marker::PhantomData, ptr};
use alloc::boxed::Box;
/// A thread-safe cell which can be written to only once.
- #[derive(Debug)]
pub struct OnceBox<T> {
inner: AtomicPtr<T>,
ghost: PhantomData<Option<Box<T>>>,
}
+ impl<T> core::fmt::Debug for OnceBox<T> {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ write!(f, "OnceBox({:?})", self.inner.load(Ordering::Relaxed))
+ }
+ }
+
impl<T> Default for OnceBox<T> {
fn default() -> Self {
Self::new()
diff --git a/tests/it.rs b/tests/it.rs
index 81faaff..c769487 100644
--- a/tests/it.rs
+++ b/tests/it.rs
@@ -166,6 +166,7 @@ mod unsync {
#[test]
#[cfg(feature = "std")]
+ #[cfg(not(target_os = "android"))]
fn lazy_poisoning() {
let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
for _ in 0..2 {
@@ -288,6 +289,7 @@ mod sync {
}
#[test]
+ #[cfg(not(target_os = "android"))]
fn get_or_try_init() {
let cell: OnceCell<String> = OnceCell::new();
assert!(cell.get().is_none());
@@ -348,6 +350,7 @@ mod sync {
#[test]
#[cfg_attr(miri, ignore)] // miri doesn't support processes
+ #[ignore = "Android: ignore for now. Need to compile these binaries separately."]
fn reentrant_init() {
let examples_dir = {
let mut exe = std::env::current_exe().unwrap();
@@ -486,6 +489,7 @@ mod sync {
}
#[test]
+ #[cfg(not(target_os = "android"))]
fn lazy_poisoning() {
let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
for _ in 0..2 {