aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid LeGare <legare@google.com>2022-03-03 03:14:23 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-03-03 03:14:23 +0000
commit19b01ce760bb8a81c73d5ffabd3af621ee8dcffe (patch)
tree9920d6c25aa95c5ccff5cf61965f1a8d34973523
parent58186bd635849700d844124bcfdad8c68cb91272 (diff)
parenta26422b7402aace9f613ccc552ff3af47f9fdef9 (diff)
downloadcrossbeam-utils-android13-qpr3-c-s4-release.tar.gz
Update crossbeam-utils to 0.8.7 am: 66bcc0c86b am: a3bf6f146b am: a26422b740t_frc_odp_330442040t_frc_odp_330442000t_frc_ase_330444010android-13.0.0_r83android-13.0.0_r82android-13.0.0_r81android-13.0.0_r80android-13.0.0_r79android-13.0.0_r78android-13.0.0_r77android-13.0.0_r76android-13.0.0_r75android-13.0.0_r74android-13.0.0_r73android-13.0.0_r72android-13.0.0_r71android-13.0.0_r70android-13.0.0_r69android-13.0.0_r68android-13.0.0_r67android-13.0.0_r66android-13.0.0_r65android-13.0.0_r64android-13.0.0_r63android-13.0.0_r62android-13.0.0_r61android-13.0.0_r60android-13.0.0_r59android-13.0.0_r58android-13.0.0_r57android-13.0.0_r56android-13.0.0_r55android-13.0.0_r54android-13.0.0_r53android-13.0.0_r52android-13.0.0_r51android-13.0.0_r50android-13.0.0_r49android-13.0.0_r48android-13.0.0_r47android-13.0.0_r46android-13.0.0_r45android-13.0.0_r44android-13.0.0_r43android-13.0.0_r42android-13.0.0_r41android-13.0.0_r40android-13.0.0_r39android-13.0.0_r38android-13.0.0_r37android-13.0.0_r36android-13.0.0_r35android-13.0.0_r34android-13.0.0_r33android-13.0.0_r32android-13.0.0_r30android-13.0.0_r29android-13.0.0_r28android-13.0.0_r27android-13.0.0_r24android-13.0.0_r23android-13.0.0_r22android-13.0.0_r21android-13.0.0_r20android-13.0.0_r19android-13.0.0_r18android-13.0.0_r17android-13.0.0_r16aml_go_odp_330912000aml_go_ads_330915100aml_go_ads_330915000aml_go_ads_330913000android13-qpr3-s9-releaseandroid13-qpr3-s8-releaseandroid13-qpr3-s7-releaseandroid13-qpr3-s6-releaseandroid13-qpr3-s5-releaseandroid13-qpr3-s4-releaseandroid13-qpr3-s3-releaseandroid13-qpr3-s2-releaseandroid13-qpr3-s14-releaseandroid13-qpr3-s13-releaseandroid13-qpr3-s12-releaseandroid13-qpr3-s11-releaseandroid13-qpr3-s10-releaseandroid13-qpr3-s1-releaseandroid13-qpr3-releaseandroid13-qpr3-c-s8-releaseandroid13-qpr3-c-s7-releaseandroid13-qpr3-c-s6-releaseandroid13-qpr3-c-s5-releaseandroid13-qpr3-c-s4-releaseandroid13-qpr3-c-s3-releaseandroid13-qpr3-c-s2-releaseandroid13-qpr3-c-s12-releaseandroid13-qpr3-c-s11-releaseandroid13-qpr3-c-s10-releaseandroid13-qpr3-c-s1-releaseandroid13-qpr2-s9-releaseandroid13-qpr2-s8-releaseandroid13-qpr2-s7-releaseandroid13-qpr2-s6-releaseandroid13-qpr2-s5-releaseandroid13-qpr2-s3-releaseandroid13-qpr2-s2-releaseandroid13-qpr2-s12-releaseandroid13-qpr2-s11-releaseandroid13-qpr2-s10-releaseandroid13-qpr2-s1-releaseandroid13-qpr2-releaseandroid13-qpr2-b-s1-releaseandroid13-qpr1-s8-releaseandroid13-qpr1-s7-releaseandroid13-qpr1-s6-releaseandroid13-qpr1-s5-releaseandroid13-qpr1-s4-releaseandroid13-qpr1-s3-releaseandroid13-qpr1-s2-releaseandroid13-qpr1-s1-releaseandroid13-qpr1-releaseandroid13-mainline-go-adservices-releaseandroid13-frc-odp-releaseandroid13-devandroid13-d4-s2-releaseandroid13-d4-s1-releaseandroid13-d4-releaseandroid13-d3-s1-releaseandroid13-d2-release
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/crossbeam-utils/+/2004791 Change-Id: Ie7392306b8d5888ea000d2f3f38c2ddc9fcd3be9
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp8
-rw-r--r--CHANGELOG.md15
-rw-r--r--Cargo.toml34
-rw-r--r--Cargo.toml.orig6
-rw-r--r--METADATA10
-rw-r--r--build.rs29
-rw-r--r--no_atomic.rs22
-rw-r--r--src/atomic/atomic_cell.rs489
-rw-r--r--src/sync/parker.rs2
-rw-r--r--src/thread.rs2
-rw-r--r--tests/atomic_cell.rs66
-rw-r--r--tests/sharded_lock.rs3
13 files changed, 524 insertions, 169 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 1f53d5d..0d40a83 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "6d4cdd4daf9a897deef6cde9569f2fbf12c29bc5"
- }
-}
+ "sha1": "2988f873f87d2263a7fd2b9465fb9c28f43a6490"
+ },
+ "path_in_vcs": "crossbeam-utils"
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 60ccb4e..5f17007 100644
--- a/Android.bp
+++ b/Android.bp
@@ -44,7 +44,7 @@ rust_test {
host_supported: true,
crate_name: "crossbeam_utils",
cargo_env_compat: true,
- cargo_pkg_version: "0.8.5",
+ cargo_pkg_version: "0.8.7",
srcs: ["src/lib.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
@@ -62,13 +62,14 @@ rust_test {
"liblazy_static",
"librand",
],
+ proc_macros: ["librustversion"],
}
rust_defaults {
name: "crossbeam-utils_test_defaults",
crate_name: "crossbeam_utils",
cargo_env_compat: true,
- cargo_pkg_version: "0.8.5",
+ cargo_pkg_version: "0.8.7",
test_suites: ["general-tests"],
auto_gen_config: true,
edition: "2018",
@@ -83,6 +84,7 @@ rust_defaults {
"liblazy_static",
"librand",
],
+ proc_macros: ["librustversion"],
}
rust_test {
@@ -150,7 +152,7 @@ rust_library {
host_supported: true,
crate_name: "crossbeam_utils",
cargo_env_compat: true,
- cargo_pkg_version: "0.8.5",
+ cargo_pkg_version: "0.8.7",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c485ef..98088c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,18 @@
+# Version 0.8.7
+
+- Add `AtomicCell<{i*,u*}>::{fetch_max,fetch_min}`. (#785)
+- Add `AtomicCell<{i*,u*,bool}>::fetch_nand`. (#785)
+- Fix unsoundness of `AtomicCell<{i,u}64>` arithmetics on 32-bit targets that support `Atomic{I,U}64` (#781)
+
+# Version 0.8.6
+
+- Re-add `AtomicCell<{i,u}64>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` that were accidentally removed in 0.8.0 on targets that do not support `Atomic{I,U}64`. (#767)
+- Re-add `AtomicCell<{i,u}128>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` that were accidentally removed in 0.8.0. (#767)
+
# Version 0.8.5
-- Add `AtomicCell::fetch_update` (#704)
-- Support targets that do not have atomic CAS on stable Rust (#698)
+- Add `AtomicCell::fetch_update`. (#704)
+- Support targets that do not have atomic CAS on stable Rust. (#698)
# Version 0.8.4
diff --git a/Cargo.toml b/Cargo.toml
index 0b32b46..10d3240 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,38 +3,52 @@
# 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"
+rust-version = "1.36"
name = "crossbeam-utils"
-version = "0.8.5"
-authors = ["The Crossbeam Project Developers"]
+version = "0.8.7"
description = "Utilities for concurrent programming"
homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
-documentation = "https://docs.rs/crossbeam-utils"
-keywords = ["scoped", "thread", "atomic", "cache"]
-categories = ["algorithms", "concurrency", "data-structures", "no-std"]
+keywords = [
+ "scoped",
+ "thread",
+ "atomic",
+ "cache",
+]
+categories = [
+ "algorithms",
+ "concurrency",
+ "data-structures",
+ "no-std",
+]
license = "MIT OR Apache-2.0"
repository = "https://github.com/crossbeam-rs/crossbeam"
+
[dependencies.cfg-if]
version = "1"
[dependencies.lazy_static]
version = "1.4.0"
optional = true
+
[dev-dependencies.rand]
version = "0.8"
+[dev-dependencies.rustversion]
+version = "1"
+
[features]
default = ["std"]
nightly = []
std = ["lazy_static"]
+
[target."cfg(crossbeam_loom)".dependencies.loom]
version = "0.5"
optional = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 16488cb..73508a9 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -4,13 +4,12 @@ name = "crossbeam-utils"
# - Update CHANGELOG.md
# - Update README.md
# - Create "crossbeam-utils-X.Y.Z" git tag
-version = "0.8.5"
-authors = ["The Crossbeam Project Developers"]
+version = "0.8.7"
edition = "2018"
+rust-version = "1.36"
license = "MIT OR Apache-2.0"
repository = "https://github.com/crossbeam-rs/crossbeam"
homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
-documentation = "https://docs.rs/crossbeam-utils"
description = "Utilities for concurrent programming"
keywords = ["scoped", "thread", "atomic", "cache"]
categories = ["algorithms", "concurrency", "data-structures", "no-std"]
@@ -44,3 +43,4 @@ loom = { version = "0.5", optional = true }
[dev-dependencies]
rand = "0.8"
+rustversion = "1"
diff --git a/METADATA b/METADATA
index e332569..2c55b77 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.5.crate"
+ value: "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.7.crate"
}
- version: "0.8.5"
+ version: "0.8.7"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 6
- day: 21
+ year: 2022
+ month: 3
+ day: 1
}
}
diff --git a/build.rs b/build.rs
index 9c924ad..a7557fd 100644
--- a/build.rs
+++ b/build.rs
@@ -1,12 +1,33 @@
+// The rustc-cfg listed below are considered public API, but it is *unstable*
+// and outside of the normal semver guarantees:
+//
+// - `crossbeam_no_atomic_cas`
+// Assume the target does *not* support atomic CAS operations.
+// This is usually detected automatically by the build script, but you may
+// need to enable it manually when building for custom targets or using
+// non-cargo build systems that don't run the build script.
+//
+// - `crossbeam_no_atomic`
+// Assume the target does *not* support any atomic operations.
+// This is usually detected automatically by the build script, but you may
+// need to enable it manually when building for custom targets or using
+// non-cargo build systems that don't run the build script.
+//
+// - `crossbeam_no_atomic_64`
+// Assume the target does *not* support AtomicU64/AtomicI64.
+// This is usually detected automatically by the build script, but you may
+// need to enable it manually when building for custom targets or using
+// non-cargo build systems that don't run the build script.
+//
+// With the exceptions mentioned above, the rustc-cfg emitted by the build
+// script are *not* public API.
+
#![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 target = match env::var("TARGET") {
Ok(target) => target,
@@ -33,7 +54,7 @@ fn main() {
} else if NO_ATOMIC_64.contains(&&*target) {
println!("cargo:rustc-cfg=crossbeam_no_atomic_64");
} else {
- // Otherwise, assuming `"max-atomic-width" == 64`.
+ // Otherwise, assuming `"max-atomic-width" == 64` or `"max-atomic-width" == 128`.
}
println!("cargo:rerun-if-changed=no_atomic.rs");
diff --git a/no_atomic.rs b/no_atomic.rs
index 522b3b8..90ac60a 100644
--- a/no_atomic.rs
+++ b/no_atomic.rs
@@ -3,13 +3,16 @@
const NO_ATOMIC_CAS: &[&str] = &[
"avr-unknown-gnu-atmega328",
+ "bpfeb-unknown-none",
+ "bpfel-unknown-none",
"msp430-none-elf",
"riscv32i-unknown-none-elf",
"riscv32imc-unknown-none-elf",
"thumbv4t-none-eabi",
"thumbv6m-none-eabi",
];
-#[allow(dead_code)]
+
+#[allow(dead_code)] // Only crossbeam-utils uses this.
const NO_ATOMIC_64: &[&str] = &[
"arm-linux-androideabi",
"armebv7r-none-eabi",
@@ -18,18 +21,24 @@ const NO_ATOMIC_64: &[&str] = &[
"armv5te-unknown-linux-gnueabi",
"armv5te-unknown-linux-musleabi",
"armv5te-unknown-linux-uclibceabi",
+ "armv6k-nintendo-3ds",
"armv7r-none-eabi",
"armv7r-none-eabihf",
+ "avr-unknown-gnu-atmega328",
"hexagon-unknown-linux-musl",
+ "m68k-unknown-linux-gnu",
"mips-unknown-linux-gnu",
"mips-unknown-linux-musl",
"mips-unknown-linux-uclibc",
+ "mipsel-sony-psp",
"mipsel-unknown-linux-gnu",
"mipsel-unknown-linux-musl",
"mipsel-unknown-linux-uclibc",
"mipsel-unknown-none",
"mipsisa32r6-unknown-linux-gnu",
"mipsisa32r6el-unknown-linux-gnu",
+ "msp430-none-elf",
+ "powerpc-unknown-freebsd",
"powerpc-unknown-linux-gnu",
"powerpc-unknown-linux-gnuspe",
"powerpc-unknown-linux-musl",
@@ -39,18 +48,21 @@ const NO_ATOMIC_64: &[&str] = &[
"powerpc-wrs-vxworks-spe",
"riscv32gc-unknown-linux-gnu",
"riscv32gc-unknown-linux-musl",
+ "riscv32i-unknown-none-elf",
"riscv32imac-unknown-none-elf",
+ "riscv32imc-esp-espidf",
+ "riscv32imc-unknown-none-elf",
+ "thumbv4t-none-eabi",
+ "thumbv6m-none-eabi",
"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)]
+
+#[allow(dead_code)] // Only crossbeam-utils uses this.
const NO_ATOMIC: &[&str] = &[
"avr-unknown-gnu-atmega328",
"msp430-none-elf",
diff --git a/src/atomic/atomic_cell.rs b/src/atomic/atomic_cell.rs
index 1a1c464..8a49464 100644
--- a/src/atomic/atomic_cell.rs
+++ b/src/atomic/atomic_cell.rs
@@ -1,9 +1,9 @@
// Necessary for implementing atomic methods for `AtomicUnit`
#![allow(clippy::unit_arg)]
-#![allow(clippy::let_unit_value)]
use crate::primitive::sync::atomic::{self, AtomicBool};
use core::cell::UnsafeCell;
+use core::cmp;
use core::fmt;
use core::mem;
use core::sync::atomic::Ordering;
@@ -295,7 +295,7 @@ impl<T: Copy + Eq> AtomicCell<T> {
}
macro_rules! impl_arithmetic {
- ($t:ty, $example:tt) => {
+ ($t:ty, fallback, $example:tt) => {
impl AtomicCell<$t> {
/// Increments the current value by `val` and returns the previous value.
///
@@ -313,10 +313,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_add(&self, val: $t) -> $t {
- if can_transmute::<$t, atomic::AtomicUsize>() {
- let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
- a.fetch_add(val as usize, Ordering::AcqRel) as $t
- } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -341,10 +344,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_sub(&self, val: $t) -> $t {
- if can_transmute::<$t, atomic::AtomicUsize>() {
- let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
- a.fetch_sub(val as usize, Ordering::AcqRel) as $t
- } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -367,10 +373,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_and(&self, val: $t) -> $t {
- if can_transmute::<$t, atomic::AtomicUsize>() {
- let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
- a.fetch_and(val as usize, Ordering::AcqRel) as $t
- } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -379,6 +388,35 @@ macro_rules! impl_arithmetic {
}
}
+ /// Applies bitwise "nand" to the current value and returns the previous value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ #[doc = $example]
+ ///
+ /// assert_eq!(a.fetch_nand(3), 7);
+ /// assert_eq!(a.load(), !(7 & 3));
+ /// ```
+ #[inline]
+ pub fn fetch_nand(&self, val: $t) -> $t {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value = !(old & val);
+ old
+ }
+ }
+
/// Applies bitwise "or" to the current value and returns the previous value.
///
/// # Examples
@@ -393,10 +431,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_or(&self, val: $t) -> $t {
- if can_transmute::<$t, atomic::AtomicUsize>() {
- let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
- a.fetch_or(val as usize, Ordering::AcqRel) as $t
- } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -419,10 +460,13 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_xor(&self, val: $t) -> $t {
- if can_transmute::<$t, atomic::AtomicUsize>() {
- let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
- a.fetch_xor(val as usize, Ordering::AcqRel) as $t
- } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -430,6 +474,66 @@ macro_rules! impl_arithmetic {
old
}
}
+
+ /// Compares and sets the maximum of the current value and `val`,
+ /// and returns the previous value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ #[doc = $example]
+ ///
+ /// assert_eq!(a.fetch_max(2), 7);
+ /// assert_eq!(a.load(), 7);
+ /// ```
+ #[inline]
+ pub fn fetch_max(&self, val: $t) -> $t {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value = cmp::max(old, val);
+ old
+ }
+ }
+
+ /// Compares and sets the minimum of the current value and `val`,
+ /// and returns the previous value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ #[doc = $example]
+ ///
+ /// assert_eq!(a.fetch_min(2), 7);
+ /// assert_eq!(a.load(), 2);
+ /// ```
+ #[inline]
+ pub fn fetch_min(&self, val: $t) -> $t {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value = cmp::min(old, val);
+ old
+ }
+ }
}
};
($t:ty, $atomic:ty, $example:tt) => {
@@ -450,8 +554,24 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_add(&self, val: $t) -> $t {
- let a = unsafe { &*(self.value.get() as *const $atomic) };
- a.fetch_add(val, Ordering::AcqRel)
+ if can_transmute::<$t, $atomic>() {
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_add(val, Ordering::AcqRel)
+ } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value = value.wrapping_add(val);
+ old
+ }
+ }
}
/// Decrements the current value by `val` and returns the previous value.
@@ -470,8 +590,24 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_sub(&self, val: $t) -> $t {
- let a = unsafe { &*(self.value.get() as *const $atomic) };
- a.fetch_sub(val, Ordering::AcqRel)
+ if can_transmute::<$t, $atomic>() {
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_sub(val, Ordering::AcqRel)
+ } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value = value.wrapping_sub(val);
+ old
+ }
+ }
}
/// Applies bitwise "and" to the current value and returns the previous value.
@@ -488,8 +624,58 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_and(&self, val: $t) -> $t {
- let a = unsafe { &*(self.value.get() as *const $atomic) };
- a.fetch_and(val, Ordering::AcqRel)
+ if can_transmute::<$t, $atomic>() {
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_and(val, Ordering::AcqRel)
+ } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value &= val;
+ old
+ }
+ }
+ }
+
+ /// Applies bitwise "nand" to the current value and returns the previous value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ #[doc = $example]
+ ///
+ /// assert_eq!(a.fetch_nand(3), 7);
+ /// assert_eq!(a.load(), !(7 & 3));
+ /// ```
+ #[inline]
+ pub fn fetch_nand(&self, val: $t) -> $t {
+ if can_transmute::<$t, $atomic>() {
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_nand(val, Ordering::AcqRel)
+ } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value = !(old & val);
+ old
+ }
+ }
}
/// Applies bitwise "or" to the current value and returns the previous value.
@@ -506,8 +692,24 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_or(&self, val: $t) -> $t {
- let a = unsafe { &*(self.value.get() as *const $atomic) };
- a.fetch_or(val, Ordering::AcqRel)
+ if can_transmute::<$t, $atomic>() {
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_or(val, Ordering::AcqRel)
+ } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value |= val;
+ old
+ }
+ }
}
/// Applies bitwise "xor" to the current value and returns the previous value.
@@ -524,8 +726,94 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_xor(&self, val: $t) -> $t {
- let a = unsafe { &*(self.value.get() as *const $atomic) };
- a.fetch_xor(val, Ordering::AcqRel)
+ if can_transmute::<$t, $atomic>() {
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_xor(val, Ordering::AcqRel)
+ } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value ^= val;
+ old
+ }
+ }
+ }
+
+ /// Compares and sets the maximum of the current value and `val`,
+ /// and returns the previous value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ #[doc = $example]
+ ///
+ /// assert_eq!(a.fetch_max(9), 7);
+ /// assert_eq!(a.load(), 9);
+ /// ```
+ #[inline]
+ pub fn fetch_max(&self, val: $t) -> $t {
+ if can_transmute::<$t, $atomic>() {
+ // TODO: Atomic*::fetch_max requires Rust 1.45.
+ self.fetch_update(|old| Some(cmp::max(old, val))).unwrap()
+ } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value = cmp::max(old, val);
+ old
+ }
+ }
+ }
+
+ /// Compares and sets the minimum of the current value and `val`,
+ /// and returns the previous value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ #[doc = $example]
+ ///
+ /// assert_eq!(a.fetch_min(2), 7);
+ /// assert_eq!(a.load(), 2);
+ /// ```
+ #[inline]
+ pub fn fetch_min(&self, val: $t) -> $t {
+ if can_transmute::<$t, $atomic>() {
+ // TODO: Atomic*::fetch_min requires Rust 1.45.
+ self.fetch_update(|old| Some(cmp::min(old, val))).unwrap()
+ } else {
+ #[cfg(crossbeam_loom)]
+ {
+ let _ = val;
+ unimplemented!("loom does not support non-atomic atomic ops");
+ }
+ #[cfg(not(crossbeam_loom))]
+ {
+ let _guard = lock(self.value.get() as usize).write();
+ let value = unsafe { &mut *(self.value.get()) };
+ let old = *value;
+ *value = cmp::min(old, val);
+ old
+ }
+ }
}
}
};
@@ -541,9 +829,15 @@ impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);");
impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
#[cfg(not(crossbeam_no_atomic_64))]
impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
+#[cfg(crossbeam_no_atomic_64)]
+impl_arithmetic!(u64, fallback, "let a = AtomicCell::new(7u64);");
+#[cfg(crossbeam_no_atomic_64)]
+impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);");
// 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!(u128, fallback, "let a = AtomicCell::new(7u128);");
+impl_arithmetic!(i128, fallback, "let a = AtomicCell::new(7i128);");
impl_arithmetic!(
usize,
@@ -578,6 +872,30 @@ impl AtomicCell<bool> {
a.fetch_and(val, Ordering::AcqRel)
}
+ /// Applies logical "nand" to the current value and returns the previous value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use crossbeam_utils::atomic::AtomicCell;
+ ///
+ /// let a = AtomicCell::new(true);
+ ///
+ /// assert_eq!(a.fetch_nand(false), true);
+ /// assert_eq!(a.load(), true);
+ ///
+ /// assert_eq!(a.fetch_nand(true), true);
+ /// assert_eq!(a.load(), false);
+ ///
+ /// assert_eq!(a.fetch_nand(false), false);
+ /// assert_eq!(a.load(), true);
+ /// ```
+ #[inline]
+ pub fn fetch_nand(&self, val: bool) -> bool {
+ let a = unsafe { &*(self.value.get() as *const AtomicBool) };
+ a.fetch_nand(val, Ordering::AcqRel)
+ }
+
/// Applies logical "or" to the current value and returns the previous value.
///
/// # Examples
@@ -683,105 +1001,13 @@ fn lock(addr: usize) -> &'static SeqLock {
// stored at addresses that are multiples of 3. It'd be too bad if `LEN` was divisible by 3.
// In order to protect from such cases, we simply choose a large prime number for `LEN`.
const LEN: usize = 97;
-
+ #[allow(clippy::declare_interior_mutable_const)]
+ const L: SeqLock = SeqLock::new();
static LOCKS: [SeqLock; LEN] = [
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
- SeqLock::new(),
+ L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L,
+ L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L,
+ L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L,
+ L, L, L, L, L, L, L,
];
// If the modulus is a constant number, the compiler will use crazy math to transform this into
@@ -804,7 +1030,6 @@ impl AtomicUnit {
#[inline]
fn swap(&self, _val: (), _order: Ordering) {}
- #[allow(clippy::unnecessary_wraps)] // This is intentional.
#[inline]
fn compare_exchange_weak(
&self,
@@ -833,7 +1058,6 @@ macro_rules! atomic {
($t:ty, $a:ident, $atomic_op:expr, $fallback_op:expr) => {
loop {
atomic!(@check, $t, AtomicUnit, $a, $atomic_op);
- atomic!(@check, $t, atomic::AtomicUsize, $a, $atomic_op);
atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
@@ -855,7 +1079,6 @@ macro_rules! atomic {
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>()
| can_transmute::<T, atomic::AtomicU8>()
| can_transmute::<T, atomic::AtomicU16>()
| can_transmute::<T, atomic::AtomicU32>();
diff --git a/src/sync/parker.rs b/src/sync/parker.rs
index aefa515..531f5a5 100644
--- a/src/sync/parker.rs
+++ b/src/sync/parker.rs
@@ -175,6 +175,7 @@ impl Parker {
///
/// let p = Parker::new();
/// let raw = Parker::into_raw(p);
+ /// # let _ = unsafe { Parker::from_raw(raw) };
/// ```
pub fn into_raw(this: Parker) -> *const () {
Unparker::into_raw(this.unparker)
@@ -258,6 +259,7 @@ impl Unparker {
/// let p = Parker::new();
/// let u = p.unparker().clone();
/// let raw = Unparker::into_raw(u);
+ /// # let _ = unsafe { Unparker::from_raw(raw) };
/// ```
pub fn into_raw(this: Unparker) -> *const () {
Arc::into_raw(this.inner) as *const ()
diff --git a/src/thread.rs b/src/thread.rs
index c57d076..a59a4f5 100644
--- a/src/thread.rs
+++ b/src/thread.rs
@@ -446,7 +446,7 @@ impl<'scope, 'env> ScopedThreadBuilder<'scope, 'env> {
unsafe { mem::transmute(closure) };
// Finally, spawn the closure.
- self.builder.spawn(move || closure())?
+ self.builder.spawn(closure)?
};
let thread = handle.thread().clone();
diff --git a/tests/atomic_cell.rs b/tests/atomic_cell.rs
index 28208ee..da7a6e1 100644
--- a/tests/atomic_cell.rs
+++ b/tests/atomic_cell.rs
@@ -264,3 +264,69 @@ fn const_atomic_cell_new() {
CELL.store(1);
assert_eq!(CELL.load(), 1);
}
+
+// https://github.com/crossbeam-rs/crossbeam/pull/767
+macro_rules! test_arithmetic {
+ ($test_name:ident, $ty:ident) => {
+ #[test]
+ fn $test_name() {
+ let a: AtomicCell<$ty> = AtomicCell::new(7);
+
+ assert_eq!(a.fetch_add(3), 7);
+ assert_eq!(a.load(), 10);
+
+ assert_eq!(a.fetch_sub(3), 10);
+ assert_eq!(a.load(), 7);
+
+ assert_eq!(a.fetch_and(3), 7);
+ assert_eq!(a.load(), 3);
+
+ assert_eq!(a.fetch_or(16), 3);
+ assert_eq!(a.load(), 19);
+
+ assert_eq!(a.fetch_xor(2), 19);
+ assert_eq!(a.load(), 17);
+
+ assert_eq!(a.fetch_max(18), 17);
+ assert_eq!(a.load(), 18);
+
+ assert_eq!(a.fetch_min(17), 18);
+ assert_eq!(a.load(), 17);
+
+ assert_eq!(a.fetch_nand(7), 17);
+ assert_eq!(a.load(), !(17 & 7));
+ }
+ };
+}
+test_arithmetic!(arithmetic_u8, u8);
+test_arithmetic!(arithmetic_i8, i8);
+test_arithmetic!(arithmetic_u16, u16);
+test_arithmetic!(arithmetic_i16, i16);
+test_arithmetic!(arithmetic_u32, u32);
+test_arithmetic!(arithmetic_i32, i32);
+test_arithmetic!(arithmetic_u64, u64);
+test_arithmetic!(arithmetic_i64, i64);
+test_arithmetic!(arithmetic_u128, u128);
+test_arithmetic!(arithmetic_i128, i128);
+
+// https://github.com/crossbeam-rs/crossbeam/issues/748
+#[cfg_attr(miri, ignore)] // TODO
+#[rustversion::since(1.37)] // #[repr(align(N))] requires Rust 1.37
+#[test]
+fn issue_748() {
+ #[allow(dead_code)]
+ #[repr(align(8))]
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+ enum Test {
+ Field(u32),
+ FieldLess,
+ }
+
+ assert_eq!(mem::size_of::<Test>(), 8);
+ assert_eq!(
+ AtomicCell::<Test>::is_lock_free(),
+ cfg!(not(crossbeam_no_atomic_64))
+ );
+ let x = AtomicCell::new(Test::FieldLess);
+ assert_eq!(x.load(), Test::FieldLess);
+}
diff --git a/tests/sharded_lock.rs b/tests/sharded_lock.rs
index d999008..0718b44 100644
--- a/tests/sharded_lock.rs
+++ b/tests/sharded_lock.rs
@@ -21,6 +21,9 @@ fn smoke() {
#[test]
fn frob() {
const N: u32 = 10;
+ #[cfg(miri)]
+ const M: usize = 100;
+ #[cfg(not(miri))]
const M: usize = 1000;
let r = Arc::new(ShardedLock::new(()));