mod tests {
use super::{Atomic, Ordering::*};
use bytemuck::NoUninit;
use core::mem;
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, NoUninit)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
struct Foo(u8, u8);
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, NoUninit)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
struct Bar(u64, u64);
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, NoUninit)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
struct Quux(u32);
#[cfg(feature = "serde")]
fn assert_serde<T>(atomic: &Atomic<T>, value: T)
where
T: NoUninit
+ PartialEq
+ std::fmt::Debug
+ for<'a> serde::Deserialize<'a>
+ serde::Serialize,
{
let s = serde_json::to_string(atomic).unwrap();
assert_eq!(s, serde_json::to_string(&value).unwrap());
let x: Atomic<T> = serde_json::from_str(&s).unwrap();
assert_eq!(x.load(SeqCst), value);
}
#[test]
fn atomic_bool() {
let a = Atomic::new(false);
assert_eq!(
Atomic::<bool>::is_lock_free(),
cfg!(target_has_atomic = "8"),
);
assert_eq!(format!("{:?}", a), "Atomic(false)");
assert_eq!(a.load(SeqCst), false);
a.store(true, SeqCst);
assert_eq!(a.swap(false, SeqCst), true);
assert_eq!(a.compare_exchange(true, false, SeqCst, SeqCst), Err(false));
assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false));
assert_eq!(a.fetch_and(false, SeqCst), true);
assert_eq!(a.fetch_or(true, SeqCst), false);
assert_eq!(a.fetch_xor(false, SeqCst), true);
assert_eq!(a.load(SeqCst), true);
#[cfg(feature = "serde")]
assert_serde(&a, true);
}
#[test]
fn atomic_i8() {
let a = Atomic::new(0i8);
assert_eq!(Atomic::<i8>::is_lock_free(), cfg!(target_has_atomic = "8"));
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
// Make sure overflows are handled correctly
assert_eq!(a.fetch_sub(-56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), -74);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(-25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_i16() {
let a = Atomic::new(0i16);
assert_eq!(
Atomic::<i16>::is_lock_free(),
cfg!(target_has_atomic = "16")
);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(-56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 182);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(-25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_i32() {
let a = Atomic::new(0i32);
assert_eq!(
Atomic::<i32>::is_lock_free(),
cfg!(target_has_atomic = "32")
);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(-56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 182);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(-25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_i64() {
let a = Atomic::new(0i64);
assert_eq!(
Atomic::<i64>::is_lock_free(),
cfg!(target_has_atomic = "64") && mem::align_of::<i64>() == 8
);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(-56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 182);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(-25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_i128() {
let a = Atomic::new(0i128);
assert_eq!(
Atomic::<i128>::is_lock_free(),
cfg!(feature = "nightly") & cfg!(target_has_atomic = "128")
);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(-56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 182);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(-25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_isize() {
let a = Atomic::new(0isize);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(-56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 182);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(-25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_u8() {
let a = Atomic::new(0u8);
assert_eq!(Atomic::<u8>::is_lock_free(), cfg!(target_has_atomic = "8"));
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 70);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_u16() {
let a = Atomic::new(0u16);
assert_eq!(
Atomic::<u16>::is_lock_free(),
cfg!(target_has_atomic = "16")
);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 70);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_u32() {
let a = Atomic::new(0u32);
assert_eq!(
Atomic::<u32>::is_lock_free(),
cfg!(target_has_atomic = "32")
);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 70);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_u64() {
let a = Atomic::new(0u64);
assert_eq!(
Atomic::<u64>::is_lock_free(),
cfg!(target_has_atomic = "64") && mem::align_of::<u64>() == 8
);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 70);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_u128() {
let a = Atomic::new(0u128);
assert_eq!(
Atomic::<u128>::is_lock_free(),
cfg!(feature = "nightly") & cfg!(target_has_atomic = "128")
);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 70);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_usize() {
let a = Atomic::new(0usize);
assert_eq!(format!("{:?}", a), "Atomic(0)");
assert_eq!(a.load(SeqCst), 0);
a.store(1, SeqCst);
assert_eq!(a.swap(2, SeqCst), 1);
assert_eq!(a.compare_exchange(5, 45, SeqCst, SeqCst), Err(2));
assert_eq!(a.compare_exchange(2, 3, SeqCst, SeqCst), Ok(2));
assert_eq!(a.fetch_add(123, SeqCst), 3);
assert_eq!(a.fetch_sub(56, SeqCst), 126);
assert_eq!(a.fetch_and(7, SeqCst), 70);
assert_eq!(a.fetch_or(64, SeqCst), 6);
assert_eq!(a.fetch_xor(1, SeqCst), 70);
assert_eq!(a.fetch_min(30, SeqCst), 71);
assert_eq!(a.fetch_max(25, SeqCst), 30);
assert_eq!(a.load(SeqCst), 30);
#[cfg(feature = "serde")]
assert_serde(&a, 30);
}
#[test]
fn atomic_foo() {
let a = Atomic::default();
assert_eq!(Atomic::<Foo>::is_lock_free(), false);
assert_eq!(format!("{:?}", a), "Atomic(Foo(0, 0))");
assert_eq!(a.load(SeqCst), Foo(0, 0));
a.store(Foo(1, 1), SeqCst);
assert_eq!(a.swap(Foo(2, 2), SeqCst), Foo(1, 1));
assert_eq!(
a.compare_exchange(Foo(5, 5), Foo(45, 45), SeqCst, SeqCst),
Err(Foo(2, 2))
);
assert_eq!(
a.compare_exchange(Foo(2, 2), Foo(3, 3), SeqCst, SeqCst),
Ok(Foo(2, 2))
);
assert_eq!(a.load(SeqCst), Foo(3, 3));
#[cfg(feature = "serde")]
assert_serde(&a, Foo(3, 3));
}
#[test]
fn atomic_bar() {
let a = Atomic::default();
assert_eq!(Atomic::<Bar>::is_lock_free(), false);
assert_eq!(format!("{:?}", a), "Atomic(Bar(0, 0))");
assert_eq!(a.load(SeqCst), Bar(0, 0));
a.store(Bar(1, 1), SeqCst);
assert_eq!(a.swap(Bar(2, 2), SeqCst), Bar(1, 1));
assert_eq!(
a.compare_exchange(Bar(5, 5), Bar(45, 45), SeqCst, SeqCst),
Err(Bar(2, 2))
);
assert_eq!(
a.compare_exchange(Bar(2, 2), Bar(3, 3), SeqCst, SeqCst),
Ok(Bar(2, 2))
);
assert_eq!(a.load(SeqCst), Bar(3, 3));
#[cfg(feature = "serde")]
assert_serde(&a, Bar(3, 3));
}
#[test]
fn atomic_quxx() {
let a = Atomic::default();
assert_eq!(
Atomic::<Quux>::is_lock_free(),
cfg!(target_has_atomic = "32")
);
assert_eq!(format!("{:?}", a), "Atomic(Quux(0))");
assert_eq!(a.load(SeqCst), Quux(0));
a.store(Quux(1), SeqCst);
assert_eq!(a.swap(Quux(2), SeqCst), Quux(1));
assert_eq!(
a.compare_exchange(Quux(5), Quux(45), SeqCst, SeqCst),
Err(Quux(2))
);
assert_eq!(
a.compare_exchange(Quux(2), Quux(3), SeqCst, SeqCst),
Ok(Quux(2))
);
assert_eq!(a.load(SeqCst), Quux(3));
#[cfg(feature = "serde")]
assert_serde(&a, Quux(3));
}
}