C ++ドラフト標準では、「前に強く起こる」というフレーズが何度か使用されています。
std :: atexitへの呼び出し([support.start.term]を参照)の前に、静的ストレージ期間を持つオブジェクトの初期化が強く発生した場合、std :: atexitに渡された関数の呼び出しオブジェクトのデストラクタを呼び出す前にシーケンス化されます。std :: atexitの呼び出しが静的ストレージ期間のオブジェクトの初期化が完了する前に強く発生する場合、オブジェクトのデストラクタの呼び出しは、std :: atexitに渡される関数の呼び出しの前にシーケンスされます。std :: atexitへの呼び出しがstd :: atexitへの別の呼び出しの前に強く発生する場合、2番目の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)AがBの前に強く発生し、BがDの前に強く発生するという評価Bがあります。
[注:非公式に、AがBの前に強く発生する場合、AはすべてのコンテキストでBの前に評価されるように見えます。excludeが操作を消費する前に強く発生します。—エンドノート]
なぜ「以前に強く起こる」ことが導入されたのですか?直感的に、その違いと「以前の出来事」との関係は何ですか?
ノートの「AはすべてのコンテキストでBより先に評価されるように見える」とはどういう意味ですか?
(注:この質問の動機は、この回答の下でのPeter Cordesのコメントです。)
追加の標準草案(Peter Cordesに感謝)
順序と一貫性 [atomics.order] / 4
すべてのmemory_order :: seq_cst操作(フェンスを含む)には、次の制約を満たす単一の合計順序Sがあります。まず、AとBがmemory_order :: seq_cst操作で、AがBの前に強く発生する場合、AはSでBの前に発生します。 Bの前に、Sが満たすには、次の4つの条件が必要です。
(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演算である場合、SでXがBに先行します。そして
(4.4)memory_order :: seq_cstフェンスXがAの前に発生し、Bがmemory_order :: seq_cstフェンスYの前に発生する場合、XはSでYに先行します。
atexit()
1つのスレッドとexit()
別のスレッドで呼び出す場合、結果exit()
が同じスレッドで呼び出された場合とは異なるため、初期化子が消費ベースの依存関係のみを運ぶだけでは不十分です。私の古い回答はこの違いを懸念していました。
exit()
。どのスレッドも終了することでプログラム全体をreturn
強制終了できます。またはメインスレッドは-ingで終了できます。その結果、atexit()
ハンドラーが呼び出され、すべてのスレッドが実行していたすべてのスレッドが停止します。
seq_cst
には、:アトミック31.4秩序と一貫性 4。これはC ++ 17 n4659標準にはありません。ここで、32.4-3は、影響を受けるすべての場所の「前に発生する」順序と変更順序と一致する seq_cst opsの単一の合計順序の存在を定義します。「強く」は後のドラフトで追加されました。