Произвольное количество потоков (jthread)
Требуется создать произвольное количество jthread-потоков. Определяя их количество во время работы программы.
Нашел множество подобных пример:
void spawnThreads(int n) {
jthread threads[n];
for (int i = 0; i < n; i++)
{
threads[i] = jthread(foo, i);
}
}
Они оказались заведомо не рабочими, т.к cpp запрещает создавать массивы не определенного размера. После чего я использовал динамический массив, заменив первую строку на:
jthread* threads = new jthread[n]{};
Теперь, потоки запускаются но программа не дожидается их выполнения, просто закрываясь.
Если б это были thread, такое поведение было бы ожидаемым из-за отсутствия thread#.join() в коде. Но jthread не требуют операции join() и я в как новичок в замешательстве.
Ответы (1 шт):
Динамический массив при выходе за пределы видимости не будет просто так вызывать деструкторы своих элементов. А если деструкторы никто не вызывает, то ничего не останавливает код "бежать дальше". А дальше только "на выход". И все потоки просто не успевают отработать. И достаточно вызвать их вручную
void spawnThreads(int n)
{
std::jthread* threads = new std::jthread[n]{};
for (int i = 0; i < n; i++)
{
threads[i] = std::jthread(foo, i);
}
delete[] threads; // ключевая строка!!!!
}
и вот этот delete[] в конце вызовет деструкторы и по факту вызовет join.
т.к cpp запрещает создавать массивы не определенного размера.
вот не знаю, почему, но это очень очень популярная тема. А когда говоришь "вот есть std::vector - все почему то ворочают носом и говорят "ну это же не с++, это же библиотека". Но нет, STL это и есть часть языка. Просто ее аккуратно отделили. Поэтому, std::vector, std::list и десятки других классов - это и есть с++, а не "какая то левая библиотека, написанная Степановым".
И теперь код стает простеньким и красивым.
void spawnThreads3(int n)
{
std::vector<std::jthread> th;
for (int i = 0; i < 10; i++) {
th.emplace_back(foo, i);
}
}
я применил emplace_back для красоты:) Но можно было бы и так
th.push_back(std::jthread{foo, i});