Почему библиотека Boost использует переменную m_generation в реализации барьера потока?

Библиотека boost (до стандарта C ++ 11), предлагала поддержку потоков. В рамках своей поддержки он также предлагает реализацию «барьера», простого класса, который позволяет синхронизацию. Процитировать повысить сайт:

«Барьер — это простая концепция. Также известная как рандеву, это точка синхронизации между несколькими потоками. Барьер настроен для определенного числа потоков (n), и, когда потоки достигают барьера, они должны ждать, пока все n потоков Как только n-й поток достиг барьера, все ожидающие потоки могут продолжаться, и барьер сбрасывается. «

Реализация основной функции барьера (ожидания), начиная с Boost 1.54, показана ниже:

bool wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;

if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}

while (gen == m_generation)
m_cond.wait(lock);
return false;
}

Видно, что барьер можно использовать многократно: после постройки его не нужно разрушать после первого использования.

Мой вопрос сейчас: для чего нужна переменная m_generation? Я предполагаю, что у авторов библиотеки повышения была причина включить это. Он увеличивается каждый раз, когда барьер сбрасывается / готов к повторному использованию, но с какой целью? Это приватная переменная, поэтому она не может быть прочитана извне. Эту же проблему можно легко решить с помощью простой внутренней переменной bool внутри функции wait () без использования закрытой переменной класса.

2

Решение

В двух словах, m_generation необходимо иметь дело с ложные пробуждения.

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

  • Когда есть m_threshold потоков, которые достигли барьера, его номер генерации увеличен, и переменная условия сигнализируется. Это заставляет ожидающие потоки (то есть те, которые достигли барьера ранее) просыпаться от m_cond.wait(lock),

  • Теперь ожидающие потоки могут проснуться от m_cond.wait(lock) за другие причины. Это где m_generation приходит: если это изменилось, то барьер был сброшен, и поток может продолжаться. Если m_generation все еще содержит то же значение, поток должен вернуться в m_cond.wait(lock),

Наличие автоматической переменной внутри wait() не будет достигать этого, так как каждый поток будет иметь свой собственный экземпляр.

5

Другие решения