Я пытаюсь понять значение происходит раньше в спецификации C++11 и, в частности, предполагает ли спецификация какое-либо неформальное понимание термина в дополнение к тому, что указано. Я работаю с проекта N3290.
Прямым аргументом в пользу того, что термин следует интерпретировать только в отношении самой спецификации, является то, что спецификация фактически говорит о собственном определении термина. Например, 1.10.6: «происходит до (как определено ниже)» или 1.10.11: «происходит до» отношения, определенного ниже.
С другой стороны, 1.10.12 гласит: «Оценка A происходит раньше, чем оценка B, если: …» Если бы это было определение «происходит раньше», я бы ожидал, что оно будет читаться как «если и только если." Таким образом, похоже, что спецификация определяет некоторые минимальные требования к отношению «происходит до того, как это произойдет», но оставляет его открытым для других факторов, которые могут включать некоторое неформальное представление о том, что означает этот термин, или могут включать формулировку в других частях спецификации.
Затем параграф 1.10.13 определяет видимый побочный эффект или нет? Это похоже на определение, потому что видимый побочный эффект выделен курсивом, но определение дано в терминах «происходит раньше», так что следует ли это в качестве альтернативы читать как дополнительное ограничение на «происходит до», учитывая интуитивное понятие видимого побочного эффекта? Другими словами, если B видит A, означает ли это, что A произошло до B (дальнейшее ограничение на определение «происходит до»), или это импликация предназначена только в другом направлении, а именно, что когда A происходит до B, то A должен быть видимый побочный эффект.
Вот конкретный пример (на основе этот вопрос, но здесь я просто пытаюсь понять, что происходит раньше, и в отношении C++, а не C, поскольку спецификация C++ кажется немного более ясной):
#include <atomic>
#include <cassert>
#include <thread>
using namespace std;
atomic<int> a;
atomic<int> b;
void
p1()
{
atomic_store_explicit(&a, 1, memory_order_relaxed); // 1
}
void
p2()
{
if (atomic_load_explicit(&a, memory_order_relaxed)) {
//atomic_thread_fence(memory_order_release);
atomic_store_explicit(&b, 1, memory_order_relaxed); // 2
}
}
void
p3()
{
int local = 1;
if (atomic_load_explicit(&b, memory_order_relaxed)) {
//atomic_thread_fence(memory_order_acquire);
local = atomic_load_explicit(&a, memory_order_relaxed); // 3
}
assert (local == 1);
}
int
main()
{
thread t1{p1}, t2{p2}, t3{p3};
t1.join();
t2.join();
t3.join();
}
Учитывая выполнение, в котором выполняется строка, отмеченная // 3
, требует ли спецификация, чтобы строка, отмеченная // 1
, выполнялась перед любой другой строкой в программе? Неформально строка // 1
является видимым побочным эффектом в строке // 2
, значит ли это, что // 1
произошло до // 2
, и в этом случае эквивалентный аргумент говорит, что // 2
произошло до // 3
, и утверждение не может быть ошибочным? По чисто внешним причинам (а именно, понимание того, как работает NUMA, и предположение, что комитет по языку хотел оставить место для упрощенной оптимизации порядка памяти), я думаю, что это происходит до того, как условия, вероятно, не выполняются, и утверждение может потерпеть неудачу.
Мой следующий вопрос: влияет ли раскомментирование заборов в p2
и p3
на то, происходит ли // 1
перед любым другим утверждением? Здесь я подозреваю, что если до соединения между // 1
и кодом в других потоках уже не произошло что-то, раскомментирование заборов в других потоках не изменит этого. (Хотя это означало бы, что нет способа предотвратить ошибку утверждения, используя только заборы.)
В качестве последнего замечания, у меня есть эта проблема, когда спецификация содержит абстрактный язык об A, B, M, X, Y, который, кажется, подразумевает одну вещь, пока я на самом деле не пойду и не попытаюсь сопоставить A, B и т. д. с операторами и переменными. в моем коде, и в этот момент это, кажется, подразумевает что-то еще. Поэтому я надеюсь получить ответ, который действительно связывает спецификацию C++ с кодом примера, что может показаться чрезмерно педантичным. (Например, простое утверждение, что // 1
происходит перед // 3
из-за когерентности чтения-чтения, не отвечает на мой вопрос — мой вопрос больше о том, как конкретное определение когерентности чтения-чтения в спецификации С++ 11 применяется к моему конкретному примеру кода. , и о том, на каком основании предполагается, что определение когерентности чтения-чтения управляет определением «происходит раньше», а не наоборот.)
if
, а неif and only if
. См. 1.10/4 конфликт, 1.10/9 несет зависимость, 1.10/10 в зависимости от порядка и так далее. - person Igor Tandetnik   schedule 13.12.2015