5

Spurious wakup допускается различными платформами. Для того, чтобы противостоять этому, мы пишем ниже механизма циклов, в:Как условие condition_variable :: wait_for() связано с ложными пробуждениями?

while(ContinueWaiting()) 
    cv.wait(lock); // cv is a `std::conditional_variable` object 

То же самое понятно для conditional_variable::wait_until().
Но посмотрите на пример ниже:

const auto duration = Returns_10_seconds(); 
while(!Predicate()) 
    cv.wait_for(lock, duration); 

Представьте, что паразитный пробуждение произошло на 1 секунду. Таймаут еще не достигнут.
Ожидает ли еще 10 секунд? Это приведет к бесконечному циклу, который, я уверен, не должен произойти. Из исходного кода, внутри wait_for() звонки wait_until().

Я хочу понять, как работает wait_for() с поддельными пробуждениями?

+2

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

+0

@MaiLongdong, предикат используется для противодействия таким пробуждениям. Даже 'wait_for()', если он отлично работает на моей платформе, не гарантирует, что он будет работать повсюду, потому что ложные wakeups зависят от платформы. – iammilind

+1

Если вы не хотите 'wait_for' 10 секунд использовать' wait_until'' now() '+ 10 секунд :-) –

ответ

4

Я хочу понять, как же wait_for() сделки с ложные пробуждения?

Это не так.

Эта функция обычно используется в ситуации, когда вы просыпаетесь ложно, вы все равно хотите сделать какую-то другую работу. И если вы не проснетесь ложно, вы хотите заставить «поддельные» пробуждения к тому времени, когда duration прошло. Это означает, что он обычно не используется в цикле, как вы показываете, точно по причинам, которые вы указываете. То есть таймауты и ложные пробуждения обрабатываются тождественно.

Теперь вам может быть интересно, что делает предикатная версия, поскольку она подразумевает цикл?

template <class Rep, class Period, class Predicate> 
bool 
wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, 
     Predicate pred); 

Это определяется иметь те же эффекты, как:

return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred)); 

wait_until изменения делает отличающие между паразитных бодрствование взлетов и тайм-ауты. Он делает это с помощью такой петли:

while (!pred()) 
    if (wait_until(lock, abs_time) == cv_status::timeout) 
     return pred(); 
return true; 
2

Вот что стандарт должен сказать о паразитных пробуждениями:

30,5 переменные условия [thread.condition]

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

...

10 Примечание: Ответственность пользователя, чтобы гарантировать, что ожидающие потоки не ошибочно полагают, что нить закончила, если они опыта паразитных пробуждения.

Из формулировки кажется довольно понятным, что ответственность за обращение с ложными пробуждениями лежит на пользователе.

1

            
 
  
              
    const auto duration = Returns_10_seconds(); 
    while(cv.wait_for(lock, duration) == std::cv_status::timeout); 

            
 

Это, безусловно, неправильно, что нужно делать, и, таким образом, не имеет смысла обсуждать, как это исправить в случае ложных пробуждений, поскольку нарушаются даже в случае обычных пробуждений, поскольку условие ожидания не пересматривается после возвращения из ожидания.

const auto duration = Returns_10_seconds(); 
while(!Predicate()) 
    cv.wait_for(lock, duration); 

Даже после редактирования, ответ остается прежний: вы не можете справиться с «паразитным пробуждением», потому что вы не можете действительно сказать причине пробуждения - это вполне может быть полностью законное пробуждение из-за вызова condition_variable::notifyXXX до истечения таймаута.

Прежде всего обратите внимание, что вы не можете отличить пробуждение, вызванное вызовом condition_variable::notifyXXX, и пробуждение, вызванное, например, сигналом POSIX [1]. Во-вторых, даже если сигналы POSIX не вызывают беспокойства, поток ожидания все равно должен пересмотреть условие, так как это возможно, чтобы условие изменилось между временем, когда сигнализация состояния сигнализируется, а ожидающий поток возвращается из условия ожидания.

То, что вам действительно нужно делать, это обработать особым образом, не просыпаясь перед таймаутом, но просыпаясь из-за таймаута.И это полностью зависит от причин, по которым необходимо иметь тайм-аут, в первую очередь, то есть на специфику области приложений/проблем.

[1], если ждать переменного состояния прерываются сигналом, после выполнения обработчика сигнала потока разрешен либо возобновить ожидание или возвращение

+0

Ваш первый пара прав, на самом деле я написал его в текущем виде, когда я разместил. После этого я изменил его на то, что есть [cplusplus.com] (http://www.cplusplus.com/reference/condition_variable/condition_variable/wait_for/). Вы можете отредактировать ответ в соответствии с текущим состоянием вопроса. – iammilind

 Смежные вопросы

  • Нет связанных вопросов^_^