Главная страница Взаимодействие нетривиальных процессов 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. Блокировка взаимного исключения после этого снимается.
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |