Параллельное программирование на С++ в действии — страница 46 из 53

Заголовок

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

Содержимое заголовка

namespace std {

enum class cv_status { timeout, no_timeout };


class condition_variable;

class condition_variable_any;

}

D.2.1. Класс
std::condition_variable

Класс

std::condition_variable
позволяет потоку ждать выполнения условия.

Экземпляры этого класса не удовлетворяют концепциям

CopyAssignable
,
CopyConstructible
,
MoveAssignable
,
MoveConstructible
.

Определение класса

class condition_variable {

public:

 condition_variable();

 ~condition_variable();


 condition_variable(condition_variable const&) = delete;

 condition_variable& operator=(

  condition_variable const&) = delete;


 void notify_one() noexcept;

 void notify_all() noexcept;


 void wait(std::unique_lock& lock);


 template 

 void wait(std::unique_lock& lock, Predicate pred);


 template 

 cv_status wait_until(

  std::unique_lock& lock,

  const std::chrono::time_point& absolute_time);


 template 

 bool wait_until(

  std::unique_lock& lock,

  const std::chrono::time_point& absolute_time,

  Predicate pred);


 template 

 cv_status wait_for(

  std::unique_lock& lock,

  const std::chrono::duration& relative_time);


 template 

 bool wait_for(

  std::unique_lock& lock,

  const std::chrono::duration& relative_time,

  Predicate pred);

};


void notify_all_at_thread_exit(

 condition_variable&, unique_lock);

STD::CONDITION_VARIABLE
, КОНСТРУКТОР ПО УМОЛЧАНИЮ

Конструирует объект типа

std::condition_variable
.

Объявление

condition_variable();

Результат

Конструирует объект типа

std::condition_variable
.

Исключения

Исключение типа

std::system_error
, если сконструировать условную переменную не получилось.

STD::CONDITION_VARIABLE
, ДЕСТРУКТОР

Уничтожает объект

std::condition_variable
.

Объявление

~condition_variable();

Предусловия

Не существует потоков, заблокированных по

*this
в обращениях к
wait()
,
wait_for()
или
wait_until()
.

Результат

Уничтожает

*this
.

Исключения

Нет.

STD::CONDITION_VARIABLE::NOTIFY_ONE
, ФУНКЦИЯ-ЧЛЕН

Пробуждает один из потоков, ожидающих

std::condition_variable
.

Объявление

void notify_one() noexcept;

Результат

Пробуждает один из потоков, ожидающих

*this
, в точке вызова. Если таких потоков нет, функция не имеет никакого эффекта.

Исключения

Исключение типа

std::system_error
, если действие не выполнено.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE::NOTIFY_ALL
, ФУНКЦИЯ-ЧЛЕН

Пробуждает все потоки, ожидающие

std::condition_variable
.

Объявление

void notify_all() noexcept;

Результат

Пробуждает все потоки, ожидающие

*this
, в точке вызова. Если таких потоков нет, функция не имеет никакого эффекта.

Исключения

Исключение типа

std::system_error
, если действие не выполнено.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE::WAIT
, ФУНКЦИЯ-ЧЛЕН

Ожидает, пока условная переменная

std::condition_variable
не получит сигнал в результате обращения к
notify_one()
или
notify_all()
либо не произойдёт ложное пробуждение.

Объявление

void wait(std::unique_lock& lock);

Предусловия

Значение

lock.owns_lock()
равно
true
, и блокировкой владеет вызывающий поток.

Результат

Атомарно разблокирует предоставленный объект

lock
и блокирует поток, пока он не будет разбужен обращением к
notify_one()
или
notify_all()
из другого потока либо не произойдёт ложное пробуждение. Перед возвратом управления из
wait()
объект
lock
снова блокируется.

Исключения

Исключение типа

std::system_error
, если действие не выполнено. Если объект
lock
был разблокирован при обращении к
wait()
, он снова блокируется при выходе из нее, даже если выход произошёл в результате исключения.

Примечание. Ложное пробуждение означает, что поток, вызвавший

wait()
, может быть разбужен, даже если ни один другой поток не обращался к
notify_one()
или
notify_all()
. Поэтому рекомендуется использовать перегруженный вариант
wait()
, который принимает предикат. Если это нежелательно, то рекомендуется вызывать
wait()
в цикле, где проверяется предикат, ассоциированный с условной переменной.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE::WAIT
, ПЕРЕГРУЖЕННАЯ ФУНКЦИЯ-ЧЛЕН, ПРИНИМАЮЩАЯ ПРЕДИКАТ

Ожидает, пока условная переменная

std::condition_variable
не получит сигнал в результате обращения к
notify_one()
или
notify_all()
и при этом предикат равен
true
.

Объявление

template

void wait(std::unique_lock& lock, Predicate pred);

Предусловия

Выражение

pred()
должно быть допустимо и возвращать значение, преобразуемое в тип
bool
. Значение
lock.owns_lock()
должно быть равно
true
, и владельцем блокировки
lock
должен быть поток, вызвавший
wait()
.

Результат

Эквивалентно циклу

while (!pred()) {

 wait(lock);

}

Исключения

Исключение, возбужденное в результате обращения к

pred
, или
std::system_error
, если действие не выполнено.

Примечание. Возможность ложного пробуждения означает, что функция

pred
может вызываться несколько раз (сколько именно, не определено). При любом вызове
pred
мьютекс, на который ссылается объект
lock
, гарантированно будет захвачен, и функция вернет управление тогда и только тогда, когда результатом вычисления
(bool)pred()
является
true
.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE::WAIT_FOR
, ФУНКЦИЯ-ЧЛЕН

Ожидает, пока условная переменная

std::condition_variable
не получит сигнал в результате обращения к
notify_one()
или
notify_all()
, либо не истечет таймаут, либо не произойдёт ложное пробуждение.

Объявление

template

cv_status wait_for(

std::unique_lock& lock,

std::chrono::duration const& relative_time);

Предусловия

Значение

lock.owns_lock()
равно
true
, и блокировкой владеет вызывающий поток.

Результат

Атомарно разблокирует предоставленный объект

lock
и блокирует поток, пока он не будет разбужен обращением к
notify_one()
или
notify_all()
из другого потока, либо не истечет таймаут, заданный аргументом
relative_time
, либо не произойдёт ложное пробуждение. Перед возвратом управления из
wait_for()
объект
lock
снова блокируется.

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

std::cv_status::no_timeout
, если поток был разбужен в результате обращения к
notify_one()
или
notify_all()
либо ложного пробуждения. В противном случае
std::cv_status::timeout
.

Исключения

Исключение типа

std::system_error
, если действие не выполнено. Если объект
lock
был разблокирован при обращении к
wait_for()
, он снова блокируется при выходе из нее, даже если выход произошёл в результате исключения.

Примечание. Ложное пробуждение означает, что поток, вызвавший

wait_for()
, может быть разбужен, даже если ни один другой поток не обращался к
notify_one()
или
notify_all()
. Поэтому рекомендуется использовать перегруженный вариант
wait_for()
, который принимает предикат. Если это нежелательно, то рекомендуется вызывать
wait_for()
в цикле, где проверяется предикат, ассоциированный с условной переменной. При этом необходимо следить, не истек ли таймаут. Во многих случаях предпочтительнее использовать функцию
wait_until()
. Поток может быть блокирован дольше, чем указано. Если возможно, истекшее время измеряется по стабильным часам.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE::WAIT_FOR
, ПЕРЕГРУЖЕННАЯ ФУНКЦИЯ-ЧЛЕН, ПРИНИМАЮЩАЯ ПРЕДИКАТ

Ожидает, пока условная переменная

std::condition_variable
не получит сигнал в результате обращения к
notify_one()
или
notify_all()
и при этом предикат равен
true
, либо не истечет указанный таймаут.

Объявление

template

bool wait_for(

 std::unique_lock& lock,

 std::chrono::duration const& relative_time,

 Predicate pred);

Предусловия

Выражение

pred()
должно быть допустимо и возвращать значение, преобразуемое в тип
bool
. Значение
lock.owns_lock()
должно быть равно
true
, и владельцем блокировки
lock
должен быть поток, вызвавший
wait_for()
.

Результат

Эквивалентно следующему коду:

internal_clock::time_point end =

 internal_clock::now() + relative_time;

while (!pred()) {

 std::chrono::duration remaining_time =

  end-internal_clock::now();

 if (wait_for(lock, remaining_time) == std::cv_status::timeout)

  return pred();

}

return true;

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

true
, если последнее обращение к
pred()
вернуло
true
;
false
, если истекло время, заданное в аргументе
relative_time
и обращение к
pred()
вернуло
false
.

Примечание. Возможность ложного пробуждения означает, что функция

pred
может вызываться несколько раз (сколько именно, не определено). При любом вызове
pred
мьютекс, на который ссылается объект
lock
, гарантированно будет захвачен, и функция вернет управление тогда и только тогда, когда результатом вычисления
(bool)pred()
является
true
или истекло время, заданное в аргументе
relative_time
. Поток может быть блокирован дольше, чем указано. Если возможно, истекшее время измеряется по стабильным часам.

Исключения

Исключение, возбужденное в результате обращения к

pred
, или
std::system_error
, если действие не выполнено.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE::WAIT_UNTIL
, ФУНКЦИЯ-ЧЛЕН

Ожидает, пока условная переменная

std::condition_variable
не получит сигнал в результате обращения к
notify_one()
или
notify_all()
либо не будет достигнут указанный момент времени, либо не произойдёт ложное пробуждение.

Объявление

template

cv_status wait_until(

 std::unique_lock& lock,

 std::chrono::time_point const& absolute_time);

Предусловия

Значение

lock.owns_lock()
равно
true
, и владельцем блокировки
lock
является вызывающий поток.

Результат

Атомарно разблокирует предоставленный объект

lock
и блокирует поток, пока он не будет разбужен обращением к
notify_one()
или
notify_all()
из другого потока, либо функция
Clock::now()
не вернет время, большее или равное
absolute_time
, либо не произойдёт ложное пробуждение. Перед возвратом управления из
wait_until()
объект
lock
снова блокируется.

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

std::cv_status::no_timeout
, если поток был разбужен в результате обращения к
notify_one()
или
notify_all()
либо ложного пробуждения. В противном случае
std::cv_status::timeout
.

Исключения

Исключение типа

std::system_error
, если действие не выполнено. Если объект
lock
был разблокирован при обращении к
wait_for()
, он снова блокируется при выходе из нее, даже если выход произошёл в результате исключения.

Примечание. Ложное пробуждение означает, что поток, вызвавший

wait_until()
, может быть разбужен, даже если ни один другой поток не обращался к
notify_one()
или
notify_all()
. Поэтому рекомендуется использовать перегруженный вариант
wait_until()
, который принимает предикат. Если это нежелательно, то рекомендуется вызывать
wait_until()
в цикле, где проверяется предикат, ассоциированный с условной переменной. Не дается никаких гарантий относительно того, сколько времени будет блокирован вызывающий поток. Гарантируется лишь, что если функция вернула
false
, то значение, возвращенное
Clock::now()
, больше или равно
absolute_time
в точке, где поток разблокировался.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE::WAIT_UNTIL
, ПЕРЕГРУЖЕННАЯ ФУНКЦИЯ-ЧЛЕН, ПРИНИМАЮЩАЯ ПРЕДИКАТ

Ожидает, пока условная переменная

std::condition_variable
не получит сигнал в результате обращения к
notify_one()
или
notify_all()
, и при этом предикат равен
true
, либо не будет достигнут указанный момент времени.

Объявление

template

bool wait_until(

 std::unique_lock& lock,

 std::chrono::time_point const& absolute_time,

 Predicate pred);

Предусловия

Выражение

pred()
должно быть допустимо и возвращать значение, преобразуемое в тип
bool
. Значение
lock.owns_lock()
должно быть равно
true
, и владельцем блокировки
lock
должен быть поток, вызвавший
wait_until()
.

Результат

Эквивалентно следующему коду:

while (!pred()) {

 if (wait_until(lock, absolute_time) == std::cv_status::timeout)

  return pred();

}

return true;

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

true
, если последнее обращение к
pred()
вернуло
true
;
false
, если функция
Clock::now()
вернула время, большее или равное
absolute_time
, и обращение к
pred()
вернуло
false
.

Примечание. Возможность ложного пробуждения означает, что функция

pred
может вызываться несколько раз (сколько именно, не определено). При любом вызове
pred
мьютекс, на который ссылается объект
lock
, гарантированно будет захвачен, и функция вернет управление тогда и только тогда, когда результатом вычисления
(bool)pred()
является
true
или функция
Clock::now()
вернула время, больше или равное
absolute_time
. Не дается никаких гарантий относительно того, сколько времени будет блокирован вызывающий поток. Гарантируется лишь, что если функция вернула
false
, то значение, возвращенное
Clock::now()
, больше или равно
absolute_time
в точке, где поток разблокировался.

Исключения

Исключение, возбужденное в результате обращения к

pred
, или
std::system_error
, если действие не выполнено.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::NOTIFY_ALL_AT_THREAD_EXIT
, ФУНКЦИЯ, НЕ ЯВЛЯЮЩАЯСЯ ЧЛЕНОМ КЛАССА

Пробуждает все потоки, ожидающие

std::condition_variable
, при завершении текущего потока.

Объявление

void notify_all_at_thread_exit(

 condition_variable& cv, unique_lock lk);

Предусловия

Значение

lock.owns_lock()
равно
true
, и владельцем блокировки
lock
является вызывающий поток. Функция
lk.mutex()
должна возвращать такое же значение, как для любого объекта блокировки, передаваемого функциям-членам
wait()
,
wait_for()
или
wait_until()
объекта
cv
из одновременно ожидающих потоков.

Результат

Передает владение мьютексом, захваченным

lk
, внутреннему объекту и планирует отправку уведомления условной переменной
cv
при завершении вызывающего потока. Уведомление эквивалентно выполнению следующего кода:

lk.unlock();

cv.notify_all();

Исключения

Возбуждает исключение

std::system_error
, если действие не выполнено.

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

Пользователь должен следить за тем, чтобы ожидающий поток не сделал ошибочного предположения о том, что в момент его пробуждения данный поток уже завершен, — в частности, из-за возможности ложного пробуждения. Для этого можно проверять в ожидающем потоке предикат, который может быть сделан истинным только уведомляющим потоком, причём это должно делаться под защитой мьютекса, который не освобождается до вызова

notify_all_at_thread_exit
.

D.2.2. Класс
std::condition_variable_any

Класс

std::condition_variable_any
позволяет потоку ждать выполнения условия. Если объект
std::condition_variable
можно использовать только с блокировкой типа
std::unique_lock
, то
std::condition_variable_any
допустимо использовать с блокировкой любого типа, удовлетворяющего требованиям концепции
Lockable
.

Экземпляры

std::condition_variable_any
не удовлетворяют концепциям
CopyAssignable
,
CopyConstructible
,
MoveAssignable
,
MoveConstructible
.

Определение класса

class condition_variable_any {

public:

 condition_variable_any();

 ~condition_variable_any();


 condition_variable_any(

  condition_variable_any const&) = delete;

 condition_variable_any& operator=(

  condition_variable_any const&) = delete;


 void notify_one() noexcept;

 void notify_all() noexcept;


 template

 void wait(Lockable& lock);


 template 

 void wait(Lockable& lock, Predicate pred);


 template 

 std::cv_status wait_until(

  Lockable& lock,

  const std::chrono::time_point& absolute_time);


 template <

  typename Lockable, typename Clock,

  typename Duration, typename Predicate>

 bool wait_until(

  Lockable& lock,

  const std::chrono::time_point& absolute_time,

  Predicate pred);


 template 

 std::cv_status wait_for(

  Lockable& lock,

  const std::chrono::duration& relative_time);


 template <

  typename Lockable, typename Rep,

  typename Period, typename Predicate>

 bool wait_for(

  Lockable& lock,

  const std::chrono::duration& relative_time,

  Predicate pred);

};

STD::CONDITION_VARIABLE_ANY
, КОНСТРУКТОР ПО УМОЛЧАНИЮ

Конструирует объект типа

std::condition_variable_any
.

Объявление

condition_variable_any();

Результат

Конструирует объект типа

std::condition_variable_any
.

Исключения

Исключение типа

std::system_error
, если сконструировать условную переменную не получилось.

STD::CONDITION_VARIABLE_ANY
, ДЕСТРУКТОР

Уничтожает объект s

td::condition_variable_any
.

Объявление

~condition_variable_any();

Предусловия

Не существует потоков, заблокированных по

*this
в обращениях к
wait()
,
wait_for()
или
wait_until()
.

Результат

Уничтожает

*this
.

Исключения

Нет.

STD::CONDITION_VARIABLE_ANY::NOTIFY_ONE
, ФУНКЦИЯ-ЧЛЕН

Пробуждает один из потоков, ожидающих

std::condition_variable_any
.

Объявление

void notify_one() noexcept;

Результат

Пробуждает один из потоков, ожидающих

*this
, в точке вызова. Если таких потоков нет, функция не имеет никакого эффекта.

Исключения

Исключение типа

std::system_error
, если действие не выполнено.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable_any
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE_ANY::NOTIFY_ALL
, ФУНКЦИЯ-ЧЛЕН

Пробуждает все потоки, ожидающие

std::condition_variable_any
.

Объявление

void notify_all() noexcept;

Результат

Пробуждает все потоки, ожидающие

*this
, в точке вызова. Если таких потоков нет, функция не имеет никакого эффекта.

Исключения

Исключение типа

std::system_error
, если действие не выполнено.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable_any
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE::WAIT
, ФУНКЦИЯ-ЧЛЕН

Ожидает, пока условная переменная

std::condition_variable_any
не получит сигнал в результате обращения к
notify_one()
или
notify_all()
либо не произойдёт ложное пробуждение.

Объявление

template

void wait(Lockable& lock);

Предусловия

Тип

Lockable
удовлетворяет требованиям концепции
Lockable
и
lock
владеет блокировкой.

Результат

Атомарно разблокирует предоставленный объект

lock
и блокирует поток, пока он не будет разбужен обращением к
notify_one()
или
notify_all()
из другого потока либо не произойдёт ложное пробуждение. Перед возвратом управления из
wait()
объект
lock
снова блокируется.

Исключения

Исключение типа

std::system_error
, если действие не выполнено. Если объект
lock
был разблокирован при обращении к
wait()
, он снова блокируется при выходе из нее, даже если выход произошёл в результате исключения.

Примечание. Ложное пробуждение означает, что поток, вызвавший

wait()
, может быть разбужен, даже если ни один другой поток не обращался к
notify_one()
или
notify_all()
. Поэтому рекомендуется использовать перегруженный вариант
wait()
, который принимает предикат. Если это нежелательно, то рекомендуется вызывать
wait()
в цикле, где проверяется предикат, ассоциированный с условной переменной.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable_any
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE_ANY::WAIT
, ПЕРЕГРУЖЕННАЯ ФУНКЦИЯ-ЧЛЕН, ПРИНИМАЮЩАЯ ПРЕДИКАТ

Ожидает, пока условная переменная

std::condition_variable_any
получит сигнал в результате обращения к
notify_one()
или
notify_all()
и при этом предикат равен
true
.

Объявление

template

void wait(Lockable& lock, Predicate pred);

Предусловия

Выражение

pred()
должно быть допустимо и возвращать значение, преобразуемое в тип
bool
. Тип
Lockable
удовлетворяет требованиям концепции
Lockable
и
lock
владеет блокировкой.

Результат

Эквивалентно циклу

while (!pred()) {

 wait(lock);

}

Исключения

Исключение, возбужденное в результате обращения к

pred
, или
std::system_error
, если действие не выполнено.

Примечание. Возможность ложного пробуждения означает, что функция

pred
может вызываться несколько раз (сколько именно, не определено). При любом вызове
pred
мьютекс, на который ссылается объект
lock
, гарантированно будет захвачен, и функция вернет управление тогда и только тогда, когда результатом вычисления
(bool)pred()
является
true
.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable_any
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE_ANY::WAIT_FOR
, ФУНКЦИЯ-ЧЛЕН

Ожидает, пока условная переменная

std::condition_variable_any
получит сигнал в результате обращения к
notify_one()
или
notify_all()
, либо истечет таймаут, либо произойдёт ложное пробуждение.

Объявление

template

std::cv_status wait_for(

 Lockable& lock,

 std::chrono::duration const& relative_time);

Предусловия

Тип

Lockable
удовлетворяет требованиям концепции
Lockable
и
lock
владеет блокировкой.

Результат

Атомарно разблокирует предоставленный объект

lock
и блокирует поток, пока он не будет разбужен обращением к
notify_one()
или
notify_all()
из другого потока, либо не истечет таймаут, заданный аргументом
relative_time
, либо не произойдёт ложное пробуждение. Перед возвратом управления из
wait_for()
объект
lock
снова блокируется.

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

std::cv_status::no_timeout
, если поток был разбужен в результате обращения к
notify_one()
или
notify_all()
либо ложного пробуждения. В противном случае
std::cv_status::timeout
.

Исключения

Исключение типа

std::system_error
, если действие не выполнено. Если объект
lock
был разблокирован при обращении к
wait_for()
, он снова блокируется при выходе из нее, даже если выход произошёл в результате исключения.

Примечание. Ложное пробуждение означает, что поток, вызвавший

wait_for()
, может быть разбужен, даже если ни один другой поток не обращался к
notify_one()
или
notify_all()
. Поэтому рекомендуется использовать перегруженный вариант
wait_for()
, который принимает предикат. Если это нежелательно, то рекомендуется вызывать
wait_for()
в цикле, где проверяется предикат, ассоциированный с условной переменной. При этом необходимо следить, не истек ли таймаут. Во многих случаях предпочтительнее использовать функцию
wait_until()
. Поток может быть блокирован дольше, чем указано. Если возможно, истекшее время измеряется по стабильным часам.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable_any
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE_ANY::WAIT_FOR
, ПЕРЕГРУЖЕННАЯ ФУНКЦИЯ-ЧЛЕН, ПРИНИМАЮЩАЯ ПРЕДИКАТ

Ожидает, пока условная переменная

std::condition_variable_any
получит сигнал в результате обращения к
notify_one()
или
notify_all()
и при этом предикат равен
true
, либо истечет указанный таймаут.

Объявление

template

         typename Period, typename Predicate>

bool wait_for(

 Lockable& lock,

 std::chrono::duration const& relative_time,

 Predicate pred);

Предусловия

Выражение

pred()
должно быть допустимо и возвращать значение, преобразуемое в тип
bool
. Тип
Lockable
удовлетворяет требованиям концепции
Lockable
и
lock
владеет блокировкой.

Результат

Эквивалентно следующему коду:

internal_clock::time_point end

 = internal_clock::now() + relative_time;

while (!pred()) {

 std::chrono::duration remaining_time =

  end-internal_clock::now();

 if (wait_for(lock, remaining_time) == std::cv_status::timeout)

  return pred();

}

return true;

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

true
, если последнее обращение к
pred()
вернуло
true
;
false
, если истекло время, заданное в аргументе
relative_time
и обращение к
pred()
вернуло
false
.

Примечание. Возможность ложного пробуждения означает, что функция

pred
может вызываться несколько раз (сколько именно, не определено). При любом вызове
pred
мьютекс, на который ссылается объект
lock
, гарантированно будет захвачен, и функция вернет управление тогда и только тогда, когда результатом вычисления
(bool)pred()
является
true
или истекло время, заданное в аргументе
relative_time
. Поток может быть блокирован дольше, чем указано. Если возможно, истекшее время измеряется по стабильным часам.

Исключения

Исключение, возбужденное в результате обращения к

pred
, или
std::system_error
, если действие не выполнено.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable_any
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE_ANY::WAIT_UNTIL
, ФУНКЦИЯ-ЧЛЕН

Ожидает, пока условная переменная

std::condition_variable_any
получит сигнал в результате обращения к
notify_one()
или
notify_all()
либо будет достигнут указанный момент времени, либо произойдёт ложное пробуждение.

Объявление

template

std::cv_status wait_until(

 Lockable& lock,

 std::chrono::time_point const& absolute_time);

Предусловия

Тип

Lockable
удовлетворяет требованиям концепции
Lockable
и
lock
владеет блокировкой.

Результат

Атомарно разблокирует предоставленный объект

lock
и блокирует поток, пока он не будет разбужен обращением к
notify_one()
или
notify_all()
из другого потока, либо функция
Clock::now()
не вернет время, большее или равное
absolute_time
, либо не произойдёт ложное пробуждение. Перед возвратом управления из
wait_until()
объект
lock
снова блокируется.

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

std::cv_status::no_timeout
, если поток был разбужен в результате обращения к
notify_one()
или
notify_all()
либо ложного пробуждения. В противном случае
std::cv_status::timeout
.

Исключения

Исключение типа

std::system_error
, если действие не выполнено. Если объект
lock
был разблокирован при обращении к
wait_for()
, он снова блокируется при выходе из нее, даже если выход произошёл в результате исключения.

Примечание. Ложное пробуждение означает, что поток, вызвавший

wait_until()
, может быть разбужен, даже если ни один другой поток не обращался к
notify_one()
или
notify_all()
. Поэтому рекомендуется использовать перегруженный вариант
wait_until()
, который принимает предикат. Если это нежелательно, то рекомендуется вызывать
wait_until()
в цикле, где проверяется предикат, ассоциированный с условной переменной. Не дается никаких гарантий относительно того, сколько времени будет блокирован вызывающий поток. Гарантируется лишь, что если функция вернула
false
, то значение, возвращенное
Clock::now()
, больше или равно
absolute_time
в точке, где поток разблокировался.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable_any
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

STD::CONDITION_VARIABLE_ANY::WAIT_UNTIL
, ПЕРЕГРУЖЕННАЯ ФУНКЦИЯ-ЧЛЕН, ПРИНИМАЮЩАЯ ПРЕДИКАТ

Ожидает, пока условная переменная

std::condition_variable_any
но лучит сигнал в результате обращения к
notify_one()
или
notify_all()
, и при этом предикат равен
true
, либо будет достигнут указанный момент времени.

Объявление

template

         typename Duration, typename Predicate>

bool wait_until(

 Lockable& lock,

 std::chrono::time_point const& absolute_time,

 Predicate pred);

Предусловия

Выражение

pred()
должно быть допустимо и возвращать значение, преобразуемое в тип
bool
. Тип
Lockable
удовлетворяет требованиям концепции
Lockable
и
lock
владеет блокировкой.

Результат

Эквивалентно следующему коду:

while (!pred()) {

 if (wait_until(lock, absolute_time) == std::cv_status::timeout)

  return pred();

}

return true;

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

true
, если последнее обращение к
pred()
вернуло
true
;
false
, если функция
Clock::now()
вернула время, большее или равное
absolute_time
, и обращение к
pred()
вернуло
false
.

Примечание. Возможность ложного пробуждения означает, что функция

pred
может вызываться несколько раз (сколько именно, не определено). При любом вызове
pred
мьютекс, на который ссылается объект
lock
, гарантированно будет захвачен, и функция вернет управление тогда и только тогда, когда результатом вычисления
(bool)pred()
является
true
или функция
Clock::now()
вернула время, большее или равное
absolute_time
. Не дается никаких гарантий относительно того, сколько времени будет блокирован вызывающий поток. Гарантируется лишь, что если функция вернула
false
, то значение, возвращенное
Clock::now()
, больше или равно
absolute_time
в точке, где поток разблокировался.

Исключения

Исключение, возбужденное в результате обращения к

pred
, или
std::system_error
, если действие не выполнено.

Синхронизация

Обращения к функциям

notify_one()
,
notify_all()
,
wait()
,
wait_for()
и
wait_until()
одного и того же объекта
std::condition_variable_any
сериализуются. Обращение к
notify_one()
или
notify_all()
будит только потоки, запущенные до этого обращения.

D.3. Заголовок