Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 [ 62 ] 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

27 /* и наши функции-обертки */

28 void Pthread rwlock destroy(pthread rwlock t *);

29 void Pthread rwlock init(pthread rwlock t *. pthread rwlockattr t *):

30 void Pthread rwlock rdlock(pthread rwlock t *);

31 int Pthread rwlock tryrdlock(pthread rwlock t *):

32 int Pthread rwlock trywrlock(pthread rwlock t *):

33 void Pthread rwlock unlock(pthread rwlock t *):

34 void Pthread rwlock wrlock(pthread rwlock t *):

35 #endif pthread rwlock h

3-13 Наш тип pthread rwlock t содержит одно взаимное исключение, две условные переменные, один флаг и три счетчика. Мы увидим, для чего все это нужно, когда будем разбираться с работой функций нашей программы. При просмотре или изменении содержимого этой структуры мы должны устанавливать блокировку rw mutex. После успешной инициализации структуры полю rw magic присваивается значение RW MAGIC. Значение этого поля проверяется всеми функциями - таким образом гарантируется, что вызвавший поток передал указатель на проинициализированную блокировку. Оно устанавливается в О после уничтожения блокировки.

Обратите внимание, что в счетчике rw refcount всегда хранится текущий статус блокировки чтения-записи: -1 обозначает блокировку записи (и только одна такая блокировка может существовать в любой момент времени), О обозначает, что блокировка доступна и может быть установлена, а любое положительное значение соответствует количеству установленных блокировок на чтение. 14-17 Мы также определяем константу для статической инициализации нашей структуры.

Функция pthread rwlock init

Первая функция, pthread rwlock init, динамически инициализирует блокировку чтения-записи. Ее текст приведен в листинге 8.2.

7-8 Присваивание атрибутов с помощью этой функции не поддерживается, поэтому мы проверяем, чтобы указатель attr был нулевым.

9-19 Мы инициализируем взаимное исключение и две условные переменные, которые содержатся в нашей структуре. Все три счетчика устанавливаются в О, а полю rw magi с присваивается значение, указывающее на то, что структура была проинициализирована.

20-25 Если при инициализации взаимного исключения или условной переменной возникает ошибка, мы аккуратно уничтожаем проинициализированные объекты и возвращаем код ошибки.

Функция pthread rwlock destroy

В листинге 8.3 приведена функция pthread rwl ock destroy, уничтожающая блокировку чтения записи после окончания работы с ней. 8-13 Прежде всего проверяется, не используется ли блокировка в данный момент, а затем вызываются соответствующие функции для уничтожения взаимного исключения и двух условных переменных.



Листинг 8.2. Функция pthread rwlock init: инициализация блокировки чтения-записи

my rwlock/pth read rwlock i n i t.с

1 linclude unpipc.h

2 #include pthread rwlock.h

3 int

4 pthread rwlock init(pthread rwlock t *rw. pthread rwlockattr t *attr)

6 int result:

7 if (attr !- NULL)

8 return(EINVAL): /* not supported */

9 if ( (result pthread mutex init(&rw->rw mutex. NULL)) != 0)

10 goto errl:

11 if ( (result - pthread condJnit(&rw->rw condreaders. NULL)) !- 0)

12 goto err2:

13 if ( (result - pthread cond init(&rw->rw condwriters. NULL)) !- 0)

14 goto еггЗ:

15 rw->rw nwaitreaders - 0;

16 rw->rw nwaitwriters - 0:

17 rw->rw refcount - 0:

18 rw->rw magic - RW MAGIC:

19 return(O):

20 еггЗ:

21 pthread cond destroy(&rw->rw condreaders):

22 err2:

23 pthread mutex destroy(&rw->rw mutex):

24 errl:

25 return(result): /* значение errno */

26 }

Листинг 8.3. Функция pthread rwlock destroy: уничтожение блокировки чтения-записи

my rwlock/pth read rwlock dest roy.с

1 #include unpipc.h

2 linclude pthread rwlock.h

3 int

4 pthread rwlock destroy(pthread rwlock t *rw)

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(£BUSY):

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(O):

16 1



ПРИМЕЧАНИЕ

В этой функции есть проблема: если вызвавший поток будет заблокирован в функции pthread cond wait и после этого его выполнение будет отменено, он завершит свою работу, не разблокировав взаимное исключение, и значение rw nwaitreaders окажется неверным. Та же проблема есть и в функции pthread rwlock wrlock в листинге 8.6. Эти проблемы будут исправлены в разделе 8.5.

Функция pthread rwlock rdlock

Текст функции pthread rwlock rdlock приведен в листинге 8.4.

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

my rwlock/pthread rwlock rdlock.с

1 #include unpipc.h

2 linclude pthread rwlock.h

3 int

4 pthread rwlock rdlock(pthread rwlock t *rw)

6 int result:

7 if (rw->rw magic != RW MAGIC)

8 return(EINVAL):

9 if ( (result = pthread mutexJock(&rw->rw mutex)) != 0)

10 return(result):

11 /* предпочтение отдается ожидающим разрешения на запись процессам */

12 while (rw->rw refcount < О 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 ockt всегда устанавливается блокировка на rw mutex, являющееся ее полем.

11-18 Нельзя получить блокировку на чтение, если rwref count имеет отрицательное значение (блокировка установлена на запись) или имеются потоки, ожидающие возможности получения блокировки на запись (rwnwaitwriters больше 0). Если одно из этих условий верно, мы увеличиваем значение rwnwai treaders и вызываем pthread cond wait для условной переменной rw condreaders. Вскоре мы увидим, что при разблокировании ресурса прежде всего проверяется наличие процессов, ожидающих возможности установить блокировку на запись, и если таковых не существует, проверяется наличие ожидающих возможности считывания. Если они имеются, для условной переменной rw condreaders передается широковещательный сигнал.

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



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 [ 62 ] 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.