AtomicI8

Struct AtomicI8 

Source
pub struct AtomicI8 { /* private fields */ }
Expand description

Atomic 8-bit signed integer.

Provides easy-to-use atomic operations with automatic memory ordering selection. All methods are thread-safe and can be shared across threads.

§Memory Ordering Strategy

This type uses carefully chosen default memory orderings:

  • Read operations (load): Use Acquire ordering to ensure visibility of writes from other threads.
  • Write operations (store): Use Release ordering to ensure writes are visible to other threads.
  • Read-Modify-Write (swap, CAS): Use AcqRel ordering for both read and write synchronization.
  • Arithmetic operations (fetch_inc, fetch_add, etc.): Use Relaxed ordering for optimal performance in pure counting scenarios where no other data needs synchronization.
  • Bit operations (fetch_and, fetch_or, etc.): Use AcqRel ordering as they typically synchronize flag states.
  • Max/Min operations: Use AcqRel ordering as they often coordinate with threshold-based logic.

For advanced use cases requiring different memory orderings, use inner() to access the underlying standard library type.

§Features

  • Automatic memory ordering selection
  • Rich set of integer operations (increment, decrement, arithmetic, etc.)
  • Zero-cost abstraction with inline methods
  • Access to underlying type via inner() for advanced use cases

§Example

use prism3_rust_concurrent::atomic::AtomicI8;
use std::sync::Arc;
use std::thread;

let counter = Arc::new(AtomicI8::new(0));
let mut handles = vec![];

for _ in 0..10 {
    let counter = counter.clone();
    let handle = thread::spawn(move || {
        for _ in 0..100 {
            counter.fetch_inc();
        }
    });
    handles.push(handle);
}

for handle in handles {
    handle.join().unwrap();
}

assert_eq!(counter.load(), 1000);

§Author

Haixing Hu

Implementations§

Source§

impl AtomicI8

Source

pub const fn new(value: i8) -> Self

Creates a new atomic integer.

§Parameters
  • value - The initial value.
§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(42);
assert_eq!(atomic.load(), 42);
Source

pub fn load(&self) -> i8

Loads the current value.

§Memory Ordering

Uses Acquire ordering to ensure that:

  • This load operation happens-before any subsequent memory operations in the current thread.
  • If another thread performed a Release store, all writes before that store are visible after this load.

This is the standard choice for reading shared state that may have been modified by other threads.

§Returns

The current value.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(42);
assert_eq!(atomic.load(), 42);
Source

pub fn store(&self, value: i8)

Stores a new value.

§Memory Ordering

Uses Release ordering to ensure that:

  • All memory operations before this store in the current thread happen-before the store.
  • When another thread performs an Acquire load and sees this value, all writes before this store become visible.

This is the standard choice for publishing data to other threads.

§Parameters
  • value - The new value to store.
§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(0);
atomic.store(42);
assert_eq!(atomic.load(), 42);
Source

pub fn swap(&self, value: i8) -> i8

Swaps the current value with a new value, returning the old value.

§Memory Ordering

Uses AcqRel ordering to ensure that:

  • Acquire: Reads the current value and establishes happens-before with prior Release operations.
  • Release: Writes the new value and makes all prior writes visible to subsequent Acquire operations.

This is the standard choice for atomic exchange operations that both read and write.

§Parameters
  • value - The new value to swap in.
§Returns

The old value.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let old = atomic.swap(20);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 20);
Source

pub fn compare_set(&self, current: i8, new: i8) -> Result<(), i8>

Compares and sets the value atomically.

If the current value equals current, sets it to new and returns Ok(()). Otherwise, returns Err(actual) where actual is the current value.

§Memory Ordering
  • Success: Uses AcqRel ordering (both Acquire and Release) to synchronize with other threads.
  • Failure: Uses Acquire ordering to see the latest value written by other threads.

This is the standard CAS pattern: on success, we need Release to publish our write; on failure, we need Acquire to see what value actually exists.

§Parameters
  • current - The expected current value.
  • new - The new value to set if current matches.
§Returns

Ok(()) on success, or Err(actual) on failure.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
assert!(atomic.compare_set(10, 20).is_ok());
assert_eq!(atomic.load(), 20);
Source

pub fn compare_set_weak(&self, current: i8, new: i8) -> Result<(), i8>

Weak version of compare-and-set.

May spuriously fail even when the comparison succeeds. Should be used in a loop.

Uses AcqRel ordering on success and Acquire ordering on failure.

§Parameters
  • current - The expected current value.
  • new - The new value to set if current matches.
§Returns

Ok(()) on success, or Err(actual) on failure.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let mut current = atomic.load();
loop {
    match atomic.compare_set_weak(current, current + 1) {
        Ok(_) => break,
        Err(actual) => current = actual,
    }
}
assert_eq!(atomic.load(), 11);
Source

pub fn compare_and_exchange(&self, current: i8, new: i8) -> i8

Compares and exchanges the value atomically, returning the previous value.

If the current value equals current, sets it to new and returns the old value. Otherwise, returns the actual current value.

Uses AcqRel ordering on success and Acquire ordering on failure.

§Parameters
  • current - The expected current value.
  • new - The new value to set if current matches.
§Returns

The value before the operation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let prev = atomic.compare_and_exchange(10, 20);
assert_eq!(prev, 10);
assert_eq!(atomic.load(), 20);
Source

pub fn compare_and_exchange_weak(&self, current: i8, new: i8) -> i8

Weak version of compare-and-exchange.

May spuriously fail even when the comparison succeeds. Should be used in a loop.

Uses AcqRel ordering on success and Acquire ordering on failure.

§Parameters
  • current - The expected current value.
  • new - The new value to set if current matches.
§Returns

The value before the operation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let mut current = atomic.load();
loop {
    let prev =
        atomic.compare_and_exchange_weak(current, current + 5);
    if prev == current {
        break;
    }
    current = prev;
}
assert_eq!(atomic.load(), 15);
Source

pub fn fetch_inc(&self) -> i8

Increments the value by 1, returning the old value.

§Memory Ordering

Uses Relaxed ordering for optimal performance. This is appropriate for pure counters where:

  • Only the counter value itself needs to be atomic.
  • No other data needs to be synchronized.
  • The typical use case is statistics/counting.

Rationale: Counters are the most common use of atomic integers. Using Relaxed provides maximum performance (especially on ARM) while maintaining correctness for the counter value itself. If you need to synchronize other data, use load()/store() with their stronger orderings.

§Returns

The old value before incrementing.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let old = atomic.fetch_inc();
assert_eq!(old, 10);
assert_eq!(atomic.load(), 11);
Source

pub fn fetch_dec(&self) -> i8

Decrements the value by 1, returning the old value.

Uses Relaxed ordering.

§Returns

The old value before decrementing.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let old = atomic.fetch_dec();
assert_eq!(old, 10);
assert_eq!(atomic.load(), 9);
Source

pub fn fetch_add(&self, delta: i8) -> i8

Adds a delta to the value, returning the old value.

§Memory Ordering

Uses Relaxed ordering for the same reasons as fetch_inc(): optimal performance for pure counting scenarios. See fetch_inc() documentation for detailed rationale.

§Parameters
  • delta - The value to add.
§Returns

The old value before adding.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let old = atomic.fetch_add(5);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 15);
Source

pub fn fetch_sub(&self, delta: i8) -> i8

Subtracts a delta from the value, returning the old value.

Uses Relaxed ordering.

§Parameters
  • delta - The value to subtract.
§Returns

The old value before subtracting.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let old = atomic.fetch_sub(3);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 7);
Source

pub fn fetch_mul(&self, factor: i8) -> i8

Multiplies the value by a factor, returning the old value.

Uses Relaxed ordering for the operation.

§Parameters
  • factor - The factor to multiply by.
§Returns

The old value before multiplication.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let old = atomic.fetch_mul(3);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 30);
Source

pub fn fetch_div(&self, divisor: i8) -> i8

Divides the value by a divisor, returning the old value.

Uses Relaxed ordering for the operation.

§Parameters
  • divisor - The divisor to divide by.
§Returns

The old value before division.

§Panics

Panics if divisor is zero.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(30);
let old = atomic.fetch_div(3);
assert_eq!(old, 30);
assert_eq!(atomic.load(), 10);
Source

pub fn fetch_and(&self, value: i8) -> i8

Performs bitwise AND, returning the old value.

§Memory Ordering

Uses AcqRel ordering because bit operations typically manipulate flag bits that coordinate access to other data.

Rationale: Unlike pure counters, bit operations are commonly used for:

  • State flags (INITIALIZED, RUNNING, STOPPED, etc.)
  • Feature toggles
  • Permission masks

These scenarios require synchronization with related data, so we use the stronger AcqRel ordering by default.

§Parameters
  • value - The value to AND with.
§Returns

The old value before the operation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(0b1111);
let old = atomic.fetch_and(0b1100);
assert_eq!(old, 0b1111);
assert_eq!(atomic.load(), 0b1100);
Source

pub fn fetch_or(&self, value: i8) -> i8

Performs bitwise OR, returning the old value.

Uses AcqRel ordering.

§Parameters
  • value - The value to OR with.
§Returns

The old value before the operation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(0b1100);
let old = atomic.fetch_or(0b0011);
assert_eq!(old, 0b1100);
assert_eq!(atomic.load(), 0b1111);
Source

pub fn fetch_xor(&self, value: i8) -> i8

Performs bitwise XOR, returning the old value.

Uses AcqRel ordering.

§Parameters
  • value - The value to XOR with.
§Returns

The old value before the operation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(0b1100);
let old = atomic.fetch_xor(0b0110);
assert_eq!(old, 0b1100);
assert_eq!(atomic.load(), 0b1010);
Source

pub fn fetch_not(&self) -> i8

Performs bitwise NOT, returning the old value.

This is a convenience method equivalent to fetch_xor(-1). Uses AcqRel ordering.

§Returns

The old value before the operation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(0b1010_0101);
let old = atomic.fetch_not();
assert_eq!(old, 0b1010_0101);
assert_eq!(atomic.load(), !0b1010_0101_i8);
§Note

This method is implemented using fetch_xor(-1) because hardware and LLVM do not provide a native atomic NOT instruction. The compiler will optimize this into efficient machine code.

Source

pub fn fetch_update<F>(&self, f: F) -> i8
where F: Fn(i8) -> i8,

Updates the value using a function, returning the old value.

Internally uses a CAS loop until the update succeeds.

§Parameters
  • f - A function that takes the current value and returns the new value.
§Returns

The old value before the update.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let old = atomic.fetch_update(|x| x * 2);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 20);
Source

pub fn fetch_accumulate<F>(&self, x: i8, f: F) -> i8
where F: Fn(i8, i8) -> i8,

Accumulates a value using a binary function, returning the old value.

Internally uses a CAS loop until the update succeeds.

§Parameters
  • x - The value to accumulate with.
  • f - A binary function that takes the current value and x, returning the new value.
§Returns

The old value before the accumulation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
let old = atomic.fetch_accumulate(5, |a, b| a + b);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 15);
Source

pub fn fetch_max(&self, value: i8) -> i8

Sets the value to the maximum of the current value and the given value, returning the old value.

§Memory Ordering

Uses AcqRel ordering because max/min operations often coordinate with threshold-based logic and related metadata.

Rationale: Common use cases include:

  • Peak value tracking with timestamp recording
  • High-water marks that trigger alerts
  • Resource allocation thresholds

These scenarios typically need to synchronize with other data (timestamps, alert states, etc.), so we use AcqRel for safety.

§Parameters
  • value - The value to compare with.
§Returns

The old value before the operation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
atomic.fetch_max(20);
assert_eq!(atomic.load(), 20);

atomic.fetch_max(15);
assert_eq!(atomic.load(), 20);
Source

pub fn fetch_min(&self, value: i8) -> i8

Sets the value to the minimum of the current value and the given value, returning the old value.

Uses AcqRel ordering.

§Parameters
  • value - The value to compare with.
§Returns

The old value before the operation.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;

let atomic = AtomicI8::new(10);
atomic.fetch_min(5);
assert_eq!(atomic.load(), 5);

atomic.fetch_min(8);
assert_eq!(atomic.load(), 5);
Source

pub fn inner(&self) -> &AtomicI8

Gets a reference to the underlying standard library atomic type.

This allows direct access to the standard library’s atomic operations for advanced use cases that require fine-grained control over memory ordering.

§Returns

A reference to the underlying std::sync::atomic::std::sync::atomic::AtomicI8.

§Example
use prism3_rust_concurrent::atomic::AtomicI8;
use std::sync::atomic::Ordering;

let atomic = AtomicI8::new(0);
atomic.inner().store(42, Ordering::Relaxed);
assert_eq!(atomic.inner().load(Ordering::Relaxed), 42);

Trait Implementations§

Source§

impl Atomic for AtomicI8

Source§

type Value = i8

The value type stored in the atomic.
Source§

fn load(&self) -> i8

Loads the current value. Read more
Source§

fn store(&self, value: i8)

Stores a new value. Read more
Source§

fn swap(&self, value: i8) -> i8

Swaps the current value with a new value, returning the old value. Read more
Source§

fn compare_set(&self, current: i8, new: i8) -> Result<(), i8>

Compares and sets the value atomically. Read more
Source§

fn compare_set_weak(&self, current: i8, new: i8) -> Result<(), i8>

Weak version of compare-and-set. Read more
Source§

fn compare_exchange(&self, current: i8, new: i8) -> i8

Compares and exchanges the value atomically, returning the previous value. Read more
Source§

fn compare_exchange_weak(&self, current: i8, new: i8) -> i8

Weak version of compare-and-exchange. Read more
Source§

fn fetch_update<F>(&self, f: F) -> i8
where F: Fn(i8) -> i8,

Updates the value using a function, returning the old value. Read more
Source§

impl AtomicNumber for AtomicI8

Source§

fn fetch_add(&self, delta: i8) -> i8

Adds a delta to the value, returning the old value. Read more
Source§

fn fetch_sub(&self, delta: i8) -> i8

Subtracts a delta from the value, returning the old value. Read more
Source§

fn fetch_mul(&self, factor: i8) -> i8

Multiplies the value by a factor, returning the old value. Read more
Source§

fn fetch_div(&self, divisor: i8) -> i8

Divides the value by a divisor, returning the old value. Read more
Source§

impl Debug for AtomicI8

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for AtomicI8

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Display for AtomicI8

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<i8> for AtomicI8

Source§

fn from(value: i8) -> Self

Converts to this type from the input type.
Source§

impl Send for AtomicI8

Source§

impl Sync for AtomicI8

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.