最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

rust - Atomic compare and store if unequal - Stack Overflow

programmeradmin1浏览0评论

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 While this is not technically a duplicate of your other question for C++ because it's a different language, they are almost certainly going to have the same answer. Rust atomics have the same functionality and (effectively) the same memory model as in C++, so your solution to C++ should port over directly. I'd suggest deleting one of the two questions for now. – Nate Eldredge Commented Mar 8 at 6:27
  • @NateEldredge I checked the rust documentation of atomics, I guess c++ equivalent of exchange (unconditional store) method is swap, if I'm not wrong? I think using swap I should be able to achieve the above functionality – Harry Commented Mar 8 at 6:35
  • That's correct. – Nate Eldredge Commented Mar 8 at 6:41
Add a comment  | 

1 Answer 1

Reset to default 0

It'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.

发布评论

评论列表(0)

  1. 暂无评论