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

на главную - закладки

Жанры

Системное программирование в среде Windows

Харт Джонсон М.

Шрифт:

• Как мьютекс, так и событие связываются с блоком сообщений или иной структурой данных.

• Мьютекс определяет критический участок кода для доступа к объекту структуры данных.

• Событие используется для того, чтобы сигнализировать о появлении нового сообщения.

• Обобщая, можно утверждать, что мьютекс обеспечивает соблюдение условий, определяемых инвариантами объекта (то есть поддерживает свойства безопасности), а событие сигнализирует о том, что состояние объекта изменилось (например, сообщение было добавлено в буфер сообщений или удалено из него), и он мог перейти в известное состояние (например, в буфере сообщений присутствует,

по крайней мере, одно сообщение).

• Один поток (в программе 8.2 — поток производителя) блокирует структуру данных, изменяет состояние объекта путем создания нового сообщения и применяет функции SetEvent или PulseEvent к событию, связанному с появлением нового сообщения.

• По крайней мере, один поток из числа остальных (в данном примере — поток потребителя) ожидает наступления события, сигнализирующего о том, что объект достиг требуемого состояния. Ожидание должно выполняться за пределами критического участка кода, чтобы поток производителя мог иметь доступ к объекту.

• Кроме того, поток потребителя может блокировать мьютекс, проверить состояние объекта (например, поступило ли в буфер новое сообщение) и отказаться от ожидания события, если объект уже находится в требуемом состоянии. 

Модель переменных условий

А теперь давайте объединим все это в едином фрагменте кода, представляющем то, что мы будем называть моделью переменных условий (condition variable model, CV model), которая может существовать в виде сигнальной (signal) и широковещательной (broadcast) моделей. В первых примерах будет использована широковещательная модель. Результат представляет собой программную модель, с которой мы будем работать еще не один раз, и которая может быть использована для решения широкого круга задач синхронизации. Для удобства изложения примеры сформулированы в терминах задачи производителя и потребителя.

Обсуждение может показаться вам несколько абстрактным, однако, поняв суть методики, вы сможете решать многие задачи синхронизации, справиться с которыми без наличия хорошей модели было бы очень трудно.

В упомянутом фрагменте кода имеется несколько ключевых элементов.

• Структура данных типа STATE_TYPE, в которой содержатся все данные, или переменные состояний (state variables), такие как сообщения, контрольные суммы и счетчики, используемые в программе 8.2.

• Мьютекс и одно или более событий, связанных с этой структурой данных и обычно входящих в ее состав.

• Одна или несколько булевых функций, предназначенных для вычисления предикатов переменных условий (condition variable predicates), представляющих собой условия (состояния), наступления которых может ожидать поток. Например, в качестве предикатов могут использоваться следующие условия: "готово новое сообщение", "имеется свободное место в буфере", "очередь не пуста". Можно связывать с каждым предикатом переменной условия отдельное событие, но возможно также использование одного события для представления изменения состояния или же для представления комбинации нескольких предикатов (получаемой посредством применения операции логического "или"). В последнем случае для определения фактического состояния должны проверяться возвращаемые значения отдельных предикативных функций при блокированном мьютексе. Если предикат (логическое выражение)

является простым, необходимость в использовании отдельной функции отпадает.

Эти принципы используются потоками производителя и потребителя в приведенном ниже фрагменте кода, включающем единственное событие и предикат переменной условия (реализованный с помощью функции cvp, которая здесь не представлена). В данном примере принимается, что если поток производителя сигнализирует о достижении требуемого состояния, то должны быть освобождены сразу несколько потоков, откуда следует, что сигнал должен рассылаться всем ожидающим потокам потребителя. Так, сигналом, соответствующим созданию потоком производителя нескольких сообщений, может служить увеличение значения счетчика сообщений. Во многих случаях вам может требоваться освобождение только одного потока, что обсуждается после приведенного ниже фрагмента кода. 

Этот код ориентирован на работу под управлением Windows 9x и всех версий Windows NT. Для упрощения решения впоследствии в нем будет использована функция SignalObjectAndWait.

Примечание и предостережение

В данном примере намеренно и вполне осознанно используется функция PulseEvent, хотя некоторые авторы, а кое-где и документация Microsoft (см. замечания в соответствующем разделе MSDN), этого делать не рекомендуют. Причины нашего выбора будут ясны из последующего обсуждения и подкреплены примерами, а читателю предлагается решить (корректно) эту задачу, используя функцию SetEvent.

typedef struct _state_t {

 HANDLE Guard; /* Мьютекс, защищающий объект. */

 HANDLE CvpSet; /* Вручную сбрасываемое событие — выполняется условие, определяемое предикатом cvp. */

 … другие переменные условий

 /* Структура состояния, содержащая счетчики, контрольные суммы и прочее. */

 struct STATE_VAR_TYPE StateVar;

 } STATE_TYPE State;

/* Инициализировать состояние, создавая мьютекс и событие. */

/* Поток ПРОИЗВОДИТЕЛЯ, который изменяет состояние. */

WaitForSingleObject(State.Guard, INFINITE);

/* Изменить состояние таким образом, чтобы выполнялось условие, */

/* определяемое предикатом CV. */

/* Пример: к данному моменту подготовлено одно или несколько сообщений.*/

State.StateVar.MsgCount += N;

PulseEvent(State.CvpSet);

ReleaseMutex(State.Guard);

/* Конец интересующей нас части кода потока производителя. */

/* Ожидание определенного состояния функцией потока ПОТРЕБИТЕЛЯ. */

WaitForSingleObject(State.Guard, INFINITE);

while (!cvp(&State)) {

 ReleaseMutex(State.Guard);

 WaitForSingleObject(State.CvpSet, TimeOut);

Поделиться:
Популярные книги

Внешняя Зона

Жгулёв Пётр Николаевич
8. Real-Rpg
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Внешняя Зона

Князь

Мазин Александр Владимирович
3. Варяг
Фантастика:
альтернативная история
9.15
рейтинг книги
Князь

Путь Чести

Щукин Иван
3. Жизни Архимага
Фантастика:
фэнтези
боевая фантастика
6.43
рейтинг книги
Путь Чести

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Школа. Первый пояс

Игнатов Михаил Павлович
2. Путь
Фантастика:
фэнтези
7.67
рейтинг книги
Школа. Первый пояс

Наследник и новый Новосиб

Тарс Элиан
7. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник и новый Новосиб

Бестужев. Служба Государевой Безопасности. Книга третья

Измайлов Сергей
3. Граф Бестужев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бестужев. Служба Государевой Безопасности. Книга третья

По дороге пряностей

Распопов Дмитрий Викторович
2. Венецианский купец
Фантастика:
фэнтези
героическая фантастика
альтернативная история
5.50
рейтинг книги
По дороге пряностей

Начальник милиции. Книга 3

Дамиров Рафаэль
3. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 3

Убивать, чтобы жить

Бор Жорж
1. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать, чтобы жить

Измена. Осколки чувств

Верди Алиса
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Осколки чувств

Ведьма

Резник Юлия
Любовные романы:
современные любовные романы
эро литература
8.54
рейтинг книги
Ведьма

Темный Патриарх Светлого Рода 6

Лисицин Евгений
6. Темный Патриарх Светлого Рода
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Темный Патриарх Светлого Рода 6

Светлая ведьма для Темного ректора

Дари Адриана
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Светлая ведьма для Темного ректора