Здравствуйте, _NN_, Вы писали:
_NN>_NN>int i{ 10 };
_NN>std::thread t( [&i] { printf("%d", i); } );
_NN>
запуск потока это всегда барьер памяти. Поэтому у тебя гарантировано инициализация i числом 10 пройдет ДО запуска потока
Здравствуйте, CRT, Вы писали:
CRT> как компилятор может сначала вызвать b() перед a()?
CRT> у меня это в голове не укладывается. Такого быть не должно.
Может, естественно, если компилятор знает, что это не влияет на наблюдаемое поведение.
Вот такая штука есть:
https://en.wikipedia.org/wiki/Memory_model_(programming)
Тонкий момент, что "наблюдаемое поведение" — в пределах одного треда. Если ты будешь наблюдать это поведение из другого треда без должной синхронизации, то можно будет увидеть бардак.
Другое дело, что в начальном примере был запуск треда, который вроде как по современным стандартам (The memory model was then included in the next C++ and C standards, C++11 and C11) должен создавать барьер.
Здравствуйте, ·, Вы писали:
CRT>> как компилятор может сначала вызвать b() перед a()?
CRT>> у меня это в голове не укладывается. Такого быть не должно.
·>Может, естественно, если компилятор знает, что это не влияет на наблюдаемое поведение.
чтобы это знать, компилятор должен учитывать всё что делается внутри a() и b() и так же внутри тех функций которые эти a() и b() в свою очередь вызывают и далее по цепочке. Что-то я сомневаюсь что компилятор копает
так глубоко. Хотя кто их знает...
·>Другое дело, что в начальном примере был запуск треда, который вроде как по современным стандартам (The memory model was then included in the next C++ and C standards, C++11 and C11) должен создавать барьер.
это я знаю.
вообще автор задал вопрос неоднозначно
Есть ли у нас гарантии от компилятора и от процессора, что toolRunner будет создан после того как будет создан tool ?
Что он имел в виду: создание объекта std::thread toolRunner или начало работы потока который представляется этим объектом?
Это ж не одно и то же. Конструктор объекта toolRunner и его функция потока выполняются в разных потоках.
Если считать что компилятор может конструкторы вызывать не в том порядке в котором они указаны в коде, то объект toolRunner может быть создан раньше чем tool. Но тогда получается что барьер памяти будет не работать, потому что барьер то как раз должен завершить все операции записи...
Короче, однозначно что tool уже будет проинициализирован перед запуском потока toolRunner .
Здравствуйте, CRT, Вы писали:
CRT> CRT>> как компилятор может сначала вызвать b() перед a()?
CRT> CRT>> у меня это в голове не укладывается. Такого быть не должно.
CRT> ·>Может, естественно, если компилятор знает, что это не влияет на наблюдаемое поведение.
CRT> чтобы это знать, компилятор должен учитывать всё что делается внутри a() и b() и так же внутри тех функций которые эти a() и b() в свою очередь вызывают и далее по цепочке. Что-то я сомневаюсь что компилятор копает так глубоко. Хотя кто их знает...
Ну во-первых, а кто сказал, что a() и b() это обязано быть чем-то глубоким.
А во-вторых, это работа такая у оптимизатора компилятора, стараться копать поглубже.
CRT> ·>Другое дело, что в начальном примере был запуск треда, который вроде как по современным стандартам (The memory model was then included in the next C++ and C standards, C++11 and C11) должен создавать барьер.
CRT> это я знаю.
CRT> вообще автор задал вопрос неоднозначно
Ну да... Тонкости в формулировке правильного вопроса есть.
CRT> Короче, однозначно что tool будет проинициализирован перед запуском потока.
+1.
Интересно как оно работало в старых версиях языка... Полагаю это было на уровне OS API.