Предохранитель потока, эквивалентный предохранителю замка / уникальному замку


Стандартная библиотека предоставляет mutex класс, с возможностью вручную блокировать и разблокировать его:

std::mutex m;
m.lock();
// ...
m.unlock();
Однако библиотека, по-видимому, также признает, что общий случай-это просто заблокировать мьютекс в какой-то момент и разблокировать его при выходе из блока. Для этого он предоставляет std::lock_guard и еще std::unique_lock:
std::mutex m;
std::lock_guard<std::mutex> lock(m);
// ...

// Automatic unlock

Я думаю, что довольно распространенным шаблоном для потоков является создание одного (либо в виде переменной стека, либо в виде элемента), а затем join это раньше разрушая его :

std::thread t(foo);
// ...
t.join();

Кажется, легко написать thread_guard, который взял бы thread (или последовательность threads) и просто вызвал бы join на свое собственное уничтожение:

std::thread t(foo);
thread_guard<std::thread> g(t);
// ...
// Join automatically
  1. Есть ли такой класс стандартной библиотеки?

  2. Если нет, то есть ли какая-то причина избегать этого?

1 2

1 ответ:

Этот вопрос обсуждается в книге Скотта Мейера "современный эффективный c++"

Проблема заключается в том, что если бы было другое поведение по умолчанию (отсоединение или соединение), то было бы трудно найти ошибки, если вы забыли, что существует неявная операция. Таким образом, фактическое поведение по умолчанию при разрушении утверждает, если явно не присоединено или отделено. И никакого класса "охранников" там тоже нет по этой причине.

Если вы Всегда хотите присоединиться, то безопасно написать такой класс себе. Но когда кто-то использует его и хочет отделить, люди могут забыть, что деструктор неявно присоединится к нему. Так вот в чем риск при написании такой функции.

В качестве альтернативы вы можете использовать scope_guard boost или библиотеку folly (которую я лично предпочитаю больше) и объявить в начале явно свое намерение, и оно будет выполнено. Или вы можете написать основанный на политике класс" Guard", где вы должны явно указать, что вы хотите сделать при уничтожении.