Литмир - Электронная Библиотека
Содержание  
A
A

#include <pthread.h>

int pthread_cond_broadcast(pthread_cond_t *<i>cptr</i>);

int pthread_cond_timedwait(pthread_cond_t *<i>cptr</i>, pthread_mutex_t *<i>mptr</i>,

 const struct timespec *<i>abstime</i>);

<i>Обе функции возвращают: 0 в случае успешного выполнения, положительное значение Exxx в случае ошибки</i>

Функция

pthread_cond_timedwait
позволяет потоку задать предельное время блокирования. Аргумент
abstime
представляет собой структуру
timespec
(определенную в разделе 6.9 при рассмотрении функции
pselect
), которая задает системное время для момента, когда функция должна возвратить управление, даже если к этому моменту условная переменная не подала сигнал. Если возникает такая ситуация, возвращается ошибка
ETIME
.

В данном случае значение времени является абсолютным значением времени, в отличие от относительного значения разницы во времени (time delta) между некоторыми событиями. Иными словами,

abstime
— это системное время, то есть количество секунд и наносекунд, прошедших с 1 января 1970 года (UTC) до того момента, когда эта функция должна вернуть управление. Здесь имеется различие как с функцией
pselect
, так и с функцией
select
, задающими количество секунд (и наносекунд в случае
pselect
) до некоторого момента в будущем, когда функция должна вернуть управление. Обычно для этого вызывается функция
gettimeofday
, которая выдает текущее время (в виде структуры
timeval
), а затем оно копируется в структуру
timespec
и к нему добавляется требуемое значение:

struct timeval tv;

struct timespec ts;

if (gettimeofday(&amp;tv, NULL) &lt; 0)

 err_sys(&quot;gettimeofday error&quot;);

ts.tv_sec = tv.tv_sec + 5; /* 5 с в будущем */

ts.tv_nsec = tv.tv_usec * 1000; /* микросекунды переводим в наносекунды */

pthread_cond_timedwait( , &amp;ts);

Преимущество использования абсолютного времени (в противоположность относительному) заключается в том, что функция может завершиться раньше (возможно, из-за перехваченного сигнала). Тогда функцию можно вызвать снова, не меняя содержимое структуры

timespec
. Недостаток этого способа заключается в необходимости вызывать дополнительно функцию
gettimeofday
перед тем, как в первый раз вызывать функцию
pthread_cond_timedwait
.

ПРИМЕЧАНИЕ

В POSIX определена новая функция clock_gettime, возвращающая текущее время в виде структуры timespec.

26.9. Веб-клиент и одновременный доступ

Изменим код нашего веб-клиента из раздела 26.6: уберем вызов функции Solaris

thr_join
и заменим его вызовом функции
pthread_join
. Как сказано в разделе 26.6, теперь нам нужно точно указать, завершения какого потока мы ждем. Для этого мы используем условную переменную, описанную в разделе 26.8.

Единственным изменением в отношении глобальных переменных (см. листинг 26.7) является добавление нового флага и условной переменной:

#define F_JOINED 8 /* количество потоков */

int ndone; /* количество завершившихся потоков */

pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t ndone_cond = PTHREAD_COND_IINITIALIZER;

Единственным изменением функции

do_get_read
(см. листинг 26.9) будет увеличение на единицу значения переменной
ndone
и оповещение главного цикла о завершении выполнения потока:

 printf(&quot;end-of-file on %s\n&quot;, fptr-&gt;f_name);

 Close(fd);

 Pthread_mutex_lock(&amp;ndone_mutex);

 fptr-&gt;f_flags = F_DONE; /* сбрасывает флаг F_READING */

 ndone++;

 Pthread_cond_signal(&amp;ndone_cond);

 Pthread_mutex_unlock(&amp;ndone_mutex);

 return(fptr); /* завершение выполнения потока */

}

Большинство изменений касается главного цикла, представленного в листинге 26.8. Новая версия показана в листинге 26.13.

Листинг 26.13. Основной рабочий цикл функции main

//threads/web03.c

43  while (nlefttoread &gt; 0) {

44   while (nconn &lt; maxnconn &amp;&amp; nlefttoconn &gt; 0) {

45    /* находим файл для считывания */

46    for (i = 0; i &lt; nfiles; i++)

47     if (file[i].f_flags == 0)

48      break;

49    if (i == nfiles)

50     err_quit(&quot;nlefttoconn = %d but nothing found&quot;, nlefttoconn);

51    file[i].f_flags = F_CONNECTING;

52    Pthread_create(&amp;tid, NULL, &amp;do_get_read, &amp;file[i]);

53    file[i].f_tid = tid;

54    nconn++;

55    nlefttoconn--;

56   }

57   /* Ждем завершения выполнения одного из потоков */

58   Pthread_mutex_lock(&amp;ndone_mutex);

59   while (ndone == 0)

60    Pthread_cond_wait(&amp;ndone_cond, &amp;ndone_mutex);

61   for (i = 0; i &lt; nfiles; i++) {

62    if (file[i].f_flags &amp; F_DONE) {

294
{"b":"225366","o":1}