Параллельное программирование на С++ в действии. Практика разработки многопоточных программ | страница 26



типа >thread_guard, и в его деструкторе (2) происходит присоединение к потоку Это справедливо даже в том случае, когда выход из функции >f произошел в результате исключения внутри функции >do_something_in_current_thread.

Деструктор класса >thread_guard в листинге 2.3 сначала проверяет, что объект >std::thread находится в состоянии >joinable()(1) и, лишь если это так, вызывает >join()(2). Это существенно, потому что функцию >join() можно вызывать только один раз для данного потока, так что если он уже присоединился, то делать это вторично было бы ошибкой.

Копирующий конструктор и копирующий оператор присваивания помечены признаком >=delete(3), чтобы компилятор не генерировал их автоматически: копирование или присваивание такого объекта таит в себе опасность, поскольку время жизни копии может оказаться дольше, чем время жизни присоединяемого потока. Но раз эти функции объявлены как «удаленные», то любая попытка скопировать объект типа >thread_guard приведет к ошибке компиляции. Дополнительные сведения об удаленных функциях см. в приложении А, раздел А.2.

Если ждать завершения потока не требуется, то от проблемы безопасности относительно исключений можно вообще уйти, отсоединив поток. Тем самым связь потока с объектом >std::thread разрывается, и при уничтожении объекта >std::thread функция >std::terminate() не будет вызвана. Но отсоединенный поток по-прежнему работает — в фоновом режиме.

2.1.4. Запуск потоков в фоновом режиме

Вызов функции-члeнa >detach() объекта >std::thread оставляет поток работать в фоновом режиме, без прямых способов коммуникации с ним. Теперь ждать завершения потока не получится — после того как поток отсоединен, уже невозможно получить ссылающийся на него объект >std::thread, для которого можно было бы вызвать >join(). Отсоединенные потоки действительно работают в фоне: отныне ими владеет и управляет библиотека времени выполнения С++, которая обеспечит корректное освобождение связанных с потоком ресурсов при его завершении.

Отсоединенные потоки часто называют потоками-демонами по аналогии с процессами-демонами в UNIX, то есть с процессами, работающими в фоновом режиме и не имеющими явного интерфейса с пользователем. Обычно такие потоки работают в течение длительного времени, в том числе на протяжении всего времени жизни приложения. Они, например, могут следить за состоянием файловой системы, удалять неиспользуемые записи из кэша или оптимизировать структуры данных. С другой стороны, иногда отсоединенный поток применяется, когда существует какой-то другой способ узнать о его завершении или в случае, когда нужно запустить задачу и «забыть» о ней.