Книга: UNIX: взаимодействие процессов

Функция pthread_rwlock_unlock

Функция pthread_rwlock_unlock

Последняя функция, pthread_rwlock_unlock, приведена в листинге 8.8.

Листинг 8.8. Функция pthread_rwlock_unlock: разблокирование ресурса

//my_rwlock/pthread_rwlock_unlock.c
1  #include "unpipc.h"
2  #include "pthread_rwlock.h"
3  int
4  pthread_rwlock_unlock(pthread_rwlock_t *rw)
5  {
6   int result;
7   if (rw->rw_magic != RW_MAGIC)
8    return(EINVAL);
9   if ((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)
10   return(result);
11  if (rw->rw_refcount > 0)
12   rw->rw_refcount--; /* снятие блокировки на чтение */
13  else if (rw->rw_refcount == –1)
14   rw->rw_refcount = 0; /* снятие блокировки на запись */
15  else
16   err_dump("rw_refcount = %d", rw->rw_refcount);
17  /* преимущество отдается ожидающим возможности записи потокам */
18  if (rw->rw_nwaitwriters > 0) {
19   if (rw->rw_refcount == 0)
20    result = pthread_cond_signal(&rw->rw_condwriters);
21  } else if (rw->rw_nwaitreaders > 0)
22   result = pthread_cond_broadcast(&rw->rw_condreaders);
23  pthread_mutex_unlock(&rw->rw_mutex);
24  return(result);
25 }

11-16 Если rw_refcount больше 0, считывающий поток снимает блокировку на чтение. Если rw_refcount равно –1, записывающий поток снимает блокировку на запись.

17-22 Если имеются ожидающие разрешения на запись потоки, по условной переменной rw_condwriters передается сигнал (если блокировка свободна, то есть значение счетчика rw_refcount равно 0). Мы знаем, что только один поток может осуществлять запись, поэтому используем функцию pthread_cond_signal. Если нет потоков, ожидающих возможности записи, но есть потоки, ожидающие возможности чтения, мы вызываем pthread_cond_broadcast для переменной rw_condreaders, поскольку возможно одновременное считывание несколькими потоками. Обратите внимание, что мы перестаем устанавливать блокировку для считывающих потоков, если появляются потоки, ожидающие возможности записи. В противном случае постоянно появляющиеся потоки с запросами на чтение могли бы заставить поток, ожидающий возможности записи, ждать целую вечность. По этой причине мы используем два отдельных оператора if и не можем написать просто:

/* предпочтение отдается записывающим процессам */
if (rw->rw_nwaitreaders > 0 && rw->rw_refcount == 0)
 result = pthread_cond_signal(&rw->rw_condwriters);
else if (rw->rw_nwaitreaders > 0)
 result = pthread_cond_broadcast(&rw->rw_condreaders);

Мы могли бы исключить и проверку rw->rw_refcount, но это может привести к вызовам pthread_cond_signal даже при наличии блокировок на чтение, что приведет к потере эффективности.

Оглавление книги


Генерация: 1.337. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз