วลี "เกิดขึ้นอย่างแรงก่อน" ถูกใช้หลายครั้งในมาตรฐานฉบับร่าง C ++
ตัวอย่างเช่น: การยุติ [basic.start.term] / 5
หากความสมบูรณ์ของการเริ่มต้นของวัตถุที่มีระยะเวลาการจัดเก็บแบบคงที่เกิดขึ้นก่อนที่จะเรียก std :: atexit (ดู, [support.start.term]) การเรียกฟังก์ชั่นผ่านไปยัง std :: atexit ถูกจัดลำดับก่อนการเรียกไปยัง destructor สำหรับวัตถุ ถ้าการเรียกไปยัง std :: atexit เกิดขึ้นอย่างมากก่อนที่การเริ่มต้นของวัตถุที่มีระยะเวลาการจัดเก็บแบบสแตติกการเรียกไปยัง destructor สำหรับวัตถุนั้นจะถูกจัดลำดับก่อนที่การเรียกไปยังฟังก์ชันที่ส่งผ่านไปยัง std :: atexit . หากการเรียกไปยัง std :: atexit เกิดขึ้นอย่างยิ่งก่อนการเรียกไปยัง std :: atexit การเรียกใช้ฟังก์ชันที่ส่งไปยังการเรียก std :: atexit ที่สองจะถูกจัดลำดับก่อนการเรียกไปยังฟังก์ชันที่ส่งไปยัง first std :: atexit call
และกำหนดไว้ใน Data race [intro.races] / 12
การประเมิน A จะเกิดขึ้นก่อนการประเมิน D อย่างใดอย่างหนึ่ง
(12.1) A ได้รับการจัดลำดับก่อน D หรือ
(12.2) การซิงโครไนซ์กับ D และทั้ง A และ D เป็นการดำเนินการปรมาณูที่สอดคล้องกันตามลำดับ ([atomics.order]) หรือ
(12.3) มีการประเมินผล B และ C เช่นนั้น A จะถูกจัดลำดับก่อน B, B เกิดขึ้นก่อน C, และ C ถูกจัดลำดับก่อน D หรือ
(12.4) มีการประเมินผล B ซึ่งเกิดขึ้นก่อนที่ B และเกิดขึ้นก่อน D
[หมายเหตุ: อย่างไม่เป็นทางการหาก A เกิดขึ้นอย่างรุนแรงก่อน B ดังนั้น A จะปรากฏขึ้นเพื่อประเมินก่อน B ในบริบททั้งหมด เกิดขึ้นอย่างมากก่อนที่จะแยกการดำเนินการบริโภค - บันทึกท้าย]
ทำไม "เกิดขึ้นก่อน" แนะนำ? โดยสังหรณ์ใจความแตกต่างและความสัมพันธ์กับ "เกิดขึ้นก่อน" คืออะไร
"A ปรากฏว่าได้รับการประเมินก่อน B ในบริบททั้งหมด" ในบันทึกย่อหมายความว่าอะไร
(หมายเหตุ: แรงจูงใจสำหรับคำถามนี้คือความคิดเห็นของ Peter Cordes ภายใต้คำตอบนี้)
ใบเสนอราคามาตรฐานฉบับร่างเพิ่มเติม (ขอบคุณ Peter Cordes)
คำสั่งซื้อและความสอดคล้อง [atomics.order] / 4
มีการสั่งซื้อทั้งหมด S เดียวในการดำเนินการ memory_order :: seq_cst ทั้งหมดรวมถึงรั้วที่ตอบสนองข้อ จำกัด ดังต่อไปนี้ ก่อนอื่นถ้าการดำเนินการ A และ B คือ memory_order :: seq_cst และ A เกิดขึ้นอย่างรุนแรงก่อน B ดังนั้น A จะนำหน้า B ใน S วินาทีสำหรับการดำเนินการปรมาณู A และ B ทุกคู่ในวัตถุ M โดยที่ A สั่งการเชื่อมโยงกัน ก่อน B จะต้องมีสี่เงื่อนไขต่อไปนี้เพื่อให้เป็นที่พอใจโดย S:
(4.1) ถ้า A และ B เป็นการดำเนินการ memory_order :: seq_cst ดังนั้น A นำหน้า B ใน S; และ
(4.2) ถ้า A เป็นการดำเนินการ memory_order :: seq_cst และ B เกิดขึ้นก่อนที่ memory_order :: seq_cst ล้อมรอบ Y แล้ว A นำหน้า Y ใน S; และ
(4.3) ถ้า memory_order :: seq_cst fence X เกิดขึ้นก่อน A และ B คือการดำเนินการ memory_order :: seq_cst ดังนั้น X นำหน้า B ใน S; และ
(4.4) ถ้า memory_order :: seq_cst fence X เกิดขึ้นก่อน A และ B เกิดขึ้นก่อน memory_order :: seq_cst fence Y แล้ว X นำหน้า Y ใน S
atexit()
ในเธรดหนึ่งและexit()
อีกเธรดหนึ่งไม่เพียงพอสำหรับ initializers ที่จะใช้การอ้างอิงแบบอิงการสิ้นเปลืองเท่านั้นเนื่องจากผลลัพธ์นั้นแตกต่างจากถ้าexit()
ถูกเรียกโดยเธรดเดียวกัน คำตอบที่เก่ากว่าของฉันเกี่ยวข้องกับความแตกต่างนี้
exit()
นั่นคือวัตถุประสงค์ของการ เธรดใด ๆสามารถฆ่าโปรแกรมทั้งหมดโดยออกจากโปรแกรมหรือเธรดหลักสามารถออกได้โดยreturn
-ing มันส่งผลให้เกิดการเรียกatexit()
ตัวจัดการและความตายของกระทู้ทั้งหมดไม่ว่าพวกเขาจะทำอะไร
seq_cst
ในอะตอม 31.4 สั่งซื้อและความสอดคล้อง: 4 นั่นไม่ใช่ใน C ++ 17 n4659มาตรฐานที่ 32.4-3 กำหนดการดำรงอยู่ของยอดสั่งซื้อเพียงครั้งเดียวของ Ops seq_cst สอดคล้องกับ“เกิดขึ้นก่อนที่” การสั่งซื้อและการปรับเปลี่ยนการสั่งซื้อสำหรับสถานที่ได้รับผลกระทบทั้งหมด ; เพิ่ม "มั่น" ในแบบร่างภายหลัง