From 84055e96003b76a487d33502152feafde2aa0b71 Mon Sep 17 00:00:00 2001 From: Tim Nieradzik Date: Thu, 14 Sep 2023 17:23:28 +0300 Subject: [PATCH 1/6] Remove redundant `nightly` feature for fetch_min, fetch_max and fetch_update See also https://github.com/rust-lang/rust/issues/48655#issuecomment-646727924 --- README.md | 4 ++-- src/lib.rs | 18 ++++++------------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 0be8db5..253ae8b 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ Traits over atomic primitive integer types. ## Notes -* Enable feature `nightly` to get `min`, `max`, `fetch_update` and - `as_mut_ptr` when you have a nightly compiler available. +* Enable feature `nightly` to get `as_mut_ptr` when you have a nightly compiler available. +* Rust 1.45.0 or newer is required ## Copyright and License diff --git a/src/lib.rs b/src/lib.rs index 503e9ff..bb15390 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg_attr(feature = "nightly", feature(atomic_min_max, atomic_mut_ptr, no_more_cas))] +#![cfg_attr(feature = "nightly", feature(atomic_mut_ptr))] use std::sync::atomic::{self, Ordering}; use std::hash::Hash; use std::fmt::{Debug, Display}; @@ -64,18 +64,15 @@ pub trait AtomicInt : Default + Send + Sync + RefUnwindSafe + UnwindSafe { ordering: Ordering ) -> ::Prim; - #[cfg(feature="nightly")] fn fetch_min(&self, val: ::Prim, order: Ordering) -> ::Prim; - #[cfg(feature="nightly")] fn fetch_max(&self, val: ::Prim, order: Ordering) -> ::Prim; - #[cfg(feature="nightly")] fn fetch_update( &self, - f: F, + set_order: Ordering, fetch_order: Ordering, - set_order: Ordering + f: F ) -> Result<::Prim, ::Prim> where F: FnMut(::Prim) -> Option<::Prim>; @@ -173,7 +170,6 @@ macro_rules! impl_atomic_int { self.fetch_xor(new, ordering) } - #[cfg(feature = "nightly")] fn fetch_min( &self, val: $prim, @@ -182,7 +178,6 @@ macro_rules! impl_atomic_int { self.fetch_min(val, ordering) } - #[cfg(feature = "nightly")] fn fetch_max( &self, val: $prim, @@ -191,17 +186,16 @@ macro_rules! impl_atomic_int { self.fetch_max(val, ordering) } - #[cfg(feature = "nightly")] fn fetch_update( &self, - f: F, - fetch_order: Ordering, set_order: Ordering, + fetch_order: Ordering, + f: F, ) -> Result<$prim, $prim> where F: FnMut($prim) -> Option<$prim>, { - self.fetch_update(f, fetch_order, set_order) + self.fetch_update(set_order, fetch_order, f) } fn get_mut(&mut self) -> &mut $prim { From 70c3aee242466aa5428929dcd06996a8e0eb4ad9 Mon Sep 17 00:00:00 2001 From: Tim Nieradzik Date: Thu, 14 Sep 2023 17:46:30 +0300 Subject: [PATCH 2/6] Define ZERO, ONE, MIN and MAX --- src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index bb15390..8d51f35 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,12 @@ pub trait AtomicInt : Default + Send + Sync + RefUnwindSafe + UnwindSafe { + Shr + ShrAssign + Sub + SubAssign; + const ZERO: ::Prim; + const ONE: ::Prim; + + const MIN: ::Prim; + const MAX: ::Prim; + fn new(val: ::Prim) -> Self; fn fetch_add( @@ -116,6 +122,12 @@ pub trait AtomicInt : Default + Send + Sync + RefUnwindSafe + UnwindSafe { macro_rules! impl_atomic_int { ($atomic:ty = $prim:ty) => { impl AtomicInt for $atomic { + const ZERO: $prim = 0; + const ONE: $prim = 1; + + const MIN: $prim = <$prim>::MIN; + const MAX: $prim = <$prim>::MAX; + type Prim = $prim; fn new(val: $prim) -> Self { From 159afb32ca5ea5f920547bc94260b7e1ec3a4592 Mon Sep 17 00:00:00 2001 From: Tim Nieradzik Date: Thu, 14 Sep 2023 17:48:59 +0300 Subject: [PATCH 3/6] Remove deprecated compare_and_swap() function This function was deprecated in Rust 1.50.0. compare_exchange() or compare_exchange_weak() may be used instead. --- src/lib.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8d51f35..2328cc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,13 +92,6 @@ pub trait AtomicInt : Default + Send + Sync + RefUnwindSafe + UnwindSafe { fn swap(&self, val: ::Prim, order: Ordering) -> ::Prim; - fn compare_and_swap( - &self, - current: ::Prim, - new: ::Prim, - ordering: Ordering - ) -> ::Prim; - fn compare_exchange( &self, current: ::Prim, @@ -230,15 +223,6 @@ macro_rules! impl_atomic_int { self.swap(val, order) } - fn compare_and_swap( - &self, - current: $prim, - new: $prim, - ordering: Ordering - ) -> $prim { - self.compare_and_swap(current, new, ordering) - } - fn compare_exchange( &self, current: $prim, From 72d162b30b607e8a8bc20895ca0e57fbcf9d0422 Mon Sep 17 00:00:00 2001 From: Tim Nieradzik Date: Thu, 14 Sep 2023 17:50:18 +0300 Subject: [PATCH 4/6] Add IDEA project folder to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 96ef6c0..1b9ff89 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +/.idea/ From ba8fcc24e4693a48d6f65ccacfa51a240783f97c Mon Sep 17 00:00:00 2001 From: Tim Nieradzik Date: Thu, 14 Sep 2023 18:13:17 +0300 Subject: [PATCH 5/6] Override Output of primitive traits and add test case --- src/lib.rs | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2328cc3..8c1d99f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,17 +14,17 @@ use std::ops::{ pub trait AtomicInt : Default + Send + Sync + RefUnwindSafe + UnwindSafe { type Prim : Copy + Debug + Display + Eq + Hash + Ord + Sized - + Add + AddAssign - + BitAnd + BitAndAssign - + BitOr + BitOrAssign - + BitXor + BitXorAssign - + Div + DivAssign - + Mul + MulAssign - + Not - + Rem + RemAssign - + Shl + ShlAssign - + Shr + ShrAssign - + Sub + SubAssign; + + Add::Prim> + AddAssign + + BitAnd::Prim> + BitAndAssign + + BitOr::Prim> + BitOrAssign + + BitXor::Prim> + BitXorAssign + + Div::Prim> + DivAssign + + Mul::Prim> + MulAssign + + Not::Prim> + + Rem::Prim> + RemAssign + + Shl::Prim> + ShlAssign + + Shr::Prim> + ShrAssign + + Sub::Prim> + SubAssign; const ZERO: ::Prim; const ONE: ::Prim; @@ -262,3 +262,28 @@ impl_atomic_int!(atomic::AtomicI16 = i16); impl_atomic_int!(atomic::AtomicI32 = i32); impl_atomic_int!(atomic::AtomicI64 = i64); impl_atomic_int!(atomic::AtomicIsize = isize); + +#[cfg(test)] +mod test { + use std::sync::atomic::AtomicU8; + use super::*; + + #[test] + fn test_fetch_update() { + fn incr(value: &T) -> Result<::Prim, ::Prim> { + value.fetch_update( + Ordering::SeqCst, + Ordering::SeqCst, + |i| Some(if i == T::MAX { T::MIN } else { i + T::ONE }) + ) + } + + let value = AtomicU8::new(0); + assert_eq!(incr(&value), Ok(0)); + assert_eq!(incr(&value), Ok(1)); + + let value = AtomicU8::new(255); + assert_eq!(incr(&value), Ok(255)); + assert_eq!(incr(&value), Ok(0)); + } +} \ No newline at end of file From 168b9b8af5b5409f146dae06283013d150221774 Mon Sep 17 00:00:00 2001 From: Tim Nieradzik Date: Thu, 14 Sep 2023 18:17:17 +0300 Subject: [PATCH 6/6] Add example to README --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 253ae8b..9a47c3a 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,30 @@ Traits over atomic primitive integer types. +## Example + +```rust +fn incr(value: &T) -> Result<::Prim, ::Prim> { + value.fetch_update( + Ordering::SeqCst, + Ordering::SeqCst, + |i| Some(if i == T::MAX { T::MIN } else { i + T::ONE }) + ) +} + +let value = AtomicU8::new(255); +assert_eq!(incr(&value), Ok(255)); +assert_eq!(incr(&value), Ok(0)); +``` + ## Notes * Enable feature `nightly` to get `as_mut_ptr` when you have a nightly compiler available. -* Rust 1.45.0 or newer is required +* Rust 1.45.0 or newer is required. ## Copyright and License - Copyright (c) 2020 James Laver, atomic_prim_traits contributors. + Copyright (c) 2020-2023 James Laver, atomic_prim_traits contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this