diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-10 07:01:50 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-10 07:01:50 +0000 |
commit | 0b9f6ace3eccba432d41cca9a308184d4d240c27 (patch) | |
tree | 95353df6eca9bf63f57a86070e6fad69c6061276 | |
parent | 1b2ea50fdcdeca62f23ac071631fdb6ac16c6953 (diff) | |
parent | d529398d91731a676c57a2787081a9d0485957f2 (diff) | |
download | once_cell-android13-mainline-permission-release.tar.gz |
Snap for 8564071 from d529398d91731a676c57a2787081a9d0485957f2 to mainline-permission-releaseaml_per_331913010aml_per_331812030aml_per_331710050aml_per_331611010aml_per_331512020aml_per_331411000aml_per_331313010aml_per_331115020aml_per_331019040aml_per_330912010aml_per_330811030android13-mainline-permission-release
Change-Id: I62e39be79283752030ac2a0997ce5b90758f3b50
-rw-r--r-- | .cargo_vcs_info.json | 7 | ||||
-rw-r--r-- | Android.bp | 56 | ||||
-rw-r--r-- | CHANGELOG.md | 8 | ||||
-rw-r--r-- | Cargo.toml | 17 | ||||
-rw-r--r-- | Cargo.toml.orig | 11 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | TEST_MAPPING | 85 | ||||
-rw-r--r-- | cargo2android.json | 4 | ||||
-rw-r--r-- | patches/imp_std.rs.patch | 20 | ||||
-rw-r--r-- | patches/it.rs.patch | 36 | ||||
-rw-r--r-- | src/imp_std.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 184 | ||||
-rw-r--r-- | src/race.rs | 27 | ||||
-rw-r--r-- | tests/it.rs | 4 |
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 @@ -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. @@ -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" @@ -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(); @@ -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 { |