- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания UNIX: взаимодействие процессов - Уильям Стивенс
Шрифт:
Интервал:
Закладка:
Тип данных pthread_rwlock_t
В листинге 8.1[1] приведен текст заголовочного файла pthread_rwlock .h, в котором определен основной тип pthread_rwlock_t и прототипы функций, работающих с блокировками чтения и записи. Обычно все это находится в заголовочном файле <pthread.h>.
Листинг 8.1. Определение типа данных pthread_rwlock_t//my_rwlock/pthread_rwlock.h
1 #ifndef __pthread_rwlock_h
2 #define __pthread_rwlock_h
3 typedef struct {
4 pthread_mutex_t rw_mutex; /* блокировка для структуры */
5 pthread_cond_t rw_condreaders; /* для ждущих читающих потоков */
6 pthread_cond_t rw_condwriters; /* для ждущих пишущих потоков */
7 int rw_magic; /* для проверки ошибок */
8 int rw_nwaitreaders;/* число ожидающих */
9 int rw_nwaitwriters;/* число ожидающих */
10 int rw_refcount;
11 /* –1, если блокировка на запись, иначе – количество блокировок на чтение */
12 } pthread_rwlock_t;
13 #define RW_MAGIC 0x19283746
14 /* порядок должен быть такой же, как у элементов структуры */
15 #define PTHREAD_RWLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER,
16 PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER,
17 RW_MAGIC, 0, 0, 0 }
18 typedef int pthread_rwlockattr_t; /* не поддерживается */
19 /* прототипы функций */
20 int pthread_rwlock_destroy(pthread_rwlock_t *);
21 int pthread_rwlock_init(pthread_rwlock_t *, pthread_rwlockattr_t *);
22 int pthread_rwlock_rdlock(pthread_rwlock_t *);
23 int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
24 int pthread_rwlock_trywrlock(pthread_rwlock_t *);
25 int pthread_rwlock_unlock(pthread_rwlock_t *);
26 int pthread_rwlock_wrlock(pthread_rwlock_t *);
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. Значение этого поля проверяется всеми функциями — таким образом гарантируется, что вызвавший поток передал указатель на проинициализированную блокировку. Оно устанавливается в 0 после уничтожения блокировки.
Обратите внимание, что в счетчике rw_refcount всегда хранится текущий статус блокировки чтения-записи: –1 обозначает блокировку записи (и только одна такая блокировка может существовать в любой момент времени), 0 обозначает, что блокировка доступна и может быть установлена, а любое положительное значение соответствует количеству установленных блокировок на чтение.
14-17 Мы также определяем константу для статической инициализации нашей структуры.
Функция pthread_rwlock_init
Первая функция, pthread_rwlock_init, динамически инициализирует блокировку чтения-записи. Ее текст приведен в листинге 8.2.
7-8 Присваивание атрибутов с помощью этой функции не поддерживается, поэтому мы проверяем, чтобы указатель attr был нулевым.
9-19 Мы инициализируем взаимное исключение и две условные переменные, которые содержатся в нашей структуре. Все три счетчика устанавливаются в 0, а полю rw_magiс присваивается значение, указывающее на то, что структура была проинициализирована.
20-25 Если при инициализации взаимного исключения или условной переменной возникает ошибка, мы аккуратно уничтожаем проинициализированные объекты и возвращаем код ошибки.
Листинг 8.2. Функция pthread_rwlock_init: инициализация блокировки чтения-записи//my_rwlock/pthread_rwlock_init.с
1 #include "unpipc.h"
2 #include "pthread_rwlock.h"
3 int
4 pthread_rwlock_init(pthread_rwlock_t *rw, pthread_rwlockattr_t *attr)
5 {
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 err1;
11 if ((result = pthread_cond_init(&rw->rw_condreaders, NULL)) != 0)
12 goto err2;
13 if ((result = pthread_cond_init(&rw->rw_condwriters, NULL)) != 0)
14 goto err3;
15 rw->rw_nwaitreaders = 0;
16 rw->rw_nwaitwriters = 0;
17 rw->rw_refcount = 0;
18 rw->rw_magic = RW_MAGIC;
19 return(0);
20 err3:
21 pthread_cond_destroy(&rw->rw_condreaders);
22 err2;
23 pthread_mutex_destroy(&rw->rw_mutex);
24 err1:
25 return(result); /* значение errno */
26 }
Функция pthread_rwlock destroy
В листинге 8.3 приведена функция pthread_rwlock_destroy, уничтожающая блокировку чтения записи после окончания работы с ней.
8-13 Прежде всего проверяется, не используется ли блокировка в данный момент, а затем вызываются соответствующие функции для уничтожения взаимного исключения и двух условных переменных.
Листинг 8.З. Функция pthread_rwlock_destroy: уничтожение блокировки чтения-записи//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);