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], если ждать переменного состояния прерываются сигналом, после выполнения обработчика сигнала потока разрешен либо возобновить ожидание или возвращение
Это не так. Вы должны либо проверить это самостоятельно, либо использовать перегрузку, которая делает это за вас (тот, который берет предикат). –
@MaiLongdong, предикат используется для противодействия таким пробуждениям. Даже 'wait_for()', если он отлично работает на моей платформе, не гарантирует, что он будет работать повсюду, потому что ложные wakeups зависят от платформы. – iammilind
Если вы не хотите 'wait_for' 10 секунд использовать' wait_until'' now() '+ 10 секунд :-) –