Код: Выделить всё
struct X
{
int i;
std::string s;
};
std::atomic p;
std::atomic a;
void create_x()
{
X* x=new X;
x->i=42;
x->s="hello";
a.store(99,std::memory_order_relaxed); //1
p.store(x,std::memory_order_release); //2
}
void use_x()
{
X* x;
while(!(x=p.load(std::memory_order_consume))) //3
std::this_thread::sleep(std::chrono::microseconds(1));
assert(x->i==42); //4
assert(x->s=="hello"); // 5
assert(a.load(std::memory_order_relaxed)==99); // 6
}
int main()
{
std::thread t1(create_x);
std::thread t2(use_x);
t1.join();
t2.join();
}
Несмотря на то, что сохранение в 1 упорядочивается перед сохранением в p 2, и
сохранение в p помечается тегом Memory_order_release, загрузка p 3
помечается тегом Memory_order_consume. Это означает, что сохранение в p происходит только
до тех выражений, которые зависят от значения
, загруженного из p. Это означает, что утверждения элементов данных структуры
X (4 и 5) гарантированно не сработают, поскольку нагрузка
p несет зависимость от этих выражений через переменную x. С другой стороны, утверждение значения 6 может сработать, а может и не сработать;
эта операция не зависит от значения, загруженного из p, и поэтому
нет никакой гарантии относительно прочитанного значения. Это особенно
очевидно, потому что оно отмечено тегом Memory_order_relaxed.
Это объяснение имеет смысл, но когда я пытаюсь подумать об этом с точки зрения отношений «происходит до», определенных cppreference, я не могу прийти к такому же выводу:
- Между хранилищами 1 и «происходит до» существуют отношения «последовательность до» и «происходит до» 2
- Между 2 и 3 существует связь «упорядоченный порядок до» и «происходит перед потоком» между 2 и 3.
- Поскольку связь «происходит перед потоком» сочетается с связью «упорядоченный перед», сохранение 1 происходит перед загрузкой 3, и, следовательно, 1 происходит до загрузки 3.
- Нагрузка 3 последовательность-до загрузки 6 по порядку программы, следовательно 3 происходит-до 6
- Как мы пришли к выводу, 1 происходит-до 3 и 3 происходит-до 6, то по транзитивности 1 происходит-до 6
Подробнее здесь: https://stackoverflow.com/questions/792 ... er-consume
Мобильная версия