Cụm từ "mạnh mẽ xảy ra trước đây" được sử dụng nhiều lần trong tiêu chuẩn dự thảo C ++.
Ví dụ: Chấm dứt [basic.start.term] / 5
Nếu việc hoàn thành khởi tạo một đối tượng có thời lượng lưu trữ tĩnh xảy ra mạnh mẽ trước khi gọi đến std :: atexit (xem, [support.start.term]), cuộc gọi đến hàm được chuyển đến std :: atexit được giải trình tự trước khi gọi hàm hủy cho đối tượng. Nếu một lệnh gọi std :: atexit xảy ra mạnh mẽ trước khi hoàn thành việc khởi tạo một đối tượng có thời lượng lưu trữ tĩnh, thì lệnh gọi hàm hủy đối tượng được sắp xếp theo trình tự trước khi lệnh gọi đến hàm được chuyển đến std :: atexit . Nếu một cuộc gọi đến std :: atexit xảy ra mạnh mẽ trước một cuộc gọi khác đến std :: atexit, cuộc gọi đến chức năng được chuyển đến cuộc gọi std :: atexit thứ hai được thực hiện trước khi cuộc gọi đến chức năng được chuyển đến đầu tiên std :: cuộc gọi atexit.
Và được xác định trong các cuộc đua dữ liệu [intro.races] / 12
Đánh giá A xảy ra mạnh mẽ trước khi đánh giá D nếu, hoặc
(12.1) A được giải trình tự trước D, hoặc
(12.2) A đồng bộ hóa với D và cả A và D là các hoạt động nguyên tử nhất quán liên tục ([nguyên tử.order]), hoặc
(12.3) có các đánh giá B và C sao cho A được giải trình tự trước B, B đơn giản xảy ra trước C và C được giải trình tự trước D, hoặc
(12.4) có đánh giá B sao cho A xảy ra mạnh trước B và B mạnh xảy ra trước D.
[Lưu ý: Không chính thức, nếu A xảy ra mạnh mẽ trước B, thì A dường như được đánh giá trước B trong tất cả các bối cảnh. Mạnh mẽ xảy ra trước khi loại trừ hoạt động tiêu thụ. - lưu ý cuối]
Tại sao "mạnh mẽ xảy ra trước khi" được giới thiệu? Theo trực giác, sự khác biệt và mối quan hệ của nó với "xảy ra trước" là gì?
"A dường như được đánh giá trước B trong tất cả các bối cảnh" trong ghi chú có nghĩa là gì?
(Lưu ý: động lực cho câu hỏi này là ý kiến của Peter Cordes dưới câu trả lời này .)
Dự thảo trích dẫn tiêu chuẩn bổ sung (nhờ Peter Cordes)
Thứ tự và tính nhất quán [nguyên tử.order] / 4
Có một tổng đơn hàng S trên tất cả các hoạt động memory_order :: seq_cst, bao gồm hàng rào, đáp ứng các ràng buộc sau. Đầu tiên, nếu A và B là các hoạt động memory_order :: seq_cst và A xảy ra mạnh mẽ trước B, thì A đứng trước B ở S. Thứ hai, với mọi cặp thao tác nguyên tử A và B trên một đối tượng M, trong đó A được sắp xếp theo thứ tự trước B, bốn điều kiện sau được yêu cầu phải được thỏa mãn bởi S:
(4.1) nếu A và B đều là các hoạt động memory_order :: seq_cst, thì A đứng trước B trong S; và
(4.2) nếu A là một hoạt động memory_order :: seq_cst và B xảy ra trước một memory_order :: seq_cst hàng rào Y, thì A đi trước Y trong S; và
(4.3) nếu một memory_order :: seq_cst fence X xảy ra trước A và B là một hoạt động memory_order :: seq_cst, thì X đi trước B trong S; và
(4.4) nếu bộ nhớ_order :: seq_cst hàng rào X xảy ra trước khi A và B xảy ra trước bộ nhớ_order :: seq_cst hàng rào Y, thì X đi trước Y ở S.
atexit()
trong một luồng và trong một luồng exit()
khác, thì việc khởi tạo chỉ mang một phụ thuộc dựa trên tiêu dùng là không đủ vì kết quả sau đó khác với nếu exit()
được gọi bởi cùng một luồng. Một câu trả lời cũ hơn của tôi liên quan đến sự khác biệt này.
exit()
. Bất kỳ luồng nào cũng có thể giết toàn bộ chương trình bằng cách thoát hoặc luồng chính có thể thoát bằng cách return
-ing. Nó dẫn đến việc kêu gọi atexit()
xử lý và cái chết của tất cả các chủ đề bất cứ điều gì họ đang làm.
seq_cst
, trong Nguyên tắc 31.4 Thứ tự và tính nhất quán: 4 . Điều đó không có trong tiêu chuẩn C ++ 17 n4659 , trong đó 32.4 - 3 xác định sự tồn tại của một đơn đặt hàng seq_cst phù hợp với các xảy ra trước khi đặt hàng và sửa đổi lệnh cho tất cả các vị trí bị ảnh hưởng ; "mạnh mẽ" đã được thêm vào trong một dự thảo sau này.