C11原子与序列点的关系

Sky*_*mer 5 c atomic sequence-points language-lawyer stdatomic

我基本上有以下代码片段:

size_t counter = atomic_fetch_sub_explicit(&atomicCounter, 1, memory_order_release);
if (counter - 1 == 0
    && atomic_load_explicit(&anotherAtomicCounter, 1, memory_order_relaxed) == 0 {
      //Some code
}
Run Code Online (Sandbox Code Playgroud)

为了正确性,重要的是 的原子加载anotherAtomicCounter发生在 的 fetch-and-sub (FAS) 之后atomicCounter。对于给定的内存顺序,通常无法保证这一点,并且加载可能会在 FAS 之前发生。但是,我想知道序列点如何影响这个特定的代码。标准中提到

如果评估 A 在评估 B 之前排序,则 A 评估将在 B 评估开始之前完成。

与规则 2 结合

在以下二元运算符的第一个(左)操作数评估之后和第二个(右)操作数评估之前有一个序列点:&&(逻辑与)、|| (逻辑或),和,(逗号)。

这意味着原子加载必须在比较之后发生,但只有在知道 FAS 的结果后才能完成比较。

我的问题是这些规则是否保证原子加载始终发生在 FAS 之后,即使使用更宽松的内存顺序也是如此?

提前致谢!

orl*_*rlp 2

要回答标题中的问题,原子和序列点之间没有真正的关系。

编写的代码确实保证编译器必须atomic_fetch_subatomic_load. 但这些函数(在 C 的内存模型中)只是简单地请求平台对某些内存块执行某些操作。当它们对谁可见时,它们的效果由内存模型和排序参数指定。因此,即使您知道请求 A 在请求 B 之前出现,也不意味着请求 A 的影响会在请求 B 之前解决,除非您明确指定。