Is it possible to atomically compare for inequality, and if it's true (not equal) store the value it's compared with. The below code doesn't achieve this using a single atomic operation
use std::sync::atomic::{AtomicI32, Ordering};
static AT: AtomicI32 = AtomicI32::new(23);
fn main() {
let a = 32;
if AT.load(Ordering::SeqCst) != a {
println!("not equal");
AT.store(a, Ordering::SeqCst);
}
}
Is it possible to atomically compare for inequality, and if it's true (not equal) store the value it's compared with. The below code doesn't achieve this using a single atomic operation
use std::sync::atomic::{AtomicI32, Ordering};
static AT: AtomicI32 = AtomicI32::new(23);
fn main() {
let a = 32;
if AT.load(Ordering::SeqCst) != a {
println!("not equal");
AT.store(a, Ordering::SeqCst);
}
}
Share
Improve this question
asked Mar 8 at 5:40
HarryHarry
3,2681 gold badge24 silver badges46 bronze badges
3
|
1 Answer
Reset to default 0It's not really clear to me how an operation like this would be meaningful, since you could just perform an unconditional store. If the value DOES equal a
, then it will still equal a
even after the store is done. The fact that you're using SeqCst
ordering further implies to me that there isn't a particular ordering constraint you're trying to uphold by avoiding the write.
There's no single atomic instruction that I'm aware of that fulfills the described operation. However, it's possible to implement a formally atomic operation that fulfills the requirement (formal in the sense appearing atomic from the point of view of an external observer):
use std::sync::atomic::{AtomicI32, Ordering};
/// Store a value into target if it doesn't already have that value. Returns
/// true if a store occurred.
fn store_if_neq(target: &AtomicI32, value: i32) -> bool {
let mut current = target.load(Ordering::Acquire);
loop {
if current == value {
break false;
} else {
current = match targetpare_exchange_weak(
current,
value,
Ordering::Release,
Ordering::Acquire,
) {
Ok(_) => break true,
Err(new) => new,
}
};
}
}
This function has the property that a write only occurs if the value is known to not equal the new value. It achieves this guarantee at the cost of higher read pressure. It avoids the race condition in your original code, which is that between the load
and the store
, it's possible that that atomic became equal to a
from another thread.
But, again, I really would just do the unconditional store. I really don't know why you'd try to avoid it.
exchange
(unconditional store) method isswap
, if I'm not wrong? I think usingswap
I should be able to achieve the above functionality – Harry Commented Mar 8 at 6:35