aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 21:43:45 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 21:43:45 +0000
commitf8213fb1349b8dda0318d0dfed7ba4e1a4f68017 (patch)
treedaaf08af737e70ccff84d0af339162a544fead0a
parent3a6a6e2bac76253a08b529b5ca7a4fdc9872beac (diff)
parentf85f5d224d731630716bfd9a48489056a68919dc (diff)
downloadcrossbeam-utils-f8213fb1349b8dda0318d0dfed7ba4e1a4f68017.tar.gz
Change-Id: I15be08aeb5e652e2ca372538682d8984f592dde4
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp134
-rw-r--r--CHANGELOG.md20
-rw-r--r--Cargo.toml38
-rw-r--r--Cargo.toml.orig22
-rw-r--r--METADATA8
-rw-r--r--README.md2
-rw-r--r--TEST_MAPPING64
-rw-r--r--build.rs62
-rw-r--r--cargo2android.json9
-rw-r--r--no_atomic.rs71
-rw-r--r--patches/disable_panic_tests_on_android.patch8
-rw-r--r--src/atomic/atomic_cell.rs566
-rw-r--r--src/atomic/consume.rs24
-rw-r--r--src/atomic/mod.rs8
-rw-r--r--src/lib.rs27
-rw-r--r--src/sync/parker.rs2
-rw-r--r--src/thread.rs2
-rw-r--r--tests/atomic_cell.rs120
-rw-r--r--tests/cache_padded.rs1
-rw-r--r--tests/sharded_lock.rs5
21 files changed, 363 insertions, 837 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 0d40a83..1d9c34d 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,5 @@
{
"git": {
- "sha1": "2988f873f87d2263a7fd2b9465fb9c28f43a6490"
- },
- "path_in_vcs": "crossbeam-utils"
-} \ No newline at end of file
+ "sha1": "d841a2028dc72b4e09739116f07e865db60f3690"
+ }
+}
diff --git a/Android.bp b/Android.bp
index 5f17007..1a2c24f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --config cargo2android.json.
+// This file is generated by cargo2android.py --run --device --dependencies --tests.
// Do not modify this file as changes will be overridden on upgrade.
package {
@@ -39,37 +39,47 @@ license {
],
}
-rust_test {
- name: "crossbeam-utils_test_src_lib",
- host_supported: true,
+rust_defaults {
+ name: "crossbeam-utils_defaults",
crate_name: "crossbeam_utils",
- cargo_env_compat: true,
- cargo_pkg_version: "0.8.7",
srcs: ["src/lib.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
- test_options: {
- unit_test: true,
- },
edition: "2018",
features: [
"default",
"lazy_static",
"std",
],
+ cfgs: [
+ "has_atomic_u16",
+ "has_atomic_u32",
+ "has_atomic_u64",
+ "has_atomic_u8",
+ ],
rustlibs: [
"libcfg_if",
"liblazy_static",
"librand",
],
- proc_macros: ["librustversion"],
+}
+
+rust_test_host {
+ name: "crossbeam-utils_host_test_src_lib",
+ defaults: ["crossbeam-utils_defaults"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "crossbeam-utils_device_test_src_lib",
+ defaults: ["crossbeam-utils_defaults"],
}
rust_defaults {
- name: "crossbeam-utils_test_defaults",
+ name: "crossbeam-utils_defaults_crossbeam_utils",
crate_name: "crossbeam_utils",
- cargo_env_compat: true,
- cargo_pkg_version: "0.8.7",
test_suites: ["general-tests"],
auto_gen_config: true,
edition: "2018",
@@ -78,19 +88,23 @@ rust_defaults {
"lazy_static",
"std",
],
+ cfgs: [
+ "has_atomic_u16",
+ "has_atomic_u32",
+ "has_atomic_u64",
+ "has_atomic_u8",
+ ],
rustlibs: [
"libcfg_if",
"libcrossbeam_utils",
"liblazy_static",
"librand",
],
- proc_macros: ["librustversion"],
}
-rust_test {
- name: "crossbeam-utils_test_tests_atomic_cell",
- defaults: ["crossbeam-utils_test_defaults"],
- host_supported: true,
+rust_test_host {
+ name: "crossbeam-utils_host_test_tests_atomic_cell",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
srcs: ["tests/atomic_cell.rs"],
test_options: {
unit_test: true,
@@ -98,9 +112,14 @@ rust_test {
}
rust_test {
- name: "crossbeam-utils_test_tests_cache_padded",
- defaults: ["crossbeam-utils_test_defaults"],
- host_supported: true,
+ name: "crossbeam-utils_device_test_tests_atomic_cell",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+ srcs: ["tests/atomic_cell.rs"],
+}
+
+rust_test_host {
+ name: "crossbeam-utils_host_test_tests_cache_padded",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
srcs: ["tests/cache_padded.rs"],
test_options: {
unit_test: true,
@@ -108,9 +127,14 @@ rust_test {
}
rust_test {
- name: "crossbeam-utils_test_tests_parker",
- defaults: ["crossbeam-utils_test_defaults"],
- host_supported: true,
+ name: "crossbeam-utils_device_test_tests_cache_padded",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+ srcs: ["tests/cache_padded.rs"],
+}
+
+rust_test_host {
+ name: "crossbeam-utils_host_test_tests_parker",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
srcs: ["tests/parker.rs"],
test_options: {
unit_test: true,
@@ -118,9 +142,14 @@ rust_test {
}
rust_test {
- name: "crossbeam-utils_test_tests_sharded_lock",
- defaults: ["crossbeam-utils_test_defaults"],
- host_supported: true,
+ name: "crossbeam-utils_device_test_tests_parker",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+ srcs: ["tests/parker.rs"],
+}
+
+rust_test_host {
+ name: "crossbeam-utils_host_test_tests_sharded_lock",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
srcs: ["tests/sharded_lock.rs"],
test_options: {
unit_test: true,
@@ -128,9 +157,14 @@ rust_test {
}
rust_test {
- name: "crossbeam-utils_test_tests_thread",
- defaults: ["crossbeam-utils_test_defaults"],
- host_supported: true,
+ name: "crossbeam-utils_device_test_tests_sharded_lock",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+ srcs: ["tests/sharded_lock.rs"],
+}
+
+rust_test_host {
+ name: "crossbeam-utils_host_test_tests_thread",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
srcs: ["tests/thread.rs"],
test_options: {
unit_test: true,
@@ -138,21 +172,30 @@ rust_test {
}
rust_test {
- name: "crossbeam-utils_test_tests_wait_group",
- defaults: ["crossbeam-utils_test_defaults"],
- host_supported: true,
+ name: "crossbeam-utils_device_test_tests_thread",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+ srcs: ["tests/thread.rs"],
+}
+
+rust_test_host {
+ name: "crossbeam-utils_host_test_tests_wait_group",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
srcs: ["tests/wait_group.rs"],
test_options: {
unit_test: true,
},
}
+rust_test {
+ name: "crossbeam-utils_device_test_tests_wait_group",
+ defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+ srcs: ["tests/wait_group.rs"],
+}
+
rust_library {
name: "libcrossbeam_utils",
host_supported: true,
crate_name: "crossbeam_utils",
- cargo_env_compat: true,
- cargo_pkg_version: "0.8.7",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
@@ -160,12 +203,25 @@ rust_library {
"lazy_static",
"std",
],
+ cfgs: [
+ "has_atomic_u16",
+ "has_atomic_u32",
+ "has_atomic_u64",
+ "has_atomic_u8",
+ ],
rustlibs: [
"libcfg_if",
"liblazy_static",
],
- apex_available: [
- "//apex_available:platform",
- "com.android.virt",
- ],
}
+
+// dependent_library ["feature_list"]
+// autocfg-1.0.1
+// cfg-if-1.0.0
+// getrandom-0.2.2 "std"
+// lazy_static-1.4.0
+// libc-0.2.93
+// 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"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98088c5..c4a92bf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,23 +1,3 @@
-# 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)
-
-# Version 0.8.4
-
-- Bump `loom` dependency to version 0.5. (#686)
-
# Version 0.8.3
- Make `loom` dependency optional. (#666)
diff --git a/Cargo.toml b/Cargo.toml
index 10d3240..a7d694c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,52 +3,40 @@
# 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 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.
+# 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)
[package]
edition = "2018"
-rust-version = "1.36"
name = "crossbeam-utils"
-version = "0.8.7"
+version = "0.8.3"
+authors = ["The Crossbeam Project Developers"]
description = "Utilities for concurrent programming"
homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
-keywords = [
- "scoped",
- "thread",
- "atomic",
- "cache",
-]
-categories = [
- "algorithms",
- "concurrency",
- "data-structures",
- "no-std",
-]
+documentation = "https://docs.rs/crossbeam-utils"
+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"
+[build-dependencies.autocfg]
+version = "1.0.0"
[features]
default = ["std"]
nightly = []
std = ["lazy_static"]
-
[target."cfg(crossbeam_loom)".dependencies.loom]
-version = "0.5"
+version = "0.4"
optional = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 73508a9..30697d2 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -4,12 +4,13 @@ name = "crossbeam-utils"
# - Update CHANGELOG.md
# - Update README.md
# - Create "crossbeam-utils-X.Y.Z" git tag
-version = "0.8.7"
+version = "0.8.3"
+authors = ["The Crossbeam Project Developers"]
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"]
@@ -21,13 +22,10 @@ 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: 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.
+# Note that this is outside of the normal semver guarantees and minor versions
+# of crossbeam may make breaking changes to them at any time.
nightly = []
[dependencies]
@@ -36,11 +34,13 @@ lazy_static = { version = "1.4.0", optional = true }
# Enable the use of loom for concurrency testing.
#
-# 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.
+# This configuration option is outside of the normal semver guarantees: minor
+# versions of crossbeam may make breaking changes to it at any time.
[target.'cfg(crossbeam_loom)'.dependencies]
-loom = { version = "0.5", optional = true }
+loom = { version = "0.4", optional = true }
+
+[build-dependencies]
+autocfg = "1.0.0"
[dev-dependencies]
rand = "0.8"
-rustversion = "1"
diff --git a/METADATA b/METADATA
index 2c55b77..e66f8d0 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.7.crate"
+ value: "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.3.crate"
}
- version: "0.8.7"
+ version: "0.8.3"
license_type: NOTICE
last_upgrade_date {
- year: 2022
- month: 3
+ year: 2021
+ month: 4
day: 1
}
}
diff --git a/README.md b/README.md
index 6e9a8e4..fd0943b 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ https://crates.io/crates/crossbeam-utils)
https://docs.rs/crossbeam-utils)
[![Rust 1.36+](https://img.shields.io/badge/rust-1.36+-lightgray.svg)](
https://www.rust-lang.org)
-[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ)
+[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.gg/BBYwKq)
This crate provides miscellaneous tools for concurrent programming:
diff --git a/TEST_MAPPING b/TEST_MAPPING
index eb8da39..a68b776 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,78 +1,32 @@
// Generated by update_crate_tests.py for tests that depend on this crate.
{
- "imports": [
- {
- "path": "external/rust/crates/base64"
- },
- {
- "path": "external/rust/crates/crossbeam-deque"
- },
- {
- "path": "external/rust/crates/crossbeam-epoch"
- },
- {
- "path": "external/rust/crates/crossbeam-queue"
- },
- {
- "path": "external/rust/crates/once_cell"
- },
- {
- "path": "external/rust/crates/tinytemplate"
- },
- {
- "path": "external/rust/crates/tinyvec"
- },
- {
- "path": "external/rust/crates/unicode-xid"
- },
- {
- "path": "external/rust/crates/vulkano"
- }
- ],
"presubmit": [
{
- "name": "crossbeam-utils_test_src_lib"
- },
- {
- "name": "crossbeam-utils_test_tests_atomic_cell"
- },
- {
- "name": "crossbeam-utils_test_tests_cache_padded"
- },
- {
- "name": "crossbeam-utils_test_tests_parker"
+ "name": "crossbeam-epoch_device_test_src_lib"
},
{
- "name": "crossbeam-utils_test_tests_sharded_lock"
+ "name": "crossbeam-epoch_device_test_tests_loom"
},
{
- "name": "crossbeam-utils_test_tests_thread"
- },
- {
- "name": "crossbeam-utils_test_tests_wait_group"
- }
- ],
- "presubmit-rust": [
- {
- "name": "crossbeam-utils_test_src_lib"
+ "name": "crossbeam-utils_device_test_src_lib"
},
{
- "name": "crossbeam-utils_test_tests_atomic_cell"
+ "name": "crossbeam-utils_device_test_tests_atomic_cell"
},
{
- "name": "crossbeam-utils_test_tests_cache_padded"
+ "name": "crossbeam-utils_device_test_tests_cache_padded"
},
{
- "name": "crossbeam-utils_test_tests_parker"
+ "name": "crossbeam-utils_device_test_tests_parker"
},
{
- "name": "crossbeam-utils_test_tests_sharded_lock"
+ "name": "crossbeam-utils_device_test_tests_sharded_lock"
},
{
- "name": "crossbeam-utils_test_tests_thread"
+ "name": "crossbeam-utils_device_test_tests_thread"
},
{
- "name": "crossbeam-utils_test_tests_wait_group"
+ "name": "crossbeam-utils_device_test_tests_wait_group"
}
]
}
diff --git a/build.rs b/build.rs
index a7557fd..3e51021 100644
--- a/build.rs
+++ b/build.rs
@@ -1,61 +1,23 @@
-// 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");
+use autocfg::AutoCfg;
+// 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,
+ let cfg = match AutoCfg::new() {
+ Ok(cfg) => cfg,
Err(e) => {
println!(
- "cargo:warning={}: unable to get TARGET environment variable: {}",
- env!("CARGO_PKG_NAME"),
+ "cargo:warning=crossbeam-utils: unable to determine rustc version: {}",
e
);
return;
}
};
- // 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` or `"max-atomic-width" == 128`.
- }
-
- println!("cargo:rerun-if-changed=no_atomic.rs");
+ 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");
}
diff --git a/cargo2android.json b/cargo2android.json
deleted file mode 100644
index 6e516e0..0000000
--- a/cargo2android.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "apex-available": [
- "//apex_available:platform",
- "com.android.virt"
- ],
- "device": true,
- "run": true,
- "tests": true
-} \ No newline at end of file
diff --git a/no_atomic.rs b/no_atomic.rs
deleted file mode 100644
index 90ac60a..0000000
--- a/no_atomic.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-// This file is @generated by no_atomic.sh.
-// It is not intended for manual editing.
-
-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)] // Only crossbeam-utils uses this.
-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",
- "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",
- "powerpc-unknown-netbsd",
- "powerpc-unknown-openbsd",
- "powerpc-wrs-vxworks",
- "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",
-];
-
-#[allow(dead_code)] // Only crossbeam-utils uses this.
-const NO_ATOMIC: &[&str] = &[
- "avr-unknown-gnu-atmega328",
- "msp430-none-elf",
- "riscv32i-unknown-none-elf",
- "riscv32imc-unknown-none-elf",
-];
diff --git a/patches/disable_panic_tests_on_android.patch b/patches/disable_panic_tests_on_android.patch
index 3306735..49e4758 100644
--- a/patches/disable_panic_tests_on_android.patch
+++ b/patches/disable_panic_tests_on_android.patch
@@ -1,5 +1,5 @@
---- a/tests/sharded_lock.rs
-+++ b/tests/sharded_lock.rs
+--- tests/sharded_lock.rs
++++ tests/sharded_lock.rs
@@ -46,6 +46,8 @@ fn frob() {
}
@@ -63,8 +63,8 @@
fn test_get_mut_poison() {
let m = Arc::new(ShardedLock::new(NonCopy(10)));
let m2 = m.clone();
---- a/tests/thread.rs
-+++ b/tests/thread.rs
+--- tests/thread.rs
++++ tests/thread.rs
@@ -9,6 +9,8 @@ const THREADS: usize = 10;
const SMALL_STACK_SIZE: usize = 20;
diff --git a/src/atomic/atomic_cell.rs b/src/atomic/atomic_cell.rs
index 8a49464..ad094b2 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;
@@ -258,44 +258,10 @@ 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 {
- ($t:ty, fallback, $example:tt) => {
+ ($t:ty, $example:tt) => {
impl AtomicCell<$t> {
/// Increments the current value by `val` and returns the previous value.
///
@@ -313,13 +279,10 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_add(&self, val: $t) -> $t {
- #[cfg(crossbeam_loom)]
- {
- let _ = val;
- unimplemented!("loom does not support non-atomic atomic ops");
- }
- #[cfg(not(crossbeam_loom))]
- {
+ 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 {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -344,13 +307,10 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_sub(&self, val: $t) -> $t {
- #[cfg(crossbeam_loom)]
- {
- let _ = val;
- unimplemented!("loom does not support non-atomic atomic ops");
- }
- #[cfg(not(crossbeam_loom))]
- {
+ 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 {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -373,13 +333,10 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_and(&self, val: $t) -> $t {
- #[cfg(crossbeam_loom)]
- {
- let _ = val;
- unimplemented!("loom does not support non-atomic atomic ops");
- }
- #[cfg(not(crossbeam_loom))]
- {
+ 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 {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -388,35 +345,6 @@ 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
@@ -431,13 +359,10 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_or(&self, val: $t) -> $t {
- #[cfg(crossbeam_loom)]
- {
- let _ = val;
- unimplemented!("loom does not support non-atomic atomic ops");
- }
- #[cfg(not(crossbeam_loom))]
- {
+ 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 {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -460,13 +385,10 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_xor(&self, val: $t) -> $t {
- #[cfg(crossbeam_loom)]
- {
- let _ = val;
- unimplemented!("loom does not support non-atomic atomic ops");
- }
- #[cfg(not(crossbeam_loom))]
- {
+ 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 {
let _guard = lock(self.value.get() as usize).write();
let value = unsafe { &mut *(self.value.get()) };
let old = *value;
@@ -474,66 +396,6 @@ 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) => {
@@ -554,24 +416,8 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_add(&self, val: $t) -> $t {
- 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
- }
- }
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_add(val, Ordering::AcqRel)
}
/// Decrements the current value by `val` and returns the previous value.
@@ -590,24 +436,8 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_sub(&self, val: $t) -> $t {
- 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
- }
- }
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_sub(val, Ordering::AcqRel)
}
/// Applies bitwise "and" to the current value and returns the previous value.
@@ -624,58 +454,8 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_and(&self, val: $t) -> $t {
- 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
- }
- }
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_and(val, Ordering::AcqRel)
}
/// Applies bitwise "or" to the current value and returns the previous value.
@@ -692,24 +472,8 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_or(&self, val: $t) -> $t {
- 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
- }
- }
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_or(val, Ordering::AcqRel)
}
/// Applies bitwise "xor" to the current value and returns the previous value.
@@ -726,124 +490,40 @@ macro_rules! impl_arithmetic {
/// ```
#[inline]
pub fn fetch_xor(&self, val: $t) -> $t {
- 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
- }
- }
+ let a = unsafe { &*(self.value.get() as *const $atomic) };
+ a.fetch_xor(val, Ordering::AcqRel)
}
}
};
}
+#[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(not(crossbeam_no_atomic_64))]
+#[cfg(has_atomic_u64)]
impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
-#[cfg(not(crossbeam_no_atomic_64))]
+#[cfg(all(has_atomic_u64, not(crossbeam_loom)))]
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);");
+#[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);");
impl_arithmetic!(
usize,
atomic::AtomicUsize,
"let a = AtomicCell::new(7usize);"
);
+#[cfg(not(crossbeam_loom))]
impl_arithmetic!(
isize,
atomic::AtomicIsize,
@@ -872,30 +552,6 @@ 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
@@ -1001,13 +657,105 @@ 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] = [
- 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,
+ 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(),
];
// If the modulus is a constant number, the compiler will use crazy math to transform this into
@@ -1030,6 +778,7 @@ impl AtomicUnit {
#[inline]
fn swap(&self, _val: (), _order: Ordering) {}
+ #[allow(clippy::unnecessary_wraps)] // This is intentional.
#[inline]
fn compare_exchange_weak(
&self,
@@ -1058,14 +807,18 @@ 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);
+ #[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(not(crossbeam_no_atomic_64))]
+ #[cfg(has_atomic_u64)]
atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op);
- // TODO: AtomicU128 is unstable
- // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
+ #[cfg(has_atomic_u128)]
+ atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
#[cfg(crossbeam_loom)]
unimplemented!("loom does not support non-atomic atomic ops");
@@ -1078,14 +831,17 @@ 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::AtomicU8>()
- | can_transmute::<T, atomic::AtomicU16>()
- | can_transmute::<T, atomic::AtomicU32>();
- #[cfg(not(crossbeam_no_atomic_64))]
+ 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 = is_lock_free | can_transmute::<T, atomic::AtomicU64>();
- // TODO: AtomicU128 is unstable
- // let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
+ #[cfg(has_atomic_u128)]
+ 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 277b370..0fbd93e 100644
--- a/src/atomic/consume.rs
+++ b/src/atomic/consume.rs
@@ -1,6 +1,5 @@
#[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.
@@ -26,7 +25,6 @@ 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 {
() => {
@@ -39,7 +37,6 @@ macro_rules! impl_consume {
};
}
-#[cfg(not(crossbeam_no_atomic))]
#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
macro_rules! impl_consume {
() => {
@@ -52,13 +49,12 @@ macro_rules! impl_consume {
macro_rules! impl_atomic {
($atomic:ident, $val:ty) => {
- #[cfg(not(crossbeam_no_atomic))]
- impl AtomicConsume for core::sync::atomic::$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!();
}
@@ -67,26 +63,32 @@ 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(not(crossbeam_no_atomic_64))]
+#[cfg(has_atomic_u64)]
impl_atomic!(AtomicU64, u64);
-#[cfg(not(crossbeam_no_atomic_64))]
+#[cfg(has_atomic_u64)]
impl_atomic!(AtomicI64, i64);
-#[cfg(not(crossbeam_no_atomic))]
-impl<T> AtomicConsume for core::sync::atomic::AtomicPtr<T> {
+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 fc713fc..874eaf2 100644
--- a/src/atomic/mod.rs
+++ b/src/atomic/mod.rs
@@ -3,9 +3,11 @@
//! * [`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))]
-cfg_if::cfg_if! {
+use cfg_if::cfg_if;
+
+#[cfg(not(crossbeam_loom))]
+cfg_if! {
// Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap
// around.
//
@@ -23,10 +25,8 @@ cfg_if::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 191c5a1..880d37e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,6 +38,7 @@
unreachable_pub
)]
#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#[cfg(crossbeam_loom)]
#[allow(unused_imports)]
@@ -46,8 +47,7 @@ mod primitive {
pub(crate) mod atomic {
pub(crate) use loom::sync::atomic::spin_loop_hint;
pub(crate) use loom::sync::atomic::{
- AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16,
- AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
+ AtomicBool, AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
};
// FIXME: loom does not support compiler_fence at the moment.
@@ -70,13 +70,15 @@ mod primitive {
// use [`core::hint::spin_loop`] instead.
#[allow(deprecated)]
pub(crate) use core::sync::atomic::spin_loop_hint;
- #[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::{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)]
pub(crate) use core::sync::atomic::{AtomicI64, AtomicU64};
+ #[cfg(has_atomic_u8)]
+ pub(crate) use core::sync::atomic::{AtomicI8, AtomicU8};
}
#[cfg(feature = "std")]
@@ -84,6 +86,15 @@ 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/src/sync/parker.rs b/src/sync/parker.rs
index 531f5a5..aefa515 100644
--- a/src/sync/parker.rs
+++ b/src/sync/parker.rs
@@ -175,7 +175,6 @@ 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)
@@ -259,7 +258,6 @@ 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 a59a4f5..c57d076 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(closure)?
+ self.builder.spawn(move || closure())?
};
let thread = handle.thread().clone();
diff --git a/tests/atomic_cell.rs b/tests/atomic_cell.rs
index da7a6e1..3d91d81 100644
--- a/tests/atomic_cell.rs
+++ b/tests/atomic_cell.rs
@@ -1,4 +1,3 @@
-use std::mem;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
@@ -9,47 +8,18 @@ fn is_lock_free() {
struct UsizeWrap(usize);
struct U8Wrap(bool);
struct I16Wrap(i16);
- #[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());
+
+ 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));
}
#[test]
@@ -264,69 +234,3 @@ 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/cache_padded.rs b/tests/cache_padded.rs
index 86e9a77..c9e7687 100644
--- a/tests/cache_padded.rs
+++ b/tests/cache_padded.rs
@@ -85,7 +85,6 @@ 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 0718b44..b4b8565 100644
--- a/tests/sharded_lock.rs
+++ b/tests/sharded_lock.rs
@@ -21,9 +21,6 @@ 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(()));
@@ -151,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>>,
}