Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Создание эффективных приложений для Windows Джеффри Рихтер 2004 (Книга).pdf
Скачиваний:
385
Добавлен:
15.06.2014
Размер:
8.44 Mб
Скачать

функции массив с их описателями. Если завершается процесс, описатель которого находится в нулевом элементе массива, WaitForMultipleObjects возвращает управление. Теперь поток может сделать то, что ему нужно, и вновь вызвать эту фун кцию, ожидая завершения другого процесса. Если поток передаст те же три описате ля, функция немедленно всрнст управление, и Вы снова получите значение WAIT_OB JECT_0. Таким образом, пока Вы не удалите описатели тех объектов, об освобожде нии которых функция уже сообщила Вам, код будет работать некорректно.

Побочные эффекты успешного ожидания

Успешный вызов WaitForSingleObject или WaitForMultipleObjecls на самом деле меняет состояние некоторых объектов ядра. Под успешным вызовом я имею в виду тот, при котором функция видит, что объект освободился, и возвращает значение, относитель ное WAITOBJECT_0. Вызов считается неудачным, если возвращается WAIT_TIMEOUT или WAIT_FAILED. В последнем случае состояние каких-либо объектов не меняется.

Изменение состояния объекта в результате вызова я называю побочным эффек, том успешного ожидания (successful wait side effect). Например, поток ждет объест «событие с автосбросом" (auto-reset event objcct) (об этих объектах я расскажу чуть позжс) Когда объект переходит в свободное состояние, функция обнаруживает это и может вернуть вызывающему потоку значение WAIT_OBJECT_0. Однако перед самым возвратом из функции событие переводится в занятое состояние — здесь сказывает ся побочный эффект успешного ожидания.

Объекты ядра «событие с автосбросом» ведут себя подобным образом, потому что таково одно из правил, определенных Microsoft для объектов этого типа. Другие объек ты дают иные побочные зффекты, а некоторые — вообще никаких К последним от носятся объекты ядра «процесс" и «поток", так что поток, ожидающий один из этих объектов, никогда не изменит его состояние. Подробнее о том, как ведут себя объек ты ядра, я буду рассказывать при рассмотрении соответствующих объектов.

Чем ценна функция WaitForMultipleObjects, так это тем, что она выполняет все дей ствия на уровне атомарного доступа. Когда поток обращается к этой функции, она ждет освобождения вссх объектов и в случае успеха вызывает в них требуемые по бочные эффекты; причем все действия выполняются как одна операция

Возьмем такой пример. Два потока вызывают WaitForMultipleObjects совершенно одинаково.

HANDLE h[2];

h[0] = hAutoResetEvent1;

//изначально занят

h[1] = hAutoResetEvent2;

//изначально занят

WaitForMulUpleObjects(2, И, TRUE, INFINITE);

На момент вызова WaitForMultipleObjects эти объекты-события заняты, и оба пото ка переходят в режим ожидания Но вот освобождается объект hAutoResetEventl Это становится известным обоим потокам, однако ни один из них не пробуждается, так как