Подтвердить что ты не робот

В чем разница между std:: condition_variable:: wait_for и std:: condition_variable:: wait_until?

Ссылка которую я использую, объясняет следующее следующим образом:

  • wait_for "блокирует текущий поток до тех пор, пока не будет вызвана переменная условия или после указанной продолжительности таймаута

  • wait_until "блокирует текущий поток до тех пор, пока переменная условия не проснется или пока не будет достигнута заданная точка времени.

В чем разница? Будет ли wait_until вращаться так, чтобы поток мог продолжать точно (более или менее), когда он сигнализируется, тогда как wait_for просто добавляет поток обратно в планирование в этой точке?

4b9b3361

Ответ 1

Разница заключается в том, как представлена ​​продолжительность ожидания: wait_for принимает относительное время ( "дождитесь до 10 секунд" ), тогда как wait_until занимает абсолютное время ( "подождите до 30 октября 30 октября, 2012" ).

Сравните объявления параметров времени:

// wait_for:
const std::chrono::duration<Rep, Period>& rel_time

// wait_until:
const std::chrono::time_point<Clock, Duration>& abs_time

Ответ 2

Ваш вопрос и другие ответы все повторили разницу; что wait_for ожидает определенное количество времени, а wait_until ждет до определенного момента времени, но последствия не прописаны.

A time_point имеет связанные часы, и это время используется для определения того, пришло ли подходящее время. Это означает, что настройки часов учитываются функцией wait_until. wait_until(..., system_clock::now() + std::chrono::seconds(10)) может оказаться в ожидании часа и 10 секунд, если часы будут отрегулированы на час до того, как ожидание закончится.

Продолжительность не имеет связанных часов, поэтому wait_for выбирает собственные часы. Стандарт указывает, что он использует std:: stable_clock, который не может быть скорректирован и продвигается с постоянной скоростью относительно реального времени. Это означает, что wait_for будет ожидать указанное время независимо от любых настроек, сделанных для любых часов. wait_for(..., std::chrono::seconds(10)) гарантированно будет ждать 10 секунд (+ некоторое время для реализации и проблемы с расписанием).

Нет никакой разницы в том, что касается спиннинга против спящего потока; как указано wait_for, чтобы вести себя так, как если бы он назывался wait_until с steady_clock::now() + duration.


Здесь часть стандарта, где это указано:

[thread.req.timing] 30.2.4/2-4

2 Реализации обязательно имеют некоторую задержку в возвращении от тайм-аута. Любые накладные расходы в ответе на прерывание, возврат функции, и планирование приводит к задержке "качества реализации", выраженной как продолжительность D i. В идеале эта задержка будет равна нулю. Кроме того, любое утверждение для ресурсов процессора и памяти вызывает задержка "качество управления", выраженная как продолжительность D m. Длительность задержки может варьироваться от тайм-аута до тайм-аута, но во всех случаях короче, лучше.

3 Функции-члены, имена которых заканчиваются на _for, принимают аргумент, указывающий продолжительность. Эти функции производят относительные тайм-ауты. Реализации должны использовать устойчивые часы для измерения времени для этих функций. Учитывая аргумент продолжительности D t, длительность тайм-аута в режиме реального времени равна D t D > D i   D m.

4 Функции-члены, имена которых заканчиваются на _until, принимают аргумент, определяющий момент времени. Эти функции производят абсолютную тайм-ауты. Реализации должны использовать часы, указанные во времени чтобы измерить время для этих функций. Учитывая часовой момент времени аргумент C t, часовой момент времени возврата от таймаута должен быть C t + D i + D m, когда часы не настроены во время таймаута. Если часы настраиваются на время C a во время таймаута, поведение должен быть следующим:
            - если C a > C t, функция ожидания должна разбудить как можно скорее, т.е. C a + D i + D m, поскольку тайм-аут уже доволен. [Примечание: эта спецификация может привести к общей продолжительности от ожиданий, уменьшающихся при измерении относительно постоянных часов. -end note ]

      - если C a <= C t, функция ожидания не должна заканчиваться до тех пор, пока Clock::now() возвращает время C n >= C t, т.е. пробуждение при C t + D i + D <югу > мсуб > . [ Примечание. Когда часы отрегулированы в обратном направлении, эта спецификация может приводят к увеличению общей продолжительности ожидания при измерении против постоянных часов. Когда часы отрегулированы вперед, это спецификация может привести к общему увеличению продолжительности ожидания при измерении на устойчивые часы. -end note]

Реализация возвращается с такого таймаута в любой момент времени с указанного времени выше, до момента, когда он вернется с установочного тайм-аута на разницу между C t и временной точкой вызова _until. [Примечание. Реализации должны уменьшать продолжительность ожидания, когда часы корректируются вперед. -end note]

Ответ 3

  • wait_for будет ждать определенное количество времени. Например, подождите две секунды.
  • wait_until будет ждать некоторое время. Он будет, например, ждать до 23 июля 2013 года 11:22:34 вечера. достигается на часах.

Ответ 4

Вот одно важное различие в их использовании, как объяснено в книге Энтони Уильямса книга:

Рассмотрим этот пример, когда переменная состояния ожидает тайм-аута:

std::condition_variable cv;
bool done;
std::mutex m;

bool wait_loop()
{
    auto const timeout= std::chrono::steady_clock::now()+
    std::chrono::milliseconds(500);
    std::unique_lock<std::mutex> lk(m);
    while(!done)
    {
       if(cv.wait_until(lk,timeout)==std::cv_status::timeout)
          break;
    }
    return done;
}

Это рекомендуемый способ ожидания переменных условия с если вы не передадите предикат ожиданию. Сюда, общая длина цикла ограничена. Как вы видели в разделе 4.1.1, вам нужно зацикливать при использовании переменных условия, если вы не проходите в предикате, чтобы обрабатывать ложные пробуждения. Если вы используете wait_for() в цикле, вы можете оказаться в ожидании почти полной длины времени до ложного следа, а в следующий раз через ожидание время снова начинается. Это может повторяться любое количество раз, общее время ожидания неограниченное.

IMO, это один из таких сценариев, где wait_for не может легко заменить wait_until из-за его перенасыщения.