Произвольное количество потоков (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 шт):

Автор решения: KoVadim

Динамический массив при выходе за пределы видимости не будет просто так вызывать деструкторы своих элементов. А если деструкторы никто не вызывает, то ничего не останавливает код "бежать дальше". А дальше только "на выход". И все потоки просто не успевают отработать. И достаточно вызвать их вручную

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});
→ Ссылка