Переменные условия увеличения - звонки в стек «notify_one»?

В одном продюсерском/однопользовательском приложении с использованием потоков Boost, что произойдет, если поток производителя сделает более одного вызова cond_var.notify_one() до того, как потребительский поток вызвал cond_var.wait (блокировка ) ?

Будут ли дополнительные вызовы notify_one уложены в стек, так что каждый вызов .wait() будет соответствовать 1: 1 с помощью .notify_one() вызов?

EDIT A commonly quoted example for implementing a concurrent queue has these methods:

void push(Data const& data)
{
    boost::mutex::scoped_lock lock(the_mutex);
    the_queue.push(data);
    lock.unlock();
    the_condition_variable.notify_one();
}

void wait_and_pop(Data& popped_value)
{
    boost::mutex::scoped_lock lock(the_mutex);
    while(the_queue.empty())
    {
        the_condition_variable.wait(lock);
    }

    popped_value=the_queue.front();
    the_queue.pop();
}

Я использовал очень похожий код и испытывал некоторый нечетный рост памяти, который, по-видимому, объясняется потребительским потоком, не просыпающимся для каждого .notify_one() (потому что он все еще занят другой работой) и задался вопросом, может ли быть причиной «укладки».

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

3
nl ja de

2 ответы

Спецификация notify_one :

C ++ 11 30.5.1/7: Эффекты: если какие-либо потоки заблокированы в ожидании * this , разблокирует один из этих theads.

Таким образом, ответ отрицательный: вызовы notify_one и notify_all будут только запускать поток (ы), ожидающий в настоящее время, и не запоминаются позже.

UPDATE: Извините, я неправильно понял вопрос как std :: condition_variable . Неудивительно, что Boost более или менее идентичны:

Если какие-либо потоки в настоящее время заблокированы ждут * this в вызове wait или timed_wait ), разблокирует один из этих потоков.

Что касается вашего редактирования: если нет потока, ожидающего, когда кто-то вызовет push , то следующий поток для вызова pop не будет ждать вообще, так как the_queue не будет пустым. Поэтому нет необходимости в переменной состояния помнить, что она не должна ждать; эта информация хранится в управляемом состоянии, а не в переменной условия. Если потребитель не может идти в ногу с производителем, вам нужно либо ускорить потребление, либо замедлить производство; вы ничего не можете сделать с сигнальным механизмом, чтобы помочь с этим.

7
добавлено
спасибо за обновление - как вы говорите, второй раз вокруг .wait никогда не вызывается, потому что очередь не пуста. Doh!
добавлено автор Alnitak, источник

Короче: нет, он не складывается.

notify_one() has only effect if another thread is waiting on the cond_var. So if your consumer was waiting, the first notify_one() has unblocked the consumer. The second notify_one() has no effect, since no thread is waiting on the condition_variable

3
добавлено
pro.cxx
pro.cxx
3 049 участник(ов)

C/C++ chat 0. Простые вопросы, лабы и о IDE — в чат новичков @supapro 1. Не хамим, не переходим на личности, не вбрасываем утверждения без доказательств 2. No Ads, offtop, flood Объявления о вакансиях и евенты - в лс @AlexFails https://t.me/ProCxx/259155

supapro.cxx
supapro.cxx
1 925 участник(ов)

Чат для тех, кто немного знает C++, простые вопросы по реализации, синтаксису и ide – сюда, а для другого есть: /Главный чат по серьезным вопросам — @ProCxx /Чат по обсуждению всего — @fludpac

C++ Russia
C++ Russia
384 участник(ов)

Сообщество разработчиков C++ в Telegram.

cxx.Дискуссионная
cxx.Дискуссионная
298 участник(ов)

это не двач, общайтесь вежливо; разговор на почти любые темы; Не согласны с баном? В лс @AlexFails, @ivario

C++ для маленьких и тупых
C++ для маленьких и тупых
105 участник(ов)

Лоу левел (по среднему IQ участников) чатик ExtremeCode @extremecode Флудилка @extremecode_rest