Skip to main content
 首页 » 编程设计

c++之"strongly happens before"是什么意思

2024年12月31日8zhoujg

在 C++ 草案标准中多次使用了短语“强烈发生在之前”。
例如:终止 [basic.start.term]/5

If the completion of the initialization of an object with static storage duration strongly happens before a call to std​::​atexit (see , [support.start.term]), the call to the function passed to std​::​atexit is sequenced before the call to the destructor for the object. If a call to std​::​atexit strongly happens before the completion of the initialization of an object with static storage duration, the call to the destructor for the object is sequenced before the call to the function passed to std​::​atexit. If a call to std​::​atexit strongly happens before another call to std​::​atexit, the call to the function passed to the second std​::​atexit call is sequenced before the call to the function passed to the first std​::​atexit call.


并定义在
数据竞争 [intro.races]/12

An evaluation A strongly happens before an evaluation D if, either

(12.1) A is sequenced before D, or

(12.2) A synchronizes with D, and both A and D are sequentially consistent atomic operations ([atomics.order]), or

(12.3) there are evaluations B and C such that A is sequenced before B, B simply happens before C, and C is sequenced before D, or

(12.4) there is an evaluation B such that A strongly happens before B, and B strongly happens before D.

[ Note: Informally, if A strongly happens before B, then A appears to be evaluated before B in all contexts. Strongly happens before excludes consume operations. — end note ]


为什么要引入“强发生在之前”?直观地,它与“发生在之前”有什么区别和关系?
注释中的“A 似乎在所有上下文中都先于 B 求值”是什么意思?
(注意:这个问题的动机是 Peter Cordes 在 this answer 下的评论。)
附加的标准报价草案(感谢 Peter Cordes)
顺序和一致性 [atomics.order]/4

There is a single total order S on all memory_­order​::​seq_­cst operations, including fences, that satisfies the following constraints. First, if A and B are memory_­order​::​seq_­cst operations and A strongly happens before B, then A precedes B in S. Second, for every pair of atomic operations A and B on an object M, where A is coherence-ordered before B, the following four conditions are required to be satisfied by S:

(4.1) if A and B are both memory_­order​::​seq_­cst operations, then A precedes B in S; and

(4.2) if A is a memory_­order​::​seq_­cst operation and B happens before a memory_­order​::​seq_­cst fence Y, then A precedes Y in S; and

(4.3) if a memory_­order​::​seq_­cst fence X happens before A and B is a memory_­order​::​seq_­cst operation, then X precedes B in S; and

(4.4) if a memory_­order​::​seq_­cst fence X happens before A and B happens before a memory_­order​::​seq_­cst fence Y, then X precedes Y in S.

请您参考如下方法:

Why was "strongly happens before" introduced? Intuitively, what's its difference and relation with "happens before"?



也要为“之前发生过”做好准备!
看一下 cppref 的当前快照
https://en.cppreference.com/w/cpp/atomic/memory_order



似乎在 C++20 中添加了“简单地发生在之前”。

Simply happens-before

Regardless of threads, evaluation A simply happens-before evaluation B if any of the following is true:

1) A is sequenced-before B

2) A synchronizes-with B

3) A simply happens-before X, and X simply happens-before B

Note: without consume operations, simply happens-before and happens-before relations are the same.



所以Simply-HB 和HB 是一样的,只是它们处理消费操作的方式不同。见HB

Happens-before

Regardless of threads, evaluation A happens-before evaluation B if any of the following is true:

1) A is sequenced-before B

2) A inter-thread happens before B

The implementation is required to ensure that the happens-before relation is acyclic, by introducing additional synchronization if necessary (it can only be necessary if a consume operation is involved, see Batty et al)



他们在消费方面有何不同?见线程间HB

Inter-thread happens-before

Between threads, evaluation A inter-thread happens before evaluation B if any of the following is true

1) A synchronizes-with B

2) A is dependency-ordered before B

3) ...

...



依赖顺序(即使用释放/消费)的操作是 HB,但不一定是简单的 HB。

消费比获得更轻松,所以如果我理解正确的话,HB 比Simply-HB 更轻松。

Strongly happens-before

Regardless of threads, evaluation A strongly happens-before evaluation B if any of the following is true:

1) A is sequenced-before B

2) A synchronizes with B, and both A and B are sequentially consistent atomic operations

3) A is sequenced-before X, X simply happens-before Y, and Y is sequenced-before B

4) A strongly happens-before X, and X strongly happens-before B

Note: informally, if A strongly happens-before B, then A appears to be evaluated before B in all contexts.

Note: strongly happens-before excludes consume operations.



所以释放/消费操作不能是 Strongly-HB。

Release/acquire 可以是 HB 和 Simply-HB(因为 release/acquire 与同步)但不一定是 Strongly-HB。因为 Strongly-HB 明确表示 A 必须与 B 同步并且是顺序一致的操作。
                            Is happens-before guaranteed? 
 
                        HB             Simply-HB          Strongly-HB 
 
relaxed                 no                 no                 no 
release/consume        yes                 no                 no       
release/acquire        yes                yes                 no 
S.C.                   yes                yes                yes 

What does the "A appears to be evaluated before B in all contexts" in the note mean?



所有上下文:所有线程/所有 CPU 看到(或“最终会同意”)相同的顺序。这是顺序一致性的保证——所有变量的全局总修改顺序。获取/释放链仅保证参与链的线程的感知修改顺序。链外的线程理论上允许看到不同的顺序。

不知道为什么要引入Strongly-HB和Simply-HB。也许有助于澄清如何围绕消费进行操作? Strongly-HB 有一个很好的特性——如果一个线程观察到 A strong-happens-before B,它知道所有线程都会观察到同样的事情。

消费历史:

Paul E. McKenney 负责在 C 和 C++ 标准中使用。 Consume 保证指针赋值和它指向的内存之间的顺序。它的发明是因为 DEC Alpha。 DEC Alpha 可以推测性地取消引用一个指针,因此它也有一个内存栅栏来防止这种情况。 DEC Alpha 不再制造,今天没有处理器有这种行为。消费旨在非常放松。