aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2021-06-22 10:09:30 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-06-22 10:09:30 +0000
commitf61a55ceceaee70ab50328313126d1e3d1b62b55 (patch)
treec662582a391e8ddc05a36058307c9d9351ae136a
parent0a9d0cd11bb8f8dd61c4a5ec589da5ab9e2a875f (diff)
parent2ce91674eba239b60b91d77c02fe074e40ed8eda (diff)
downloadcrossbeam-utils-f61a55ceceaee70ab50328313126d1e3d1b62b55.tar.gz
Upgrade rust/crates/crossbeam-utils to 0.8.5 am: 2ce91674eb
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/crossbeam-utils/+/1742398 Change-Id: I155201329f19e8637968f22131bd877fb9ff4353
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp27
-rw-r--r--CHANGELOG.md5
-rw-r--r--Cargo.toml4
-rw-r--r--Cargo.toml.orig16
-rw-r--r--METADATA8
-rw-r--r--TEST_MAPPING6
-rw-r--r--build.rs35
-rw-r--r--no_atomic.rs59
-rw-r--r--src/atomic/atomic_cell.rs79
-rw-r--r--src/atomic/consume.rs24
-rw-r--r--src/atomic/mod.rs8
-rw-r--r--src/lib.rs27
-rw-r--r--tests/atomic_cell.rs54
-rw-r--r--tests/cache_padded.rs1
-rw-r--r--tests/sharded_lock.rs2
16 files changed, 231 insertions, 126 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 78aaf0a..1f53d5d 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "d4f6785c9be365832eecfc04222f95a1c2dd314a"
+ "sha1": "6d4cdd4daf9a897deef6cde9569f2fbf12c29bc5"
}
}
diff --git a/Android.bp b/Android.bp
index 8fdf39b..3957788 100644
--- a/Android.bp
+++ b/Android.bp
@@ -51,12 +51,6 @@ rust_defaults {
"lazy_static",
"std",
],
- cfgs: [
- "has_atomic_u16",
- "has_atomic_u32",
- "has_atomic_u64",
- "has_atomic_u8",
- ],
rustlibs: [
"libcfg_if",
"liblazy_static",
@@ -88,12 +82,6 @@ rust_defaults {
"lazy_static",
"std",
],
- cfgs: [
- "has_atomic_u16",
- "has_atomic_u32",
- "has_atomic_u64",
- "has_atomic_u8",
- ],
rustlibs: [
"libcfg_if",
"libcrossbeam_utils",
@@ -203,12 +191,6 @@ rust_library {
"lazy_static",
"std",
],
- cfgs: [
- "has_atomic_u16",
- "has_atomic_u32",
- "has_atomic_u64",
- "has_atomic_u8",
- ],
rustlibs: [
"libcfg_if",
"liblazy_static",
@@ -216,12 +198,11 @@ rust_library {
}
// dependent_library ["feature_list"]
-// autocfg-1.0.1
// cfg-if-1.0.0
// getrandom-0.2.3 "std"
// lazy_static-1.4.0
-// libc-0.2.94
+// libc-0.2.97
// ppv-lite86-0.2.10 "simd,std"
-// rand-0.8.3 "alloc,default,getrandom,libc,rand_chacha,rand_hc,std,std_rng"
-// rand_chacha-0.3.0 "std"
-// rand_core-0.6.2 "alloc,getrandom,std"
+// rand-0.8.4 "alloc,default,getrandom,libc,rand_chacha,rand_hc,std,std_rng"
+// rand_chacha-0.3.1 "std"
+// rand_core-0.6.3 "alloc,getrandom,std"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1618732..8c485ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# Version 0.8.5
+
+- Add `AtomicCell::fetch_update` (#704)
+- Support targets that do not have atomic CAS on stable Rust (#698)
+
# Version 0.8.4
- Bump `loom` dependency to version 0.5. (#686)
diff --git a/Cargo.toml b/Cargo.toml
index 65f9815..0b32b46 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "crossbeam-utils"
-version = "0.8.4"
+version = "0.8.5"
authors = ["The Crossbeam Project Developers"]
description = "Utilities for concurrent programming"
homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
@@ -30,8 +30,6 @@ version = "1.4.0"
optional = true
[dev-dependencies.rand]
version = "0.8"
-[build-dependencies.autocfg]
-version = "1.0.0"
[features]
default = ["std"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 4962b71..16488cb 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -4,7 +4,7 @@ name = "crossbeam-utils"
# - Update CHANGELOG.md
# - Update README.md
# - Create "crossbeam-utils-X.Y.Z" git tag
-version = "0.8.4"
+version = "0.8.5"
authors = ["The Crossbeam Project Developers"]
edition = "2018"
license = "MIT OR Apache-2.0"
@@ -22,10 +22,13 @@ default = ["std"]
# This is enabled by default.
std = ["lazy_static"]
+# These features are no longer used.
+# TODO: remove in the next major version.
# Enable to use of unstable functionality.
# This is disabled by default and requires recent nightly compiler.
-# Note that this is outside of the normal semver guarantees and minor versions
-# of crossbeam may make breaking changes to them at any time.
+#
+# NOTE: This feature is outside of the normal semver guarantees and minor or
+# patch versions of crossbeam may make breaking changes to them at any time.
nightly = []
[dependencies]
@@ -34,13 +37,10 @@ lazy_static = { version = "1.4.0", optional = true }
# Enable the use of loom for concurrency testing.
#
-# This configuration option is outside of the normal semver guarantees: minor
-# versions of crossbeam may make breaking changes to it at any time.
+# NOTE: This feature is outside of the normal semver guarantees and minor or
+# patch versions of crossbeam may make breaking changes to them at any time.
[target.'cfg(crossbeam_loom)'.dependencies]
loom = { version = "0.5", optional = true }
-[build-dependencies]
-autocfg = "1.0.0"
-
[dev-dependencies]
rand = "0.8"
diff --git a/METADATA b/METADATA
index af54cb2..e332569 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.4.crate"
+ value: "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.5.crate"
}
- version: "0.8.4"
+ version: "0.8.5"
license_type: NOTICE
last_upgrade_date {
year: 2021
- month: 5
- day: 20
+ month: 6
+ day: 21
}
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a68b776..eea3de0 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -27,6 +27,12 @@
},
{
"name": "crossbeam-utils_device_test_tests_wait_group"
+ },
+ {
+ "name": "unicode-xid_device_test_src_lib"
+ },
+ {
+ "name": "unicode-xid_device_test_tests_exhaustive_tests"
}
]
}
diff --git a/build.rs b/build.rs
index 3e51021..9c924ad 100644
--- a/build.rs
+++ b/build.rs
@@ -1,23 +1,40 @@
-use autocfg::AutoCfg;
+#![warn(rust_2018_idioms)]
+
+use std::env;
+
+include!("no_atomic.rs");
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
- let cfg = match AutoCfg::new() {
- Ok(cfg) => cfg,
+ let target = match env::var("TARGET") {
+ Ok(target) => target,
Err(e) => {
println!(
- "cargo:warning=crossbeam-utils: unable to determine rustc version: {}",
+ "cargo:warning={}: unable to get TARGET environment variable: {}",
+ env!("CARGO_PKG_NAME"),
e
);
return;
}
};
- cfg.emit_type_cfg("core::sync::atomic::AtomicU8", "has_atomic_u8");
- cfg.emit_type_cfg("core::sync::atomic::AtomicU16", "has_atomic_u16");
- cfg.emit_type_cfg("core::sync::atomic::AtomicU32", "has_atomic_u32");
- cfg.emit_type_cfg("core::sync::atomic::AtomicU64", "has_atomic_u64");
- cfg.emit_type_cfg("core::sync::atomic::AtomicU128", "has_atomic_u128");
+ // Note that this is `no_*`, not `has_*`. This allows treating
+ // `cfg(target_has_atomic = "ptr")` as true when the build script doesn't
+ // run. This is needed for compatibility with non-cargo build systems that
+ // don't run the build script.
+ if NO_ATOMIC_CAS.contains(&&*target) {
+ println!("cargo:rustc-cfg=crossbeam_no_atomic_cas");
+ }
+ if NO_ATOMIC.contains(&&*target) {
+ println!("cargo:rustc-cfg=crossbeam_no_atomic");
+ println!("cargo:rustc-cfg=crossbeam_no_atomic_64");
+ } else if NO_ATOMIC_64.contains(&&*target) {
+ println!("cargo:rustc-cfg=crossbeam_no_atomic_64");
+ } else {
+ // Otherwise, assuming `"max-atomic-width" == 64`.
+ }
+
+ println!("cargo:rerun-if-changed=no_atomic.rs");
}
diff --git a/no_atomic.rs b/no_atomic.rs
new file mode 100644
index 0000000..522b3b8
--- /dev/null
+++ b/no_atomic.rs
@@ -0,0 +1,59 @@
+// This file is @generated by no_atomic.sh.
+// It is not intended for manual editing.
+
+const NO_ATOMIC_CAS: &[&str] = &[
+ "avr-unknown-gnu-atmega328",
+ "msp430-none-elf",
+ "riscv32i-unknown-none-elf",
+ "riscv32imc-unknown-none-elf",
+ "thumbv4t-none-eabi",
+ "thumbv6m-none-eabi",
+];
+#[allow(dead_code)]
+const NO_ATOMIC_64: &[&str] = &[
+ "arm-linux-androideabi",
+ "armebv7r-none-eabi",
+ "armebv7r-none-eabihf",
+ "armv4t-unknown-linux-gnueabi",
+ "armv5te-unknown-linux-gnueabi",
+ "armv5te-unknown-linux-musleabi",
+ "armv5te-unknown-linux-uclibceabi",
+ "armv7r-none-eabi",
+ "armv7r-none-eabihf",
+ "hexagon-unknown-linux-musl",
+ "mips-unknown-linux-gnu",
+ "mips-unknown-linux-musl",
+ "mips-unknown-linux-uclibc",
+ "mipsel-unknown-linux-gnu",
+ "mipsel-unknown-linux-musl",
+ "mipsel-unknown-linux-uclibc",
+ "mipsel-unknown-none",
+ "mipsisa32r6-unknown-linux-gnu",
+ "mipsisa32r6el-unknown-linux-gnu",
+ "powerpc-unknown-linux-gnu",
+ "powerpc-unknown-linux-gnuspe",
+ "powerpc-unknown-linux-musl",
+ "powerpc-unknown-netbsd",
+ "powerpc-unknown-openbsd",
+ "powerpc-wrs-vxworks",
+ "powerpc-wrs-vxworks-spe",
+ "riscv32gc-unknown-linux-gnu",
+ "riscv32gc-unknown-linux-musl",
+ "riscv32imac-unknown-none-elf",
+ "thumbv7em-none-eabi",
+ "thumbv7em-none-eabihf",
+ "thumbv7m-none-eabi",
+ "thumbv8m.base-none-eabi",
+ "thumbv8m.main-none-eabi",
+ "thumbv8m.main-none-eabihf",
+ "mipsel-sony-psp",
+ "thumbv4t-none-eabi",
+ "thumbv6m-none-eabi",
+];
+#[allow(dead_code)]
+const NO_ATOMIC: &[&str] = &[
+ "avr-unknown-gnu-atmega328",
+ "msp430-none-elf",
+ "riscv32i-unknown-none-elf",
+ "riscv32imc-unknown-none-elf",
+];
diff --git a/src/atomic/atomic_cell.rs b/src/atomic/atomic_cell.rs
index ad094b2..1a1c464 100644
--- a/src/atomic/atomic_cell.rs
+++ b/src/atomic/atomic_cell.rs
@@ -258,6 +258,40 @@ impl<T: Copy + Eq> AtomicCell<T> {
pub fn compare_exchange(&self, current: T, new: T) -> Result<T, T> {
unsafe { atomic_compare_exchange_weak(self.value.get(), current, new) }
}
+
+ /// Fetches the value, and applies a function to it that returns an optional
+ /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
+ /// `Err(previous_value)`.
+ ///
+ /// Note: This may call the function multiple times if the value has been changed from other threads in
+ /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
+ /// only once to the stored value.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ /// let a = AtomicCell::new(7);
+ /// assert_eq!(a.fetch_update(|_| None), Err(7));
+ /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(7));
+ /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(8));
+ /// assert_eq!(a.load(), 9);
+ /// ```
+ #[inline]
+ pub fn fetch_update<F>(&self, mut f: F) -> Result<T, T>
+ where
+ F: FnMut(T) -> Option<T>,
+ {
+ let mut prev = self.load();
+ while let Some(next) = f(prev) {
+ match self.compare_exchange(prev, next) {
+ x @ Ok(_) => return x,
+ Err(next_prev) => prev = next_prev,
+ }
+ }
+ Err(prev)
+ }
}
macro_rules! impl_arithmetic {
@@ -497,33 +531,25 @@ macro_rules! impl_arithmetic {
};
}
-#[cfg(has_atomic_u8)]
impl_arithmetic!(u8, atomic::AtomicU8, "let a = AtomicCell::new(7u8);");
-#[cfg(all(has_atomic_u8, not(crossbeam_loom)))]
impl_arithmetic!(i8, atomic::AtomicI8, "let a = AtomicCell::new(7i8);");
-#[cfg(has_atomic_u16)]
impl_arithmetic!(u16, atomic::AtomicU16, "let a = AtomicCell::new(7u16);");
-#[cfg(all(has_atomic_u16, not(crossbeam_loom)))]
impl_arithmetic!(i16, atomic::AtomicI16, "let a = AtomicCell::new(7i16);");
-#[cfg(has_atomic_u32)]
impl_arithmetic!(u32, atomic::AtomicU32, "let a = AtomicCell::new(7u32);");
-#[cfg(all(has_atomic_u32, not(crossbeam_loom)))]
impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);");
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
-#[cfg(all(has_atomic_u64, not(crossbeam_loom)))]
+#[cfg(not(crossbeam_no_atomic_64))]
impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
-#[cfg(all(has_atomic_u128, not(crossbeam_loom)))]
-impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
-#[cfg(all(has_atomic_u128, not(crossbeam_loom)))]
-impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);");
+// TODO: AtomicU128 is unstable
+// impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
+// impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);");
impl_arithmetic!(
usize,
atomic::AtomicUsize,
"let a = AtomicCell::new(7usize);"
);
-#[cfg(not(crossbeam_loom))]
impl_arithmetic!(
isize,
atomic::AtomicIsize,
@@ -809,16 +835,13 @@ macro_rules! atomic {
atomic!(@check, $t, AtomicUnit, $a, $atomic_op);
atomic!(@check, $t, atomic::AtomicUsize, $a, $atomic_op);
- #[cfg(has_atomic_u8)]
atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
- #[cfg(has_atomic_u16)]
atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
- #[cfg(has_atomic_u32)]
atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op);
- #[cfg(has_atomic_u64)]
+ #[cfg(not(crossbeam_no_atomic_64))]
atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op);
- #[cfg(has_atomic_u128)]
- atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
+ // TODO: AtomicU128 is unstable
+ // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
#[cfg(crossbeam_loom)]
unimplemented!("loom does not support non-atomic atomic ops");
@@ -831,17 +854,15 @@ macro_rules! atomic {
/// Returns `true` if operations on `AtomicCell<T>` are lock-free.
const fn atomic_is_lock_free<T>() -> bool {
// HACK(taiki-e): This is equivalent to `atomic! { T, _a, true, false }`, but can be used in const fn even in Rust 1.36.
- let is_lock_free = can_transmute::<T, AtomicUnit>() | can_transmute::<T, atomic::AtomicUsize>();
- #[cfg(has_atomic_u8)]
- let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU8>();
- #[cfg(has_atomic_u16)]
- let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU16>();
- #[cfg(has_atomic_u32)]
- let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU32>();
- #[cfg(has_atomic_u64)]
+ let is_lock_free = can_transmute::<T, AtomicUnit>()
+ | can_transmute::<T, atomic::AtomicUsize>()
+ | can_transmute::<T, atomic::AtomicU8>()
+ | can_transmute::<T, atomic::AtomicU16>()
+ | can_transmute::<T, atomic::AtomicU32>();
+ #[cfg(not(crossbeam_no_atomic_64))]
let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU64>();
- #[cfg(has_atomic_u128)]
- let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
+ // TODO: AtomicU128 is unstable
+ // let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
is_lock_free
}
diff --git a/src/atomic/consume.rs b/src/atomic/consume.rs
index 0fbd93e..277b370 100644
--- a/src/atomic/consume.rs
+++ b/src/atomic/consume.rs
@@ -1,5 +1,6 @@
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
use crate::primitive::sync::atomic::compiler_fence;
+#[cfg(not(crossbeam_no_atomic))]
use core::sync::atomic::Ordering;
/// Trait which allows reading from primitive atomic types with "consume" ordering.
@@ -25,6 +26,7 @@ pub trait AtomicConsume {
fn load_consume(&self) -> Self::Val;
}
+#[cfg(not(crossbeam_no_atomic))]
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
macro_rules! impl_consume {
() => {
@@ -37,6 +39,7 @@ macro_rules! impl_consume {
};
}
+#[cfg(not(crossbeam_no_atomic))]
#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
macro_rules! impl_consume {
() => {
@@ -49,12 +52,13 @@ macro_rules! impl_consume {
macro_rules! impl_atomic {
($atomic:ident, $val:ty) => {
- impl AtomicConsume for ::core::sync::atomic::$atomic {
+ #[cfg(not(crossbeam_no_atomic))]
+ impl AtomicConsume for core::sync::atomic::$atomic {
type Val = $val;
impl_consume!();
}
#[cfg(crossbeam_loom)]
- impl AtomicConsume for ::loom::sync::atomic::$atomic {
+ impl AtomicConsume for loom::sync::atomic::$atomic {
type Val = $val;
impl_consume!();
}
@@ -63,32 +67,26 @@ macro_rules! impl_atomic {
impl_atomic!(AtomicBool, bool);
impl_atomic!(AtomicUsize, usize);
-#[cfg(not(crossbeam_loom))]
impl_atomic!(AtomicIsize, isize);
-#[cfg(has_atomic_u8)]
impl_atomic!(AtomicU8, u8);
-#[cfg(has_atomic_u8)]
impl_atomic!(AtomicI8, i8);
-#[cfg(has_atomic_u16)]
impl_atomic!(AtomicU16, u16);
-#[cfg(has_atomic_u16)]
impl_atomic!(AtomicI16, i16);
-#[cfg(has_atomic_u32)]
impl_atomic!(AtomicU32, u32);
-#[cfg(has_atomic_u32)]
impl_atomic!(AtomicI32, i32);
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
impl_atomic!(AtomicU64, u64);
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
impl_atomic!(AtomicI64, i64);
-impl<T> AtomicConsume for ::core::sync::atomic::AtomicPtr<T> {
+#[cfg(not(crossbeam_no_atomic))]
+impl<T> AtomicConsume for core::sync::atomic::AtomicPtr<T> {
type Val = *mut T;
impl_consume!();
}
#[cfg(crossbeam_loom)]
-impl<T> AtomicConsume for ::loom::sync::atomic::AtomicPtr<T> {
+impl<T> AtomicConsume for loom::sync::atomic::AtomicPtr<T> {
type Val = *mut T;
impl_consume!();
}
diff --git a/src/atomic/mod.rs b/src/atomic/mod.rs
index 874eaf2..fc713fc 100644
--- a/src/atomic/mod.rs
+++ b/src/atomic/mod.rs
@@ -3,11 +3,9 @@
//! * [`AtomicCell`], a thread-safe mutable memory location.
//! * [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering.
+#[cfg(not(crossbeam_no_atomic_cas))]
#[cfg(not(crossbeam_loom))]
-use cfg_if::cfg_if;
-
-#[cfg(not(crossbeam_loom))]
-cfg_if! {
+cfg_if::cfg_if! {
// Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap
// around.
//
@@ -25,8 +23,10 @@ cfg_if! {
}
}
+#[cfg(not(crossbeam_no_atomic_cas))]
mod atomic_cell;
mod consume;
+#[cfg(not(crossbeam_no_atomic_cas))]
pub use self::atomic_cell::AtomicCell;
pub use self::consume::AtomicConsume;
diff --git a/src/lib.rs b/src/lib.rs
index 880d37e..191c5a1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,7 +38,6 @@
unreachable_pub
)]
#![cfg_attr(not(feature = "std"), no_std)]
-#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#[cfg(crossbeam_loom)]
#[allow(unused_imports)]
@@ -47,7 +46,8 @@ mod primitive {
pub(crate) mod atomic {
pub(crate) use loom::sync::atomic::spin_loop_hint;
pub(crate) use loom::sync::atomic::{
- AtomicBool, AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
+ AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16,
+ AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
};
// FIXME: loom does not support compiler_fence at the moment.
@@ -70,15 +70,13 @@ mod primitive {
// use [`core::hint::spin_loop`] instead.
#[allow(deprecated)]
pub(crate) use core::sync::atomic::spin_loop_hint;
- pub(crate) use core::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize};
- #[cfg(has_atomic_u16)]
- pub(crate) use core::sync::atomic::{AtomicI16, AtomicU16};
- #[cfg(has_atomic_u32)]
- pub(crate) use core::sync::atomic::{AtomicI32, AtomicU32};
- #[cfg(has_atomic_u64)]
+ #[cfg(not(crossbeam_no_atomic))]
+ pub(crate) use core::sync::atomic::{
+ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
+ AtomicU8, AtomicUsize,
+ };
+ #[cfg(not(crossbeam_no_atomic_64))]
pub(crate) use core::sync::atomic::{AtomicI64, AtomicU64};
- #[cfg(has_atomic_u8)]
- pub(crate) use core::sync::atomic::{AtomicI8, AtomicU8};
}
#[cfg(feature = "std")]
@@ -86,15 +84,6 @@ mod primitive {
}
}
-cfg_if! {
- if #[cfg(feature = "alloc")] {
- extern crate alloc;
- } else if #[cfg(feature = "std")] {
- extern crate std as alloc;
- }
-}
-
-#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
pub mod atomic;
mod cache_padded;
diff --git a/tests/atomic_cell.rs b/tests/atomic_cell.rs
index 3d91d81..28208ee 100644
--- a/tests/atomic_cell.rs
+++ b/tests/atomic_cell.rs
@@ -1,3 +1,4 @@
+use std::mem;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
@@ -8,18 +9,47 @@ fn is_lock_free() {
struct UsizeWrap(usize);
struct U8Wrap(bool);
struct I16Wrap(i16);
-
- assert_eq!(AtomicCell::<usize>::is_lock_free(), true);
- assert_eq!(AtomicCell::<isize>::is_lock_free(), true);
- assert_eq!(AtomicCell::<UsizeWrap>::is_lock_free(), true);
-
- assert_eq!(AtomicCell::<u8>::is_lock_free(), cfg!(has_atomic_u8));
- assert_eq!(AtomicCell::<bool>::is_lock_free(), cfg!(has_atomic_u8));
- assert_eq!(AtomicCell::<U8Wrap>::is_lock_free(), cfg!(has_atomic_u8));
-
- assert_eq!(AtomicCell::<I16Wrap>::is_lock_free(), cfg!(has_atomic_u16));
-
- assert_eq!(AtomicCell::<u128>::is_lock_free(), cfg!(has_atomic_u128));
+ #[repr(align(8))]
+ struct U64Align8(u64);
+
+ assert!(AtomicCell::<usize>::is_lock_free());
+ assert!(AtomicCell::<isize>::is_lock_free());
+ assert!(AtomicCell::<UsizeWrap>::is_lock_free());
+
+ assert!(AtomicCell::<()>::is_lock_free());
+
+ assert!(AtomicCell::<u8>::is_lock_free());
+ assert!(AtomicCell::<i8>::is_lock_free());
+ assert!(AtomicCell::<bool>::is_lock_free());
+ assert!(AtomicCell::<U8Wrap>::is_lock_free());
+
+ assert!(AtomicCell::<u16>::is_lock_free());
+ assert!(AtomicCell::<i16>::is_lock_free());
+ assert!(AtomicCell::<I16Wrap>::is_lock_free());
+
+ assert!(AtomicCell::<u32>::is_lock_free());
+ assert!(AtomicCell::<i32>::is_lock_free());
+
+ // Sizes of both types must be equal, and the alignment of `u64` must be greater or equal than
+ // that of `AtomicU64`. In i686-unknown-linux-gnu, the alignment of `u64` is `4` and alignment
+ // of `AtomicU64` is `8`, so `AtomicCell<u64>` is not lock-free.
+ assert_eq!(
+ AtomicCell::<u64>::is_lock_free(),
+ cfg!(not(crossbeam_no_atomic_64))
+ && cfg!(any(
+ target_pointer_width = "64",
+ target_pointer_width = "128"
+ ))
+ );
+ assert_eq!(mem::size_of::<U64Align8>(), 8);
+ assert_eq!(mem::align_of::<U64Align8>(), 8);
+ assert_eq!(
+ AtomicCell::<U64Align8>::is_lock_free(),
+ cfg!(not(crossbeam_no_atomic_64))
+ );
+
+ // AtomicU128 is unstable
+ assert!(!AtomicCell::<u128>::is_lock_free());
}
#[test]
diff --git a/tests/cache_padded.rs b/tests/cache_padded.rs
index c9e7687..86e9a77 100644
--- a/tests/cache_padded.rs
+++ b/tests/cache_padded.rs
@@ -85,6 +85,7 @@ fn drops() {
assert_eq!(count.get(), 2);
}
+#[allow(clippy::clone_on_copy)] // This is intentional.
#[test]
fn clone() {
let a = CachePadded::new(17);
diff --git a/tests/sharded_lock.rs b/tests/sharded_lock.rs
index b4b8565..d999008 100644
--- a/tests/sharded_lock.rs
+++ b/tests/sharded_lock.rs
@@ -148,7 +148,7 @@ fn arc() {
fn arc_access_in_unwind() {
let arc = Arc::new(ShardedLock::new(1));
let arc2 = arc.clone();
- let _ = thread::spawn(move || -> () {
+ let _ = thread::spawn(move || {
struct Unwinder {
i: Arc<ShardedLock<isize>>,
}