AtomicPtr::compare_exchange 在指向结构的指针上使用时的行为是什么?

What is the behavior of AtomicPtr::compare_exchange when used on a pointer to a struct?

compare_exchange 的这种用法会产生定义的行为吗?

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

struct Dummy {
    foo: i64,
    bar: i64,
}

fn main() {
    let ptr = &mut Dummy { foo: 1, bar: 2 };
    let some_ptr = AtomicPtr::new(ptr);

    let other_ptr = &mut Dummy { foo: 10, bar: 10 };

    let value = some_ptr.compare_exchange(ptr, other_ptr, Ordering::SeqCst, Ordering::Relaxed);
}

如果定义了,定义的行为是什么? Rust 会在 x86_64 等支持的架构上使用双宽度 CAS 进行上述操作吗?

Does this usage of compare_exchange produce defined behavior?

除非编译器或标准库中存在错误,否则安全的 Rust 永远不会导致 C 和 C++ 意义上的未定义行为。此外,创建和操作指针始终是安全的,它只是取消引用它们或将它们转换为需要显式 unsafe 的引用,因为程序员需要提供编译器无法验证的保证。当然,对安全函数的特定调用是否如您所愿是另一回事。

If it is defined, what is the defined behavior?

该行为由文档指定:地址 some_ptr 指向的地址与地址 ptr 指向的地址进行比较,如果它们匹配,则 some_ptr 自动更新为指向 other_ptr 提供的地址。在任何一种情况下都返回先前的指针。由于您的代码从 ptr 初始化 some_ptr 并且不创建可以更改它的线程,因此它将导致 some_ptr 指向 other_ptr 提供的地址并返回ptr.

Will Rust use double width CAS for the above operation on supported architectures like x86_64?

AtomicPtr::compare_exchange() 只比较和交换指针,它和 usize 一样宽(现代硬件上是 64 位),没有理由使用双宽度 CAS。

但我想我理解混乱是如何产生的:compare_exchange 的文档谈到指针的 value。这个“值”不是指向数据的值,它只是底层的 *mut T 指针,它只代表一个内存地址。就像 AtomicBool 的值是 boolAtomicPtr 的值是一个指针。

如果他们说的是“ 指向的地址”而不是“ 的值”,文档会更精确一些,但这样会更冗长。 (较短的“ 的地址”将再次引起歧义,因为它可能被理解为指向指针本身所在的地址。)