Для осуществления синхронизации используется только сама условная переменная cond. Результат ссылки на копии пере м енной cond в обращениях к функциям pthread_cond_wait(), pthread_cond_timedwait(), pthread_cond_signal(), pthread_cond_broadcast() и pthread_cond_destroy() неопределен. Попытка инициализировать уже инициализированную условную переменную приведет к неопределенному поведению.
Если атрибуты условной переменной, действующие по умолчанию, заранее определены, для инициализации условных переменных, которые создаются статически, можно использовать макрос PTHREAD_COND_INITIALIZER. Результат в это м случае эквивалентен дина м ической инициализации путе м вызова функции pthread_cond_init () с пара м етро м attr, равны м значению NULL, но без проверки на наличие ошибок.
Возвращаемые значения
При успешно м завершении функции pthread_cond_destroy() и pthread_cond_init() возвращают нулевое значение; в противно м случае— код ошибки, обозначающий ее характер.
Проверка на наличие ошибок с кодами [EBUSY] и [EINVAL] реализована так (если реализована вообще), как будто она выполняется в самом начале работы каждой функции, и код ошибки в случае ее обнаружения возвращается до модификации состояния условной переменной, заданной параметром cond.
Ошибки
Функция pthread_cond_destroy () может завершиться неудачно, если:
[EBUSY] реализация обнаружила попытку разрушить объект, адресуемый параметром cond, который относится к другому потоку (например, при использовании в функциях pthread_cond_wait() или pthread_cond_timedwait ());
[EINVAL] значение, заданное пара м етро м cond, недействительно.
Функция pthread_cond_init () завершится неудачно, если:
[EAGAIN] система испытывает недостаток в ресурсах (не имеется в виду память), необходимых для инициализации еще одной условной переменной;
[ENOMEM] для инициализации условной переменной недостаточно существующей памяти.
Функция pthread_cond_init () может завершиться неудачно, если:
[EBUSY] реализация обнаружила попытку повторно инициализировать объект условной переменной, адресуемый параметром cond, которой был ранее инициализирован, но еще не разрушен;
[ EINVAL ] значение, заданное параметром аttr, недействительно.
Примеры
Условную пере м енную м ожно разрушить сразу после того, как будут запущены все потоки, заблокированные по ней. Рассмотрим, например, следующий код.
struct list {
pthread_mutex_t lm;
}
struct elt {
key k;
int busy;
pthread_cond_t notbusy;
}
/* Находим элемент списка и сохраняем его. */
struct elt * list_find (struct list *lp, key k) {
struct elt *ep;
pthread_mutex_lock (&lp->lm);
while ((ep = find_elt (1, к) ! = NULL) && ep->busy)
pthread_cond_wait (&ep->notbusy, &lp->lm);
if (ер != NULL) ep->busy = 1;
pthread_mutex_unlock (&lp->lm) ;
return (ер);
}
delete_elt (struct list *lp, struct elt *ep) {
pthread_mutex_lock (&lp->lm);
assert (ep->busy);
//... удаляем элемент ер из списка …
ep->busy = 0; /* Paranoid. */
(A) pthread_cond_broadcast (&ep->notbusy);
pthread_mutex_unlock (&lp->lm);
(B) pthread_cond_destroy (&rp->notbusy);
free (ер);
}
В этом примере условную переменную и ее элемент списка можно освободить (строка В) сразу после того, как все потоки, ожидающие соответствующего значения условной переменной, будут «разбужены» (строка А), поскольку мьютекс и этот код гарантируют, что никакой другой поток не сможет ссылаться на удаляемый элемент.
Замечания по использованию
Отсутствуют.
Логическое обоснование
С м. раздел «Логическое обоснование» в описании функции pthread_mutex_init ().
Будущие направления
Отсутствуют.
Смотри также
pthread_cond_broadcast (), pthread_cond_signal (), pthread_cond_timedwait (), то м Base Definidons стандартаШЕЕStd 1003.1-2001, <pthread.h>.
Последовательность внесения изменений
Функции впервые реализованы в выпуске Issue 5. Включены для согласования с расширение м POSIX Threads Extension.
Issue 6
Функции pthread_cond_destroy() и pthread_cond_init() от м ече н ы как часть опции Threads.
Раздел «Описание» был отредактирован путе м при м енения интерпретации IEEE PASC Interpretation 1003.1с #34.
В целях согласования со стандарто м ISO/IEC 9899:1999 в прототип функции pthread_cond_init () было добавлено ключевое слово restrict.
pthread_cond_timedwait, pthread_cond_wait
Имя
pthread_cond_timedwait, pthread_cond_wait — функции ожидания условия.
Синопсис
THR
#include <pthread.h>
int pthread_cond_timedwait ( pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
int pthread_cond_wait (pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
Описание
Функции pthread_cond_timedwait() и pthread_cond_wait() используются для блокирования потоков по условной переменной. Они вызываются с использованием мьютекса mutex , блокируемого вызывающим потоком; в противном случае результирующее поведение не определено.
Эти функции автоматически освобождают мьютекс mutex и обеспечивают блокирование вызывающего потока по условной переменной cond; «автоматически» здесь означает «автоматический доступ к мьютексу со стороны другого потока с последующим доступом к условной переменной». Другими словами, если какой-то другой поток может получить мьютекс после его освобождения вызывающим потоком, то результат последующего вызова функции pthread_cond_broadcast () или pthread_cond_signal () в этом (другом) потоке будет таким, как если бы он имел место после блокирования вызывающего потока.
При успешном выполнении мьютекс будет заблокирован, а владеть им будет вызывающий поток.
При использовании условных переменных всегда существует булев предикат, совместно используемый этими переменными, которые связаны с каждым ожидаемым условием. Это условие становится истинным, если поток должен продолжать выполнение. При использовании функций pthread_cond_timedwait() или pthread_cond_wait () возможны фиктивные запуски. Поскольку возврат из этих функций не подразумевает ничего, кроме оценки значения упомянутого выше предиката, он должен вычисляться после каждого такого выхода из функции.
Результат использования нескольких мьютексов для параллельно выполняемых операций pthread_cond_timedwait () или pthread_cond_wait () по одной и той же условной переменной не определен; другими словами, условная переменная связывается с уникальным мьютексом, когда поток ожидает заданного значения условной переменной, и это (динамическое) связывание завершится вместе с завершением ожидания.
Ожидание условия (синхронизированное или нет) представляет собой «точку отмены». Если статус возможности аннулирования дл я потока соответствует значению PTHREAD_CANCEL_DEFERRED, побочным эффектом действий, выполняемых по запросу на аннулирование во время ожидания условия будет повторный захват мьютекса перед вызовом первого обработчика запроса на отмену. Другими словами, результат будет выглядеть так, как если бы поток был разблокирован и получил воз м ожность выполниться до точки выхода из вызова функции pthread_cond_timedwait() или pthread_cond_wait(), но в этой точке «обнаружил» запрос на от м ену и в м есто возврата к инициатору вызова функции pthread_cond_timedwait() или pthread_cond_wait() приступил к выполнению действий по аннулированию, которые включают вызов обработчиков этого запроса.