Namespaces
Variants

std::condition_variable:: wait_until

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
template < class Clock, class Duration >

std:: cv_status
wait_until ( std:: unique_lock < std:: mutex > & lock,

const std:: chrono :: time_point < Clock, Duration > & abs_time ) ;
(1) (начиная с C++11)
template < class Clock, class Duration, class Predicate >

bool wait_until ( std:: unique_lock < std:: mutex > & lock,
const std:: chrono :: time_point < Clock, Duration > & abs_time,

Predicate pred ) ;
(2) (начиная с C++11)

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

1) Атомарно вызывает lock. unlock ( ) и блокируется на * this .
Поток будет разблокирован, когда notify_all() или notify_one() будет выполнен, или когда будет достигнуто время abs_time . Также он может быть разблокирован ложным пробуждением.
При разблокировке вызывает lock. lock ( ) (возможно блокируясь на блокировке), затем возвращает управление.
2) Эквивалентно while ( ! pred ( ) )
if ( wait_until ( lock, abs_time ) == std:: cv_status :: timeout )
return pred ( ) ;
return true ;
.
Эта перегрузка может использоваться для игнорирования ложных пробуждений при ожидании выполнения определенного условия.

Сразу после того, как wait_until возвращает управление, lock. owns_lock ( ) имеет значение true , и lock. mutex ( ) заблокирован вызывающим потоком. Если эти постусловия не могут быть выполнены [1] , вызывается std::terminate .

Если выполняется любое из следующих условий, поведение является неопределённым:

  • lock. owns_lock ( ) равно false .
  • lock. mutex ( ) не заблокирован вызывающим потоком.
  • Если другие потоки также ожидают на * this , lock. mutex ( ) отличается от мьютекса, разблокируемого функциями ожидания ( wait , wait_for и wait_until ), вызванными на * this этими потоками.
  1. Это может произойти, если повторная блокировка мьютекса вызывает исключение.

Содержание

Параметры

lock - блокировка, которая должна быть захвачена вызывающим потоком
abs_time - момент времени, когда ожидание истекает
pred - предикат для проверки возможности завершения ожидания
Требования к типам
-
Predicate должен удовлетворять требованиям FunctionObject .
-
pred ( ) должно быть валидным выражением, а его тип и категория значения должны удовлетворять требованиям BooleanTestable .

Возвращаемое значение

1) std:: cv_status :: timeout если abs_time был достигнут, иначе std:: cv_status :: no_timeout .
2) Последний результат pred ( ) перед возвратом к вызывающей стороне.

Исключения

1) Исключения, связанные с таймаутом.
2) Исключения, связанные с таймаутом, и любые исключения, выбрасываемые pred .

Примечания

Стандарт рекомендует использовать часы, связанные с abs_time для измерения времени; эти часы не обязаны быть монотонными. Не даётся никаких гарантий относительно поведения этой функции при дискретной корректировке часов, но существующие реализации преобразуют abs_time из Clock в std::chrono::system_clock и делегируют вызов POSIX-функции pthread_cond_timedwait , чтобы ожидание учитывало корректировки системных часов, но не пользовательских часов Clock . В любом случае, функция также может ожидать дольше, чем до момента достижения abs_time из-за задержек планирования или конкуренции за ресурсы.

Даже если используемые часы являются std::chrono::steady_clock или другим монотонным clock, корректировка системного clock может вызвать ложное пробуждение.

Эффекты notify_one() / notify_all() и каждой из трёх атомарных частей wait() / wait_for() / wait_until() (разблокировка+ожидание, пробуждение и блокировка) происходят в едином полном порядке, который можно рассматривать как порядок модификации атомарной переменной: этот порядок специфичен для данной конкретной переменной условия. Это делает невозможным, чтобы notify_one() , например, был задержан и разблокировал поток, который начал ожидание сразу после вызова notify_one() .

Пример

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
std::condition_variable cv;
std::mutex cv_m; // Этот мьютекс используется для трёх целей:
                 // 1) для синхронизации доступа к i
                 // 2) для синхронизации доступа к std::cerr
                 // 3) для переменной условия cv
int i = 0;
void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cerr << "Waiting... \n";
    cv.wait(lk, []{ return i == 1; });
    std::cerr << "...finished waiting. i == 1\n";
}
void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lk(cv_m);
        std::cerr << "Notifying...\n";
    }
    cv.notify_all();
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lk(cv_m);
        i = 1;
        std::cerr << "Notifying again...\n";
    }
    cv.notify_all();
}
int main()
{
    std::thread t1(waits), t2(waits), t3(waits), t4(signals);
    t1.join(); 
    t2.join(); 
    t3.join();
    t4.join();
}

Возможный вывод:

Waiting...
Waiting...
Waiting...
Notifying...
Notifying again...
...finished waiting. i == 1
...finished waiting. i == 1
...finished waiting. i == 1

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 2093 C++11 исключения, связанные с таймаутом, отсутствовали в спецификации упоминает эти исключения
LWG 2114
( P2167R3 )
C++11 конвертируемость в bool была слишком слабой для отражения ожиданий реализаций требования усилены
LWG 2135 C++11 поведение было неясным, если lock. lock ( ) выбрасывает исключение вызывает std::terminate в этом случае

Смотрите также

блокирует текущий поток до пробуждения переменной условия
(public member function)
блокирует текущий поток до пробуждения переменной условия или после указанной длительности таймаута
(public member function)