Ungkapan "sangat terjadi sebelum" digunakan beberapa kali dalam standar konsep C ++.
Misalnya: Pengakhiran [basic.start.term] / 5
Jika penyelesaian inisialisasi objek dengan durasi penyimpanan statis sangat terjadi sebelum panggilan ke std :: atexit (lihat, [support.start.term]), panggilan ke fungsi diteruskan ke std :: atexit diurutkan sebelum panggilan ke destruktor untuk objek. Jika panggilan ke std :: atexit sangat terjadi sebelum penyelesaian inisialisasi objek dengan durasi penyimpanan statis, panggilan ke destruktor untuk objek tersebut diurutkan sebelum panggilan ke fungsi diteruskan ke std :: atexit . Jika panggilan ke std :: atexit sangat terjadi sebelum panggilan lain ke std :: atexit, panggilan ke fungsi diteruskan ke panggilan std :: atexit kedua diurutkan sebelum panggilan ke fungsi dialihkan ke std pertama :: panggilan atexit.
Dan didefinisikan dalam Data races [intro.races] / 12
Evaluasi A sangat terjadi sebelum evaluasi D jika, baik
(12.1) A diurutkan sebelum D, atau
(12.2) A menyinkronkan dengan D, dan baik A maupun D adalah operasi atom yang konsisten secara berurutan ([urutan atom]), atau
(12.3) ada evaluasi B dan C sehingga A diurutkan sebelum B, B hanya terjadi sebelum C, dan C diurutkan sebelum D, atau
(12.4) ada evaluasi B sehingga A sangat terjadi sebelum B, dan B sangat terjadi sebelum D.
[Catatan: Secara informal, jika A sangat terjadi sebelum B, maka A tampaknya dievaluasi sebelum B dalam semua konteks. Sangat terjadi sebelum mengecualikan operasi konsumsi. - catatan akhir]
Mengapa "sangat terjadi sebelum" diperkenalkan? Secara intuitif, apa perbedaan dan hubungannya dengan "terjadi sebelumnya"?
Apa arti "A tampaknya dievaluasi sebelum B dalam semua konteks" dalam catatan?
(Catatan: motivasi untuk pertanyaan ini adalah komentar Peter Cordes di bawah jawaban ini .)
Tambahan kutipan standar draft (terima kasih kepada Peter Cordes)
Ketertiban dan konsistensi [atomics.order] / 4
Ada urutan total tunggal S pada semua operasi memory_order :: seq_cst, termasuk pagar, yang memenuhi batasan berikut. Pertama, jika A dan B adalah operasi memory_order :: seq_cst dan A sangat terjadi sebelum B, maka A mendahului B dalam S. Kedua, untuk setiap pasangan operasi atom A dan B pada objek M, di mana A diperintahkan koherensi sebelum B, empat kondisi berikut ini harus dipenuhi oleh S:
(4.1) jika A dan B keduanya operasi memory_order :: seq_cst, maka A mendahului B dalam S; dan
(4.2) jika A adalah operasi memory_order :: seq_cst dan B terjadi sebelum memory_order :: seq_cst pagar Y, maka A mendahului Y di S; dan
(4.3) jika memory_order :: seq_cst pagar X terjadi sebelum A dan B adalah memory_order :: seq_cst operasi, maka X mendahului B dalam S; dan
(4.4) jika memory_order :: seq_cst pagar X terjadi sebelum A dan B terjadi sebelum memory_order :: seq_cst pagar Y, maka X mendahului Y di S.
atexit()
satu utas dan exit()
lainnya, itu tidak cukup bagi inisialisasi untuk hanya membawa ketergantungan berbasis konsumsi hanya karena hasilnya kemudian berbeda dari jika exit()
dipanggil oleh utas yang sama. Jawaban saya yang lebih tua menyangkut perbedaan ini.
exit()
. Setiap utas dapat mematikan seluruh program dengan keluar, atau utas utama dapat keluar dengan return
-ing. Ini menghasilkan panggilan atexit()
penangan dan kematian semua utas apa pun yang mereka lakukan.
seq_cst
, dalam Atom 31.4 Urutan dan konsistensi: 4 . Itu tidak dalam standar C ++ 17 n4659 , di mana 32,4 - 3 mendefinisikan keberadaan satu urutan total operasi seq_cst yang konsisten dengan pesanan "terjadi sebelumnya" dan pesanan modifikasi untuk semua lokasi yang terpengaruh ; "sangat" ditambahkan dalam konsep kemudian.