Здравствуйте, _NN_, Вы писали:
_NN>Всплыл такой вопрос, положим у нас есть код вида:
_NN>_NN>Tool tool{};
_NN>std::thread toolRunner([]() {
_NN> printf("Starting tool");
_NN>});
_NN>
_NN>Есть ли у нас гарантии от компилятора и от процессора, что toolRunner будет создан после того как будет создан tool ?
В этом вопросе самое важное слово "после". Вот в каком смысле "после"? Как вы это "после" понимаете, если учесть, что от этого "после" ничего не зависит и нет никаких способов, в некотором смысле физических, изнутри потока выполнения инструкций процессора узнать, что произошло раньше, а что позже?
_NN>Насколько я понимаю, компилятор вправе переупорядочить создание если нет видимого эффекта.
да.
_NN>В данном случае нет разницы что будет создано первым, а значит можно поменять местами в целях оптимизации.
да.
_NN>Исходя из этого напрашивается вывод, каждое создание std::thread должно быть ограничено барьером, чтобы запретить переупорядочивание как компилятором так и процессором и получить нужный нам порядок.
Возможно. Это зависит от того, какое поведение вы хотите запрограммировать.
_NN>Какие мысли ?
У меня есть подозрение, что вы не разделяете создание объекта toolRunner и запуск на выполнение — это две разные операции. Сначала создаётся объект toolRunner и продолжается выполнение основного потока, потом, параллельно, возможно намного позже, будет запущена нитка для toolRunner и ещё позже будет вызвана функция printf.
Более того, если убрать нитку, то ничего не поменяется:
Tool tool{};
printf("Starting tool");
Если конструктор Tool не имеет побочных эффектов, то нет гарантии, что вызов функции
printf("Starting tool"); будет произведён
после (что бы это не значило) создания объекта tool. Вообще говоря стандартом не запрещается параллельное выполнение этого кода, скажем, на двух разных процессорах: на одном создание объекта tool, а на втором выполнение функции printf.