Для реализации блокировок чтения-записи достаточно использовать взаимные исключения и условные переменные. В этом разделе мы рассмотрим одну из возможных реализаций, в которой предпочтение отдается ожидающим записи потокам. Это не является обязательным; возможны альтернативы.
ПРИМЕЧАНИЕ
Этот и последующие разделы данной главы содержат усложненный материал, который можно при первом чтении пропустить.
Другие реализации блокировок чтения записи заслуживают отдельного изучения. В разделе 7.1.2 книги [3] представлена реализация, в которой приоритет имеют ожидающие записи потоки и предусмотрена обработка отмены выполнения потока (о которой мы вскоре будем говорить подробнее). В разделе В.18.2.3.1 стандарта IEEE 1996 [8] представлена другая реализация, в которой предпочтение имеют ожидающие записи потоки и в которой также предусмотрена обработка отмены. В главе 14 книги [12] также приводится возможная реализация, в которой приоритет имеют ожидающие записи процессы. Реализация, приведенная в этом разделе, взята из пакета АСЕ (http://www.cs.wustl.edu/~schmidt/ACE.html), автором которого является Дуг Шмидт (Doug Schmidt). Аббревиатура АСЕ означает Adaptive Communications Environment. Во всех четырех реализациях используются взаимные исключения и условные переменные.
Тип данных pthread_rwlock_t
В листинге 8.1[1] приведен текст заголовочного файла pthread_rwlock .h, в котором определен основной тип 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 *);