Чтение онлайн

ЖАНРЫ

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

Стивенс Уильям Ричард

Шрифт:

//my_rwlock/pthread_rwlock_destroy.с

1 #include "unpipc.h"

2 #include "pthread_rwlock.h"

3 int

4 pthread_rwlock_destroy(pthread_rwlock_t *rw)

5 {

6 if (rw->rw_magic != RW_MAGIC)

7 return(EINVAL);

8 if (rw->rw_refcount != 0 ||

9 rw->rw_nwaitreaders != 0 || rw->rw_nwaitwriters != 0)

10 return(EBUSY);

11 pthread_mutex_destroy(&rw->rw_mutex);

12 pthread_cond_destroy(&rw->rw_condreaders);

13 pthread_cond_destroy(&rw->rw_condwriters);

14 rw->rw_magic = 0;

15 return(0);

16 }

Функция pthread_rwlock_rdlock

Текст

функции pthread_rwlock_rdlock приведен в листинге 8.4.

Листинг 8.4. Функция pthread_rwlock_rdlock: получение блокировки на чтение

//my_rwlock/pthread_rwlock_rdlock.с

1 #include "unpipc.h"

2 #include "pthread_rwlock.h"

3 int

4 pthread_rwlock_rdlock(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 /* предпочтение отдается ожидающим разрешения на запись процессам */

12 while (rw->rw_refcount < 0 || rw->rw_nwaitwriters > 0) {

13 rw->rw_nwaitreaders++;

14 result = pthread_cond_wait(&rw->rw_condreaders, &rw->rw_mutex);

15 rw->rw_nwaitreaders--;

16 if (result != 0)

17 break;

18 }

19 if (result == 0)

20 rw->rw_refcount++; /* блокировка на чтение уже кем-то установлена */

21 pthread_mutex_unlock(&rw->rw_mutex);

22 return (result);

23 }

9-10 При работе со структурой pthread_rwl ock_t всегда устанавливается блокировка на rw_mutex, являющееся ее полем.

11-18 Нельзя получить блокировку на чтение, если rw_refcount имеет отрицательное значение (блокировка установлена на запись) или имеются потоки, ожидающие возможности получения блокировки на запись (rw_nwaitwriters больше 0). Если одно из этих условий верно, мы увеличиваем значение rw_nwaitreaders и вызываем pthread_cond_wait для условной переменной rw_condreaders. Вскоре мы увидим, что при разблокировании ресурса прежде всего проверяется наличие процессов, ожидающих возможности установить блокировку на запись, и если таковых не существует, проверяется наличие ожидающих возможности считывания. Если они имеются, для условной переменной rw_condreaders передается широковещательный сигнал.

19-20 При получении блокировки на чтение мы увеличиваем значение rw_refcount. Блокировка взаимного

исключения после этого снимается.

ПРИМЕЧАНИЕ

В этой функции есть проблема: если вызвавший поток будет заблокирован в функции pthread_cond_wait и после этого его выполнение будет отменено, он завершит свою работу, не разблокировав взаимное исключение, и значение rw_nwaitreaders окажется неверным. Та же проблема есть и в функции pthread_rwlock_wrlock в листинге 8.6. Эти проблемы будут исправлены в разделе 8.5.

Функция pthread_rwlock_tryrdlock

В листинге 8.5 показана наша реализация функции pthread_rwlock_tryrdlock, которая не вызывает приостановления вызвавшего ее потока.

Листинг 8.5. Функция pthread_rwlock_tryrdlock: попытка заблокировать ресурс для чтения

//my_rwlock/pthread_rwlock_tryrdlock.с

1 #include "unpipc.h"

2 #include "pthread_rwlock.h"

3 int

4 pthread_rwlock_tryrdlock(pthread_rwlock_t *rw)

5 {

6 int result;

7 if (rw->rwjnagic != RW_MAGIC)

8 return(EINVAL);

9 if ((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)

10 return(result);

11 if (rw->rw_refcount < 0 || rw->rw_nwaitwriters > 0)

12 result = EBUSY; /* блокировка установлена пишущим потоком или есть пишущие потоки, ожидающие освобождения ресурса */

13 else

14 rw->rw_refcount++; /* увеличение количества блокировок на чтение */

15 pthread_mutex_unlock(&rw->rw_mutex);

16 return(result);

17 }

11-14 Если блокировка в данный момент установлена на запись или есть процессы, ожидающие возможности установить ее на запись, возвращается ошибка с кодом EBUSY. В противном случае мы устанавливаем блокировку, увеличивая значение счетчика rw_refcount.

Функция pthread_rwlock_wrlock

Текст функции pthread_rwlock_wrlock приведен в листинге 8.6.

11-17 Если ресурс заблокирован на считывание или запись (значение rw_refcount отлично от 0), мы приостанавливаем выполнение потока. Для этого мы увеличиваем rw_nwaitwriters и вызываем pthread_cond_wait с условной переменной rw_condwriters. Для этой переменной посылается сигнал при снятии блокировки чтения-записи, если имеются ожидающие разрешения на запись процессы.

18-19 После получения блокировки на запись мы устанавливаем значение rw_refcount в –1.

Листинг 8.6. Функция pthread_rwlock_wrlock: получение блокировки на запись

//my_rwlock/pthread_rwlock_wrlock.c

1 #include "unpipc.h"

2 #include "pthread_rwlock.h"

3 int

4 pthread_rwlock_wrlock(pthread_rwlock_t *rw)

5 {

6 int result;

7 if (rw->rw_magic != RW_MAGIC)

8 return(EINVAL);

Поделиться с друзьями: