CAS'ing C++ 中 64 位字的 32 个低位

问题描述 投票:0回答:1

我有一个 64 位共享变量,一个线程想要 CAS 该字的低 32 位,同时忽略该字的高 32 位的更改。有没有一种便携式的免锁方式?

这样的东西是否有效,或者它违反了与严格别名或 C++ 对象模型相关的内容?:

union {
    std::atomic<std::int64_t> desc;
    struct {
        std::atomic<uint32_t> ldesc;
        std::atomic<uint32_t> hdesc;
    };
} variable;

variable.desc = 0;
uint32_t x = 0;
variable.ldesc.compare_exchange_weak(x, 1);
c++ c++20 union atomic strict-aliasing
1个回答
0
投票

在当前标准中指定的 C++ 内存/对象模型中无法执行此操作。

如果原子对象是 64 位宽,则只有原语可以读取整个 64 位对象的值(可能除了逐字节读取当前未指定的对象表示形式)。

即使对于非原子访问甚至标量对象也是如此。即使成员是非原子的,您的示例也会有未定义的行为。 (从技术上讲,根据标准,匿名

struct
成员不是有效的语法。)

您可以使用

std::start_lifetime_as
将对象替换为不同类型的新对象,但是 必须 在线程之间进行外部同步,然后再进行访问,因为旧类型不再可能了。

话虽这么说,编译器通常在非原子情况下支持联合类型双关,以与 C 兼容。我不完全确定 C 是否允许原子类型的类型双关,或者它的内存模型是否允许您正在尝试的操作要做。

© www.soinside.com 2019 - 2024. All rights reserved.