在C ++草案标准中多次使用“强烈发生于”这一短语。
例如:终止 [basic.start.term] / 5
如果具有静态存储持续时间的对象的初始化强烈发生在对std :: atexit的调用之前(请参见[support.start.term]),则对该函数的调用将传递给std :: atexit在调用对象的析构函数之前进行排序。如果对std :: atexit的调用强烈发生在具有静态存储持续时间的对象的初始化完成之前,则在调用传递给std :: atexit的函数之前对对象的析构函数的调用进行排序。如果对std :: atexit的调用在另一次对std :: atexit的调用之前强烈发生,则传递给第二个std :: atexit的函数的调用在传递给第二个std :: atexit的函数之前被排序。第一个std :: atexit调用。
并在 数据竞赛 [intro.races] / 12中定义
评估A发生在评估D之前,如果发生以下情况之一
(12.1)A在D之前排序,或
(12.2)A与D同步,并且A和D都是顺序一致的原子操作([atomics.order]),或
(12.3)对B和C进行求值,使得A在B之前排序,B仅发生在C之前,而C在D之前排序,或者
(12.4)有一个评估B,使得A强烈发生在B之前,而B强烈发生在D之前。
[注意:非正式地,如果A强烈地发生在B之前,那么在所有情况下A似乎都在B之前被评估。强烈发生在排除消耗操作之前。—尾注]
为什么引入“强烈发生”?直觉上,它与“之前发生的事情”有什么区别和关系?
注释中的“在所有情况下,似乎A在B之前都被评估”是什么意思?
(注意:此问题的动机是Peter Cordes在此答案下的评论。)
标准报价附加草案(感谢Peter Cordes)
所有memory_order :: seq_cst操作(包括篱笆)上都有一个总顺序S,它满足以下约束。首先,如果A和B是memory_order ::: seq_cst运算,并且A强烈地发生在B之前,那么A在S中先于B.其次,对于对象M上的每对原子操作A和B,A的相干性在B之前,S必须满足以下四个条件:
(4.1)如果A和B都是memory_order :: seq_cst操作,则A在S中先于B; 和
(4.2)如果A是一个memory_order ::: seq_cst操作,而B发生在memory_order :: seq_cst栅栏Y之前,则A在S中位于Y之前; 和
(4.3)如果memory_order :: seq_cst栅栏X发生在A之前,而B是memory_order :: seq_cst操作,则X在S之前位于B之前; 和
(4.4)如果memory_order :: seq_cst栅栏X发生在A之前,而B发生在memory_order :: seq_cst栅栏Y之前,那么X在S中位于Y之前。
atexit()
在一个线程中调用另一个线程exit()
,则仅初始化器仅携带基于消费的依赖关系是不够的,因为其结果不同于exit()
同一线程调用的结果。我的一个较旧的答案与此差异有关。
exit()
。任何线程都可以通过退出来杀死整个程序,或者主线程可以通过return
-ing 退出。这将导致atexit()
处理程序的调用以及所有正在执行的线程的死亡。
seq_cst
在Atomics 31.4顺序和一致性中还引用了“ A强烈发生在B之前”作为规则的条件: 4。这不在C ++ 17 n4659标准中,在该标准中32.4-3定义了seq_cst ops的单个总顺序的存在与所有受影响位置的“先发生”顺序和修改顺序一致;在稍后的草稿中添加了“强烈”一词。