qubit-atomic 0.10.0

User-friendly atomic operations wrapper providing JDK-like atomic API
Documentation
/*******************************************************************************
 *
 *    Copyright (c) 2025 - 2026.
 *    Haixing Hu, Qubit Co. Ltd.
 *
 *    All rights reserved.
 *
 ******************************************************************************/

use std::cell::Cell;
use std::sync::atomic::Ordering;

use qubit_atomic::Atomic;

#[test]
fn test_default_from_debug_display_impls() {
    let bool_default = Atomic::<bool>::default();
    assert!(!bool_default.load());
    let bool_from = Atomic::<bool>::from(true);
    assert_eq!(format!("{bool_from:?}"), "Atomic { value: true }");
    assert_eq!(format!("{bool_from}"), "true");

    let int_default = Atomic::<i32>::default();
    assert_eq!(int_default.load(), 0);
    let int_from = Atomic::<i32>::from(42);
    assert_eq!(format!("{int_from:?}"), "Atomic { value: 42 }");
    assert_eq!(format!("{int_from}"), "42");

    let float_default = Atomic::<f32>::default();
    assert_eq!(float_default.load(), 0.0);
    let float_from = Atomic::<f32>::from(1.5);
    assert_eq!(format!("{float_from:?}"), "Atomic { value: 1.5 }");
    assert_eq!(format!("{float_from}"), "1.5");

    let double_default = Atomic::<f64>::default();
    assert_eq!(double_default.load(), 0.0);
    let double_from = Atomic::<f64>::from(2.5);
    assert_eq!(format!("{double_from:?}"), "Atomic { value: 2.5 }");
    assert_eq!(format!("{double_from}"), "2.5");
}

#[test]
fn test_fetch_update_retry_paths() {
    let bool_atomic = Atomic::<bool>::new(false);
    let bool_raced = Cell::new(false);
    let bool_old = bool_atomic.fetch_update(|current| {
        if !bool_raced.replace(true) {
            bool_atomic.store(!current);
        }
        !current
    });
    assert!(bool_old);
    assert!(!bool_atomic.load());

    let int_atomic = Atomic::<i32>::new(1);
    let int_raced = Cell::new(false);
    let int_old = int_atomic.fetch_update(|current| {
        if !int_raced.replace(true) {
            int_atomic.store(current + 10);
        }
        current * 2
    });
    assert_eq!(int_old, 11);
    assert_eq!(int_atomic.load(), 22);

    let float_atomic = Atomic::<f32>::new(1.0);
    let float_raced = Cell::new(false);
    let float_old = float_atomic.fetch_update(|current| {
        if !float_raced.replace(true) {
            float_atomic.store(current + 10.0);
        }
        current * 2.0
    });
    assert_eq!(float_old, 11.0);
    assert_eq!(float_atomic.load(), 22.0);

    let double_atomic = Atomic::<f64>::new(1.0);
    let double_raced = Cell::new(false);
    let double_old = double_atomic.fetch_update(|current| {
        if !double_raced.replace(true) {
            double_atomic.store(current + 10.0);
        }
        current * 2.0
    });
    assert_eq!(double_old, 11.0);
    assert_eq!(double_atomic.load(), 22.0);
}

#[test]
fn test_inner_backends() {
    let flag = Atomic::<bool>::new(false);
    assert!(!flag.inner().load(Ordering::Acquire));

    let number = Atomic::<i32>::new(42);
    assert_eq!(number.inner().load(Ordering::Acquire), 42);
}