A frase "fortemente acontece antes" é usada várias vezes no rascunho do padrão C ++.
Por exemplo: Rescisão [basic.start.term] / 5
Se a conclusão da inicialização de um objeto com duração de armazenamento estático ocorrer fortemente antes de uma chamada para std :: atexit (consulte [support.start.term]), a chamada para a função transmitida para std :: atexit é sequenciado antes da chamada para o destruidor do objeto. Se uma chamada para std :: atexit ocorrer fortemente antes da conclusão da inicialização de um objeto com duração de armazenamento estático, a chamada para o destruidor do objeto será sequenciada antes da chamada para a função passada para std :: atexit . Se uma chamada para std :: atexit acontecer fortemente antes de outra chamada para std :: atexit, a chamada para a função passada para a segunda chamada std :: atexit será sequenciada antes da chamada para a função passada para o primeira chamada std :: atexit.
E definido em Corridas de dados [intro.races] / 12
Uma avaliação A ocorre fortemente antes de uma avaliação D se,
(12.1) A é sequenciado antes de D, ou
(12.2) A sincroniza com D, e ambos A e D são operações atômicas sequencialmente consistentes ([atomics.order]), ou
(12.3) existem avaliações B e C, de modo que A é sequenciado antes de B, B simplesmente acontece antes de C e C é sequenciado antes de D, ou
(12.4) há uma avaliação B, de modo que A ocorre fortemente antes de B e B ocorre fortemente antes de D.
[Nota: Informalmente, se A acontecer fortemente antes de B, então A parecerá ser avaliado antes de B em todos os contextos. Fortemente acontece antes de excluir operações de consumo. - nota final]
Por que "fortemente aconteceu antes" foi introduzido? Intuitivamente, qual é a diferença e a relação com "acontece antes"?
O que significa "A parece ser avaliado antes de B em todos os contextos" na nota?
(Nota: a motivação para esta pergunta são os comentários de Peter Cordes sob esta resposta .)
Projeto adicional de cotação padrão (graças a Peter Cordes)
Ordem e consistência [atomics.order] / 4
Existe uma única ordem total S em todas as operações memory_order :: seq_cst, incluindo cercas, que atendem às seguintes restrições. Primeiro, se A e B são operações memory_order :: seq_cst e A ocorre fortemente antes de B, então A precede B em S. Segundo, para cada par de operações atômicas A e B em um objeto M, onde A é ordenado por coerência antes de B, as quatro condições a seguir devem ser atendidas por S:
(4.1) se A e B são ambas operações memory_order :: seq_cst, então A precede B em S; e
(4.2) se A é uma operação memory_order :: seq_cst e B ocorre antes de uma memory_order :: seq_cst cerca Y, então A precede Y em S; e
(4.3) se um memory_order :: seq_cst fence X acontecer antes de A e B ser uma operação memory_order :: seq_cst, X precederá B em S; e
(4.4) se um memory_order :: seq_cst fence X acontecer antes de A e B acontecer antes de um memory_order :: seq_cst fence Y, então X precederá Y em S.
atexit()
um thread e exit()
outro, não é suficiente que os inicializadores carreguem apenas uma dependência baseada em consumo, porque os resultados diferem se forem exit()
invocados pelo mesmo thread. Uma resposta minha mais antiga dizia respeito a essa diferença.
exit()
. Qualquer encadeamento pode matar o programa inteiro saindo, ou o encadeamento principal pode sair return
pressionando -ing. Isso resulta na chamada de atexit()
manipuladores e na morte de todos os threads, independentemente do que eles estavam fazendo.
seq_cst
, no Atomics 31.4 Ordem e consistência: 4 . Isso não está no padrão C ++ 17 n4659 , onde 32.4 - 3 define a existência de uma única ordem total de operações seq_cst consistentes com a ordem "acontece antes" e as ordens de modificação para todos os locais afetados ; o "fortemente" foi adicionado em um rascunho posterior.