Concurrency and parallelism
CP.25
Предпочитайте `gsl::joining_thread` вместо `std::thread`
Причина
joining_thread — это потока, которая присоединяется в конце своей области видимости. Отделённые потока трудно контролировать. Сложнее обеспечить отсутствие ошибок в отделённых потока (и потенциально отделённых потока).
Пример, плохой
void f() { std::cout << "Hello "; }
struct F {
void operator()() const { std::cout << "parallel world "; }
};
int main()
{
std::thread t1{f}; // f() выполняется в отдельной потоке
std::thread t2{F()}; // F()() выполняется в отдельной потоке
} // заметьте ошибки
Пример
void f() { std::cout << "Hello "; }
struct F {
void operator()() const { std::cout << "parallel world "; }
};
int main()
{
std::thread t1{f}; // f() выполняется в отдельной потоке
std::thread t2{F()}; // F()() выполняется в отдельной потоке
t1.join();
t2.join();
} // осталась одна плохая ошибка
Примечание
Сделайте "бессмертные потока" глобальными, поместите их в объемлющую область видимости или поместите их в свободное хранилище вместо detach(). Не detach.
Примечание
Из-за старого кода и библиотек третьих сторон, использующих std::thread, это правило может быть сложно внедрить.
Применение
Отмечайте использование std::thread:
- Предложите использование
gsl::joining_threadили C++20std::jthread. - Предложите "экспорт владения" в объемлющую область видимости, если она отделяет.
- Предупредите, если не очевидно, присоединяется ли поток или отделяется.