pthread_cond_timedwait()

Ожидать условную переменную в течении ограниченного времени

Прототип:

#include <pthread.h>
#include <time.h>
int pthread_cond_timedwait( pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime );

Аргументы:

cond
Условная переменная, освобождения которой необходимо дождаться.
mutex
Мьютекс, ассоциированный с условной переменной.
abstime
Указатель на struct timespec, которая определяет максимально допустимое время блокировки потока в абсолютном выражении.

Библиотека:

libc

Описание:

Функция pthread_cond_timedwait() блокирует вызывающий поток на условной переменной cond и освобождает ассоциированный с ней мьютекс mutex. Вызывающий поток должен иметь мьютекс mutex в блокированном состояни перед вызовом данной функции. При возвращении управления функцией мьютекс будет снова заблокирован, а текущий поток будет являться владельцем.

Заблокированный поток будет оставаться таким до тех пор, пока иной поток не выполнит одиночное или массовое разблокирование на условной переменной (см. pthread_cond_signal() и pthread_cond_broadcast()). Абсолютный интервал времени, заданный в abstime, определяет предельное время доставки принудительного разблокирующего сигнала уже не от прикладного потока, а от ядра ОС. Стоит учитывать, что в этот момент может произойти прерывание выполнения потока так как ожидание на условной переменной является точкой остановки потока. В любом случае перед разблокированием поток становится владельцем разблокированного мьютекса.

Для определения типа таймера, который контролирует таймауты условной переменной можно использовать функцию pthread_condattr_setclock(). При этом CLOCK_MONOTONIC не зависит от изменений системного времени и используется по умолчанию, а CLOCK_REALTIME наоборот.


Note: Не используйте рекурсивные мьютексы с условными переменными.

Если заблокированный на условной переменной поток прерывает свое выполнение, то происходит захват ассоциированного мьютекса и выполнение всех определенных в потоке деструкторов уже в контексте критической секции кода, которая организована до и после самого вызова pthread_cond_timedwait(). Если кто-то иной владеет мьютексом, прерывание потока откладывается до его разблокирования.


Note:
  • Убедитесь в том, что определенные в потоке деструкторы освобождают ассоциированный с условной переменной мьютекс. В противном случае возможна ситуация, когда мьютекс остается заблокированным, а поток-владелец уже уничтожен.

  • Для задания таймаута длительностью менее секунды достаточно получить текущее время с помощью clock_gettime() и добавить необходимое число наносекунд к полю abstime.tv_nsec field.

  • Вы можете использовать nsec2timespec() для конвертирования времени из наносекунд в struct timespectimespec2nsec() для обратного преобразования).

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

EOK
Успешное завершение или прерывание выполнения сигналом.
EAGAIN
Недостаточно системных ресурсов для выполнения ожидания на условной переменной.
EFAULT
При обращении к буферам произошла ошибка.
EINVAL
Выполнено одно или несколько из следующих условий:
EPERM
Текущий поток не владеет мьютексом.
ETIMEDOUT
Истекло время, указанное в abstime.

Примеры:

Подождать 5 секунд перед попыткой захватить контроль над условной переменной:

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c;
int main( int argc, char* argv[] )
{
struct timespec to;
int retval;
pthread_condattr_t attr;
fprintf( stderr, "starting...\n" );
/* Set up the condvar attributes to use CLOCK_MONOTONIC. */
pthread_condattr_init( &attr );
pthread_condattr_setclock( &attr, CLOCK_MONOTONIC );
pthread_cond_init( &c, &attr );
/*
* Here's the interesting bit; we'll wait for five seconds
* FROM NOW when we call pthread_cond_timedwait().
*/
clock_gettime( CLOCK_MONOTONIC, &to );
to.tv_sec += 5;
if ( (retval = pthread_mutex_lock( &m )) )
{
fprintf( stderr, "pthread_mutex_lock %s\n", strerror( retval ) );
exit( EXIT_FAILURE );
}
if ( (retval = pthread_cond_timedwait( &c, &m, &to )) )
{
fprintf( stderr, "pthread_cond_timedwait %s\n", strerror( retval ) );
exit( EXIT_FAILURE );
}
if ( (retval = pthread_mutex_unlock( &m )) )
{
fprintf( stderr, "pthread_mutex_unlock %s\n", strerror( retval ) );
exit( EXIT_FAILURE );
}
return (EXIT_SUCCESS);
}

Классификация:

POSIX 1003.1 Threads

Безопасность использования
Точка остановки потока
Да
Обработчик прерываний
Нет
Обработчик сигналов
Да
В потоке
Да

Тематические ссылки:

nsec2timespec(), pthread_cond_broadcast(), pthread_cond_init(), pthread_cond_signal(), pthread_cond_wait(), pthread_cond_wait_interruptible(), pthread_condattr_setclock(), SyncCondvarWait(), TimerTimeout(), struct timespec, timespec2nsec()




Предыдущий раздел: Описание API системной библиотеки