pub struct AtomicI32 { /* private fields */ }Expand description
Atomic 32-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): UseAcquireordering to ensure visibility of writes from other threads. - Write operations (
store): UseReleaseordering to ensure writes are visible to other threads. - Read-Modify-Write (
swap, CAS): UseAcqRelordering for both read and write synchronization. - Counter arithmetic (
fetch_inc,fetch_dec,fetch_add,fetch_sub): UseRelaxedordering for optimal performance in pure counting scenarios where no other data needs synchronization. Use the corresponding_with_orderingvariants when the counter value is used as a synchronization signal. These operations intentionally follow Rust integer atomic wrapping semantics on overflow and underflow. - CAS-based arithmetic and updates (
fetch_mul,fetch_div,fetch_update,update_and_get,try_update,try_update_and_get,fetch_accumulate,accumulate_and_get): UseAcqRelordering on successful update andAcquireordering on failed CAS attempts. - Bit operations (
fetch_and,fetch_or, etc.): UseAcqRelordering as they typically synchronize flag states. - Max/Min operations: Use
AcqRelordering as they often coordinate with threshold-based logic.
For advanced use cases requiring different memory orderings,
use inner() to access the underlying backend atomic 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 qubit_atomic::Atomic;
use std::sync::Arc;
use std::thread;
let counter = Arc::new(Atomic::<i32>::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = counter.clone();
let handle = thread::spawn(move || {
for _ in 0..10 {
counter.fetch_inc();
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
assert_eq!(counter.load(), 100);Implementations§
Source§impl AtomicI32
impl AtomicI32
Sourcepub fn load(&self) -> i32
pub fn load(&self) -> i32
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
Releasestore, 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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(42);
assert_eq!(atomic.load(), 42);Sourcepub fn store(&self, value: i32)
pub fn store(&self, value: i32)
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
Acquireload 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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(0);
atomic.store(42);
assert_eq!(atomic.load(), 42);Sourcepub fn swap(&self, value: i32) -> i32
pub fn swap(&self, value: i32) -> i32
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
Releaseoperations. - Release: Writes the new value and makes all prior
writes visible to subsequent
Acquireoperations.
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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let old = atomic.swap(20);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 20);Sourcepub fn compare_set(&self, current: i32, new: i32) -> Result<(), i32>
pub fn compare_set(&self, current: i32, new: i32) -> Result<(), i32>
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
AcqRelordering (both Acquire and Release) to synchronize with other threads. - Failure: Uses
Acquireordering 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(()) when the value was replaced.
§Errors
Returns Err(actual) with the observed value when the
comparison fails. In that case, new is not stored.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
assert!(atomic.compare_set(10, 20).is_ok());
assert_eq!(atomic.load(), 20);Sourcepub fn compare_set_weak(&self, current: i32, new: i32) -> Result<(), i32>
pub fn compare_set_weak(&self, current: i32, new: i32) -> Result<(), i32>
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(()) when the value was replaced.
§Errors
Returns Err(actual) with the observed value when the
comparison fails, including possible spurious failures. In
that case, new is not stored.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::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);Sourcepub fn compare_and_exchange(&self, current: i32, new: i32) -> i32
pub fn compare_and_exchange(&self, current: i32, new: i32) -> i32
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 observed before the operation completed. If the
returned value equals current, the exchange succeeded;
otherwise it is the actual value that prevented the exchange.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let prev = atomic.compare_and_exchange(10, 20);
assert_eq!(prev, 10);
assert_eq!(atomic.load(), 20);Sourcepub fn compare_and_exchange_weak(
&self,
current: i32,
new: i32,
) -> Result<i32, i32>
pub fn compare_and_exchange_weak( &self, current: i32, new: i32, ) -> Result<i32, i32>
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
Ok(previous) when the value was replaced, or Err(actual)
when the comparison failed, including possible spurious
failure.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let mut current = atomic.load();
loop {
match atomic.compare_and_exchange_weak(current, current + 5) {
Ok(previous) => {
assert_eq!(previous, current);
break;
}
Err(actual) => current = actual,
}
}
assert_eq!(atomic.load(), 15);Sourcepub fn fetch_inc(&self) -> i32
pub fn fetch_inc(&self) -> i32
Increments the value by 1, returning the old value.
Arithmetic wraps on overflow, matching Rust atomic integer operations.
§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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_inc();
assert_eq!(old, 10);
assert_eq!(atomic.load(), 11);Sourcepub fn fetch_inc_with_ordering(&self, ordering: Ordering) -> i32
pub fn fetch_inc_with_ordering(&self, ordering: Ordering) -> i32
Increments the value by 1 with an explicit memory ordering, returning the old value.
Arithmetic wraps on overflow, matching Rust atomic integer operations.
§Parameters
ordering- The memory ordering used by the atomic read-modify-write operation.
§Returns
The old value before incrementing.
§Example
use qubit_atomic::Atomic;
use std::sync::atomic::Ordering;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_inc_with_ordering(Ordering::AcqRel);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 11);Sourcepub fn fetch_dec(&self) -> i32
pub fn fetch_dec(&self) -> i32
Decrements the value by 1, returning the old value.
Arithmetic wraps on underflow, matching Rust atomic integer operations.
Uses Relaxed ordering.
§Returns
The old value before decrementing.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_dec();
assert_eq!(old, 10);
assert_eq!(atomic.load(), 9);Sourcepub fn fetch_dec_with_ordering(&self, ordering: Ordering) -> i32
pub fn fetch_dec_with_ordering(&self, ordering: Ordering) -> i32
Decrements the value by 1 with an explicit memory ordering, returning the old value.
Arithmetic wraps on underflow, matching Rust atomic integer operations.
§Parameters
ordering- The memory ordering used by the atomic read-modify-write operation.
§Returns
The old value before decrementing.
§Example
use qubit_atomic::Atomic;
use std::sync::atomic::Ordering;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_dec_with_ordering(Ordering::AcqRel);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 9);Sourcepub fn fetch_add(&self, delta: i32) -> i32
pub fn fetch_add(&self, delta: i32) -> i32
Adds a delta to the value, returning the old value.
Arithmetic wraps on overflow and underflow, matching Rust atomic integer operations.
§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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_add(5);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 15);Sourcepub fn fetch_add_with_ordering(&self, delta: i32, ordering: Ordering) -> i32
pub fn fetch_add_with_ordering(&self, delta: i32, ordering: Ordering) -> i32
Adds a delta to the value with an explicit memory ordering, returning the old value.
Arithmetic wraps on overflow and underflow, matching Rust atomic integer operations.
§Parameters
delta- The value to add.ordering- The memory ordering used by the atomic read-modify-write operation.
§Returns
The old value before adding.
§Example
use qubit_atomic::Atomic;
use std::sync::atomic::Ordering;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_add_with_ordering(5, Ordering::AcqRel);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 15);Sourcepub fn fetch_sub(&self, delta: i32) -> i32
pub fn fetch_sub(&self, delta: i32) -> i32
Subtracts a delta from the value, returning the old value.
Arithmetic wraps on overflow and underflow, matching Rust atomic integer operations.
Uses Relaxed ordering.
§Parameters
delta- The value to subtract.
§Returns
The old value before subtracting.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_sub(3);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 7);Sourcepub fn fetch_sub_with_ordering(&self, delta: i32, ordering: Ordering) -> i32
pub fn fetch_sub_with_ordering(&self, delta: i32, ordering: Ordering) -> i32
Subtracts a delta from the value with an explicit memory ordering, returning the old value.
Arithmetic wraps on overflow and underflow, matching Rust atomic integer operations.
§Parameters
delta- The value to subtract.ordering- The memory ordering used by the atomic read-modify-write operation.
§Returns
The old value before subtracting.
§Example
use qubit_atomic::Atomic;
use std::sync::atomic::Ordering;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_sub_with_ordering(3, Ordering::AcqRel);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 7);Sourcepub fn fetch_mul(&self, factor: i32) -> i32
pub fn fetch_mul(&self, factor: i32) -> i32
Multiplies the value by a factor, returning the old value.
Arithmetic wraps on overflow and underflow.
§Memory Ordering
Internally uses a CAS loop via compare_set, which uses
AcqRel ordering on success and Acquire ordering on
failure.
§Parameters
factor- The factor to multiply by.
§Returns
The old value before multiplication.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_mul(3);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 30);Sourcepub fn fetch_div(&self, divisor: i32) -> i32
pub fn fetch_div(&self, divisor: i32) -> i32
Divides the value by a divisor, returning the old value.
Arithmetic uses wrapping division. For signed integers,
MIN / -1 wraps to MIN.
§Memory Ordering
Internally uses a CAS loop via compare_set, which uses
AcqRel ordering on success and Acquire ordering on
failure.
§Parameters
divisor- The divisor to divide by.
§Returns
The old value before division.
§Panics
Panics if divisor is zero.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(30);
let old = atomic.fetch_div(3);
assert_eq!(old, 30);
assert_eq!(atomic.load(), 10);Sourcepub fn fetch_and(&self, value: i32) -> i32
pub fn fetch_and(&self, value: i32) -> i32
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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(0b1111);
let old = atomic.fetch_and(0b1100);
assert_eq!(old, 0b1111);
assert_eq!(atomic.load(), 0b1100);Sourcepub fn fetch_or(&self, value: i32) -> i32
pub fn fetch_or(&self, value: i32) -> i32
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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(0b1100);
let old = atomic.fetch_or(0b0011);
assert_eq!(old, 0b1100);
assert_eq!(atomic.load(), 0b1111);Sourcepub fn fetch_xor(&self, value: i32) -> i32
pub fn fetch_xor(&self, value: i32) -> i32
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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(0b1100);
let old = atomic.fetch_xor(0b0110);
assert_eq!(old, 0b1100);
assert_eq!(atomic.load(), 0b1010);Sourcepub fn fetch_not(&self) -> i32
pub fn fetch_not(&self) -> i32
Performs bitwise NOT, returning the old value.
This is a convenience method equivalent to XOR with an all-ones
bit mask. Uses AcqRel ordering.
§Returns
The old value before the operation.
§Example
use qubit_atomic::Atomic;
let value: i32 = 42;
let atomic = Atomic::<i32>::new(value);
let old = atomic.fetch_not();
assert_eq!(old, value);
assert_eq!(atomic.load(), !value);§Note
This method is implemented using fetch_xor(!0) because
hardware and LLVM do not provide a native atomic NOT
instruction. The compiler will optimize this into
efficient machine code.
Sourcepub fn fetch_update<F>(&self, f: F) -> i32
pub fn fetch_update<F>(&self, f: F) -> i32
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.
The closure may be called more than once when concurrent updates cause CAS retries.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_update(|x| x * 2);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 20);Sourcepub fn update_and_get<F>(&self, f: F) -> i32
pub fn update_and_get<F>(&self, f: F) -> i32
Updates the value using a function, returning the new 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 value committed by the successful update.
The closure may be called more than once when concurrent updates cause CAS retries.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let new = atomic.update_and_get(|x| x * 2);
assert_eq!(new, 20);
assert_eq!(atomic.load(), 20);Sourcepub fn try_update<F>(&self, f: F) -> Option<i32>
pub fn try_update<F>(&self, f: F) -> Option<i32>
Conditionally updates the value using a function.
Internally uses a CAS loop until the update succeeds or the
closure rejects the current value by returning None.
§Parameters
f- A function that takes the current value and returns the new value, orNoneto leave the value unchanged.
§Returns
Some(old_value) when the update succeeds, or None when
f rejects the observed current value.
The closure may be called more than once when concurrent updates cause CAS retries.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(3);
assert_eq!(atomic.try_update(|x| (x % 2 == 1).then_some(x + 1)), Some(3));
assert_eq!(atomic.load(), 4);
assert_eq!(atomic.try_update(|x| (x % 2 == 1).then_some(x + 1)), None);
assert_eq!(atomic.load(), 4);Sourcepub fn try_update_and_get<F>(&self, f: F) -> Option<i32>
pub fn try_update_and_get<F>(&self, f: F) -> Option<i32>
Conditionally updates the value using a function, returning the new value.
Internally uses a CAS loop until the update succeeds or the
closure rejects the current value by returning None.
§Parameters
f- A function that takes the current value and returns the new value, orNoneto leave the value unchanged.
§Returns
Some(new_value) when the update succeeds, or None when
f rejects the observed current value.
The closure may be called more than once when concurrent updates cause CAS retries.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(3);
assert_eq!(
atomic.try_update_and_get(|x| (x % 2 == 1).then_some(x + 1)),
Some(4),
);
assert_eq!(atomic.load(), 4);
assert_eq!(
atomic.try_update_and_get(|x| (x % 2 == 1).then_some(x + 1)),
None,
);
assert_eq!(atomic.load(), 4);Sourcepub fn fetch_accumulate<F>(&self, x: i32, f: F) -> i32
pub fn fetch_accumulate<F>(&self, x: i32, f: F) -> i32
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 andx, returning the new value.
§Returns
The old value before the accumulation.
The closure may be called more than once when concurrent updates cause CAS retries.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let old = atomic.fetch_accumulate(5, |a, b| a + b);
assert_eq!(old, 10);
assert_eq!(atomic.load(), 15);Sourcepub fn accumulate_and_get<F>(&self, x: i32, f: F) -> i32
pub fn accumulate_and_get<F>(&self, x: i32, f: F) -> i32
Accumulates a value using a binary function, returning the new 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 andx, returning the new value.
§Returns
The value committed by the successful accumulation.
The closure may be called more than once when concurrent updates cause CAS retries.
§Example
use qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
let new = atomic.accumulate_and_get(5, |a, b| a + b);
assert_eq!(new, 15);
assert_eq!(atomic.load(), 15);Sourcepub fn fetch_max(&self, value: i32) -> i32
pub fn fetch_max(&self, value: i32) -> i32
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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
atomic.fetch_max(20);
assert_eq!(atomic.load(), 20);
atomic.fetch_max(15);
assert_eq!(atomic.load(), 20);Sourcepub fn fetch_min(&self, value: i32) -> i32
pub fn fetch_min(&self, value: i32) -> i32
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 qubit_atomic::Atomic;
let atomic = Atomic::<i32>::new(10);
atomic.fetch_min(5);
assert_eq!(atomic.load(), 5);
atomic.fetch_min(8);
assert_eq!(atomic.load(), 5);Sourcepub fn inner(&self) -> &AtomicI32
pub fn inner(&self) -> &AtomicI32
Gets a reference to the underlying backend atomic type.
This allows direct access to the backend atomic operations for advanced use cases that require fine-grained control over memory ordering.
§Returns
A reference to the underlying backend atomic type std::sync::atomic::AtomicI32.
§Example
use qubit_atomic::Atomic;
use std::sync::atomic::Ordering;
let atomic = Atomic::<i32>::new(0);
atomic.inner().store(42, Ordering::Relaxed);
assert_eq!(atomic.inner().load(Ordering::Relaxed), 42);