Предостережение

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

В табл. 8.1 описаны четыре возможные ситуации.

Таблица 8.1. Сводная таблица свойств событий 

Автоматически сбрасываемые событияСбрасываемые вручную события
SetEventОсвобождается строго один поток. Если в этот момент ни один из потоков не ожидает наступления события, то поток, который первым перейдет в состояние ожидания следующих событий, будет сразу же освобожден. После этого событие немедленно автоматически сбрасывается.Освобождаются все потоки, которые в настоящее время ожидают наступления события. Событие остается в сигнальном состоянии до тех пор, пока не будет сброшено каким-либо потоком.
PulseEventОсвобождается строго один поток, но только в том случае, если имеется поток, ожидающий наступления события.Освобождаются все потоки, которые в этот момент ожидают наступления события, если таковые имеются, после чего событие сбрасывается и переходит в несигнальное состояние. 

Образно говоря, автоматически сбрасываемое событие — это дверь, снабженная пружиной, которая обеспечивает автоматическое закрытие двери, в то время как вручную сбрасываемое событие можно уподобить двери, в которой пружина отсутствует и которая, будучи раз открытой, продолжает оставаться в таком состоянии. Используя эту метафору, можно сказать, что функция PulseEvent открывает дверь и закрывает ее сразу же после того, как через нее проходят одна (автоматически сбрасываемые события) или все (вручную сбрасываемые события) ожидающие потоки. Функция SetEvent открывает дверь и освобождает ее.

<p>Пример: система "производитель/потребитель"</p>

В этом примере возможности программы 8.1 расширяются таким образом, чтобы потребитель мог дожидаться момента, когда появится доступное сообщение. Тем самым устраняется одна из проблем, связанная с тем, что в предыдущем варианте программы потребитель должен был непрерывно повторять попытки получения новых сообщений. Результирующая программа (программа 8.2) называется eventPC.

Заметьте, что в предлагаемом решении вместо объектов CRITICAL_SECTION используются мьютексы; единственной причиной для этого послужило лишь желание проиллюстрировать применение мьютексов. В то же время, использование автоматически сбрасываемого события и функции SetEvent в потоке потребителя является весьма существенным для работы программы, поскольку это гарантирует освобождение только одного потока.

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

Программа 8.2. eventPC: система "производитель/потребитель", использующая сигналы 

/* Глава 8. eventPC.с */

/* Поддерживает два потока — производителя и потребителя. */

/* Производитель периодически создает буферные данные с контрольными */

/* суммами, или "блоки сообщений", сигнализирующие потребителю о готовности*/

/* сообщения. Поток потребителя отображает информацию в ответ на запрос.*/

#include "EvryThng.h"

#include

Перейти на страницу:

Похожие книги