std::condition_variable::wait
void wait( std::unique_lock<std::mutex>& lock ); | (1) | (since C++11) |
template< class Predicate > void wait( std::unique_lock<std::mutex>& lock, Predicate stop_waiting ); | (2) | (since C++11) |
wait вызывает блокировку текущего потока до получения уведомления от переменной состояния или до возникновения ложного пробуждения, при необходимости циклически повторяя ожидание до тех пор, пока не будет удовлетворено некоторое предикатное условие (bool(stop_waiting()) == true).
lock, блокирует текущий поток выполнения и добавляет его в список потоков, ожидающих уведомления от *this. Поток будет разблокирован, когда будет выполнено notify_all() или notify_one(). Он также может быть разблокирован ложно. При разблокировке, независимо от причины, lock снова приобретается, и wait завершается.while (!stop_waiting())
{
wait(lock);
}Этот перегруз может использоваться для игнорирования ложных пробуждений при ожидании, пока определённое условие не станет истинным. Обратите внимание, что lock должно быть приобретено перед входом в этот метод, и оно снова приобретается после выхода из wait(lock) , что означает, что lock может использоваться для защиты доступа к stop_waiting().
Если эти функции не выполняют пост-условия (lock.owns_lock()==true и lock.mutex() заблокировано вызывающим потоком), вызывается std::terminate. Например, это может произойти, если повторное блокирование мьютекса выбросит исключение.
Параметры
| lock | - | объект типа std::unique_lock<std::mutex>, который должен быть заблокирован текущим потоком |
| stop_waiting | - | предикат, возвращающий false, если ожидание должно быть продолжено (bool(stop_waiting()) == false). Подпись предикатной функции должна быть эквивалентна следующей:
|
Возвращаемое значение
(ничего)
Исключения
stop_waiting.Примечания
Вызов этой функции, если lock.mutex() не заблокирован текущим потоком, является неопределённым поведением.
Вызов этой функции, если lock.mutex() не является тем же мьютексом, что и тот, который используется всеми другими потоками, в данный момент ожидающими той же переменной состояния, является неопределённым поведением.
Эффекты 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; // This mutex is used for three purposes:
// 1) to synchronize accesses to i
// 2) to synchronize accesses to std::cerr
// 3) for the condition variable 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 2135 | C++11 |
wait вызывал исключение при разблокировке/повторной блокировке с ошибкой | вызывает std::terminate |
См. также
| блокирует текущий поток до пробуждения переменной состояния или по истечении заданного интервала времени (публичный член-функция) |
|
| блокирует текущий поток до пробуждения переменной состояния или достижения заданного момента времени (публичный член-функция) |
|
для cnd_wait |
Внешние ссылки
| 1. | Статья блога The Old New Thing: Ложные пробуждения в переменных состояния Win32. |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/thread/condition_variable/wait