Функция pthread_cond_wait() используется, чтобы атомарно освободить мьютекс и заставить вызывающий поток блокироваться по переменной состояния. Функция pthread_cond_wait() возвращает 0 - после успешного завершения. Любое другое значение указывает, что произошла ошибка. Пример использования функции:
pthread_cond_t cv;
pthread_mutex_t mutex;
int ret;
ret = pthread_cond_wait(&cv, &mutex);
Проверка состояния обычно проводится в цикле while, который вызывает pthread_cond_wait():
while(condition_is_false)
pthread_cond_wait();
pthread_mutex_unlock();
Следует всегда вызывать pthread_cond_signal() под защитой
мьютекса, используемого с сигнальной переменной состояния. В ином
случае переменная состояния может измениться между тестированием
соответствующего состояния и блокировкой в вызове
pthread_cond_wait(),
что может вызвать бесконечное ожидание. Если никакие потоки не блокированы
по переменной состояния, вызов pthread_cond_signal () не
будет иметь никакого эффекта.
Следующий фрагмент кода иллюстрирует, как избежать бесконечного ожидания, описанного выше:
pthread_cond_t count_nonzero;
unsigned count;
decrement_count() {
pthread_mutex_lock(&count_lock);
while (count == 0)
pthread_cond_wait(&count_nonzero, &count_lock);
count = count - 1;
pthread_mutex_unlock(&count_lock);
}
increment_count() {
pthread_mutex_lock(&count_lock);
if (count == 0)
pthread_cond_signal(&count_nonzero);
count = count + 1;
pthread_mutex_unlock(&count_lock);
}
pthread_mutex_t *mp,
const struct timespec *abstime);
#include <time.h>
pthread_timestruc_t to;
pthread_cond_t cv;
pthread_mutex_t mp;
timestruct_t abstime;
int ret;
/* ожидание переменной состояния */
ret = pthread_cond_timedwait(&cv, &mp, &abstime);
pthread_mutex_lock(&m);
to.tv_sec = time(NULL) + TIMEOUT;
to.tv_nsec = 0;
while (cond == FALSE) {
err = pthread_cond_timedwait(&c, &m, &to);
if (err == ETIMEDOUT) {
/* таймаут */
break;
}
}
pthread_mutex_unlock(&m);
pthread_cond_broadcast() возвращает 0 - после успешного завершения - или любое другое значение в случае ошибки.
Поскольку pthread_cond_broadcast() заставляет все потоки,
блокированные некоторым состоянием, бороться за мьютекс, ее нужно
использовать аккуратно. Например, можно использовать
pthread_cond_broadcast(),
чтобы позволить потокам бороться за изменение количества требуемых
ресурсов, когда ресурсы освобождаются:
pthread_mutex_t rsrc_lock;
pthread_cond_t rsrc_add;
unsigned int resources;
get_resources(int amount) {
pthread_mutex_lock(&rsrc_lock);
while (resources < amount)
pthread_cond_wait(&rsrc_add, &rsrc_lock);
resources -= amount;
pthread_mutex_unlock(&rsrc_lock);
}
add_resources(int amount) {
pthread_mutex_lock(&rsrc_lock);
resources += amount;
pthread_cond_broadcast(&rsrc_add);
pthread_mutex_unlock(&rsrc_lock);
}
pthread_cond_t cv;
int ret;
/* Переменная состояния удалена */
ret = pthread_cond_destroy(&cv);