Josh Weinstein
Josh Weinstein

Reputation: 2968

rust what does a failed compare exchange on AtomicPtr return?

So in rust, I am trying to see what result is given when a AtomicPtr.compare_exchange() fails, where the expected value is not what is actually contained. I have the following code:

use std::sync::atomic::{AtomicPtr, Ordering};

pub fn foo() {
    let ptr = &mut 5;
    let ptr2 = &mut 6;
    let atomic_ptr = AtomicPtr::new(ptr);
    unsafe {
        match atomic_ptr.compare_exchange(ptr, ptr2, Ordering::SeqCst, Ordering::SeqCst) {
            Ok(got) => println!("Worked got {}", *got),
            Err(nogot) => println!("Failed got {}", *nogot),
        }
    }
}

pub fn bar() {
    let ptr = &mut 5;
    let ptr2 = &mut 6;
    let atomic_ptr = AtomicPtr::new(ptr);
    unsafe {
        match atomic_ptr.compare_exchange(ptr2, ptr2, Ordering::SeqCst, Ordering::SeqCst) {
            Ok(got) => println!("Worked got {}", *got),
            Err(nogot) => println!("Failed got {}", *nogot),
        }
    }
}

fn main() {
    foo();
    bar();
}

But this prints

Worked got 5
Failed got 5

It seems both success and fail for the compare exchange give the currently held pointer. Is this truly the case? Or am I missing something here? The docs don't document what the Result gives on failure either https://doc.rust-lang.org/std/sync/atomic/struct.AtomicPtr.html#method.compare_exchange

Upvotes: 0

Views: 995

Answers (1)

Masklinn
Masklinn

Reputation: 42492

It seems both success and fail for the compare exchange give the currently held pointer. Is this truly the case?

Yes.

The docs don't document what the Result gives on failure either

They do, though the wording obscures it:

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

This is actually 3 completely separate clauses:

  • the return value is a result indicating whether the new value was written (Ok) -- implies that it's an Err on failure
  • the return value contains the previous value -- regardless of success
  • on success the the return value is guaranteed equal to current -- obviously on failure the current you provided was wrong, so you get something else (the actual current value)

Either opening a documentation issue or a documentation PR to clarify this would probably be welcome, though beware that this issue seems to be duplicated on all three implementations of compare_exchange so you'll probably have to fix them all if you go the PR route: all integer types are implemented via a common macro but AtomicPtr and AtomicBool have their own copies of the entire interface.

Upvotes: 3

Related Questions