diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-15 21:43:45 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-15 21:43:45 +0000 |
commit | f8213fb1349b8dda0318d0dfed7ba4e1a4f68017 (patch) | |
tree | daaf08af737e70ccff84d0af339162a544fead0a | |
parent | 3a6a6e2bac76253a08b529b5ca7a4fdc9872beac (diff) | |
parent | f85f5d224d731630716bfd9a48489056a68919dc (diff) | |
download | crossbeam-utils-f8213fb1349b8dda0318d0dfed7ba4e1a4f68017.tar.gz |
Snap for 8730993 from f85f5d224d731630716bfd9a48489056a68919dc to mainline-tzdata3-releaseaml_tz3_314012070aml_tz3_314012050aml_tz3_314012010aml_tz3_313110000aml_tz3_312511020aml_tz3_312511010aml_tz3_312410020aml_tz3_312410010android12-mainline-tzdata3-releaseaml_tz3_314012010
Change-Id: I15be08aeb5e652e2ca372538682d8984f592dde4
-rw-r--r-- | .cargo_vcs_info.json | 7 | ||||
-rw-r--r-- | Android.bp | 134 | ||||
-rw-r--r-- | CHANGELOG.md | 20 | ||||
-rw-r--r-- | Cargo.toml | 38 | ||||
-rw-r--r-- | Cargo.toml.orig | 22 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | TEST_MAPPING | 64 | ||||
-rw-r--r-- | build.rs | 62 | ||||
-rw-r--r-- | cargo2android.json | 9 | ||||
-rw-r--r-- | no_atomic.rs | 71 | ||||
-rw-r--r-- | patches/disable_panic_tests_on_android.patch | 8 | ||||
-rw-r--r-- | src/atomic/atomic_cell.rs | 566 | ||||
-rw-r--r-- | src/atomic/consume.rs | 24 | ||||
-rw-r--r-- | src/atomic/mod.rs | 8 | ||||
-rw-r--r-- | src/lib.rs | 27 | ||||
-rw-r--r-- | src/sync/parker.rs | 2 | ||||
-rw-r--r-- | src/thread.rs | 2 | ||||
-rw-r--r-- | tests/atomic_cell.rs | 120 | ||||
-rw-r--r-- | tests/cache_padded.rs | 1 | ||||
-rw-r--r-- | tests/sharded_lock.rs | 5 |
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" + } +} @@ -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) @@ -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" @@ -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 } } @@ -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" } ] } @@ -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; @@ -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>>, } |