Функция 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 даже при наличии блокировок на чтение, что приведет к потере эффективности.
Данный текст является ознакомительным фрагментом.