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

Класс std::condition_variable_any позволяет потоку ждать выполнения условия. Если объект std::condition_variable можно использовать только с блокировкой типа std::unique_lock<std::mutex>, то 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<typename Lockable>

 void wait(Lockable& lock);

 template <typename Lockable, typename Predicate>

 void wait(Lockable& lock, Predicate pred);

 template <typename Lockable, typename Clock, typename Duration>

 std::cv_status wait_until(

  Lockable& lock,

  const std::chrono::time_point<Clock, Duration>& absolute_time);

 template <

  typename Lockable, typename Clock,

  typename Duration, typename Predicate>

 bool wait_until(

  Lockable& lock,

  const std::chrono::time_point<Clock, Duration>& absolute_time,

  Predicate pred);

 template <typename Lockable, typename Rep, typename Period>

 std::cv_status wait_for(

  Lockable& lock,

  const std::chrono::duration<Rep, Period>& relative_time);

 template <

  typename Lockable, typename Rep,

  typename Period, typename Predicate>

 bool wait_for(

  Lockable& lock,

  const std::chrono::duration<Rep, Period>& 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 , ДЕСТРУКТОР

Уничтожает объект std::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<typename Lockable>

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<typename Lockable, typename Predicate>

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<typename Lockable, typename Rep, typename Period>

std::cv_status wait_for(

 Lockable& lock,

 std::chrono::duration<Rep, Period> 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 Lockable, typename Rep,

         typename Period, typename Predicate>

bool wait_for(

 Lockable& lock,

 std::chrono::duration<Rep, Period> 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<Rep, Period> 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<typename Lockable, typename Clock, typename Duration>

std::cv_status wait_until(

 Lockable& lock,

 std::chrono::time_point<Clock, Duration> 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 Lockable, typename Clock,

         typename Duration, typename Predicate>

bool wait_until(

 Lockable& lock,

 std::chrono::time_point<Clock, Duration> 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() будит только потоки, запущенные до этого обращения.