Почему нельзя "присоединить" поток std::thread дважды?
Скажем, мы хотим дожидаться одного потока в нескольких других, но по идее не можем этого сделать благодаря такому ограничению (из книги C++ Concurrency in Action):
При вызове join() очищается вся ассоциированная с потоком память, так что объект std::thread более не связан с завершившимся потоком – он вообще не связан ни с каким потоком. Это значит, что для каждого потока вызвать функцию join() можно только один раз; после первого вызова объект std::thread уже не допускает присоединения, и функция joinable() возвращает false.
Я не понимаю, что значит "очищается вся ассоциированная с потоком память". Ведь у каждого потока свой стек по идее. Они образуют один поток? Один стек накидывается поверх другого, или как?
Ответы (1 шт):
Есть поток, реализованный на OS API. Есть объект thread, который этим потоком управляет. join ждет, когда поток закончится. Это происходит, когда функция потока выходит. Тогда OS освобождает все ресурсы, выделенные для потока. Главный ресурс это стек, он освобождается.
Кстати, join не останавливает поток, а просто ждет, когда он сам закончится.
После этого объект thread очищает все свои переменные, связанные с этим, уже не существующим, потоком. Прежде всего, обнуляет thread handle. То есть, объект thread переходит в состояние, когда он ни с каким потоком не связан. В этом состоянии вызов join не допускается.
Хотите дождаться окончания потока, не вызывая join, используйте condition_variable, устанавливайте его перед выходом функции потока. Или возьмите thread native handle и ждите на нем средствами OS (но это не cross-platform).