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 之后,即使使用更宽松的内存顺序也是如此?
提前致谢!
要回答标题中的问题,原子和序列点之间没有真正的关系。
编写的代码确实保证编译器必须atomic_fetch_sub在atomic_load. 但这些函数(在 C 的内存模型中)只是简单地请求平台对某些内存块执行某些操作。当它们对谁可见时,它们的效果由内存模型和排序参数指定。因此,即使您知道请求 A 在请求 B 之前出现,也不意味着请求 A 的影响会在请求 B 之前解决,除非您明确指定。