Словосполучення "сильно буває раніше" вживається кілька разів у проекті стандарту C ++.
Наприклад: Припинення [basic.start.term] / 5
Якщо завершення ініціалізації об'єкта зі статичною тривалістю зберігання сильно відбувається перед викликом до std :: atexit (див. [Support.start.term]), виклик до функції, переданої в std :: atexit секвенується перед викликом деструктора для об'єкта. Якщо виклик std :: atexit сильно відбувається до завершення ініціалізації об'єкта зі статичною тривалістю зберігання, виклик деструктора для об'єкта секвенується перед викликом функції, переданої std :: atexit . Якщо виклик std :: atexit сильно відбувається перед іншим викликом std :: atexit, виклик функції, переданої другому виклику std :: atexit, послідовно проходить перед тим, як виклик функції перейшов до перший std :: atexit call.
І визначено у перегонах даних [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 така, що A сильно відбувається перед B, а B сильно відбувається перед D.
[Примітка: Неофіційно, якщо A сильно трапляється перед B, то, схоже, A оцінюється перед B у всіх контекстах. Сильно відбувається, перш ніж виключати споживачі. - кінцева примітка]
Чому було введено "сильно сталося раніше"? Інтуїтивно, в чому його відмінність та відношення до «буває раніше»?
Що означає "А, як видається, оцінюється перед B у всіх контекстах" у примітці?
(Зауважте: мотивацією до цього питання є коментарі Пітера Кордеса під цією відповіддю .)
Додатковий проект стандартної цитати (спасибі Пітеру Кордесу)
Порядок і послідовність [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 - операція пам'яті_order :: seq_cst і B відбувається перед пам'яткою_порядок :: seq_cst огорожею Y, то A передує Y в S; і
(4.3) якщо огорожа memory_order :: seq_cst X відбувається перед тим, як A і B є операцією memory_order :: seq_cst, то X передує B у S; і
(4.4) якщо огорожа пам'яті :: seq_cst X ставиться до того, як А і В трапляється перед пам'яткою_порядок :: seq_cst паркан Y, то X передує Y у S
atexit()
один потік і exit()
інший, для ініціалізаторів недостатньо лише залежність на основі споживання лише тому, що результати відрізняються від того, якщо exit()
викликали один потік. Старше відповідь мого стурбований ця різниця.
exit()
. Будь-який потік може знищити всю програму, вийшовши, або основний потік може вийти з return
-ing. Це призводить до виклику atexit()
обробників і загибелі всіх потоків, що б вони не робили.
seq_cst
, в атоміці 31.4 Порядок та послідовність: 4 . Це не стосується стандарту C ++ 17 n4659 , де 32.4 - 3 визначає існування єдиного загального порядку seq_cst ops, що відповідає порядку "відбувається раніше" та замовленням на модифікацію для всіх постраждалих місць ; "сильно" було додано в більш пізньому проекті.