Windows для профессионалов

       

Реализация функции WaitForMultipleExpressions


Некогорое время назад я разрабатывал одно приложение и столкнулся с весьма не простым случаем синхронизации потоков. Функции WaitForMultipleObjects, заставляющей поток ждать освобождения одного или всех объектов, оказалось недостаточно. Мне понадобилась функция, которая позволяла бы задавать более сложные критерии ожидания. У меня было три объекта ядра процесс, семафор и событие. Мой поток должен был ждать до тех пор, пока не освободится либо процесс и семафор, либо процесс и событие.

Слегка поразмыслив и творчески использовав имеющиеся функции Windows, я создал именно то, что мне требовалось, — функцию WaitWorMulttpleExpressions. Ее прототип выглядит так:

DWORD WINAPI WaitForMultipleExpressions( DWORD nExpObjectS, CONST HANDLE* phExpObiects, DWORD dwMilliseconds);

Перед ее вызовом Вы должны создать массив описателей (HANDLE) и инициализировать всt cro элементы. Параметр nExpObjects сообщает число элементов в массиве, на который указывает параметр phExpObjects. Этот массив содержит несколько наборов описателей объектов ядра; при этом каждый набор отделяется элементом, равным NULL. Функция WaitForMultipleExpressions считает все объекты в одном наборе объединяемыми логической операцией AND, а сами наборы — объединяемыми логической операцией OR. Поэтому WaitForMultipleExpressions приостанавливает вызы вающий поток до тех пор, пока не освободятся сразу все объекты в одном из наборов.

Вот пример. Допустим, мы работаем с четырьмя объектами ядра (см. таблицу ниже).

Обьект ядра Значение описателя


Поток

0x1111
Семафор 0x2222
Событие 0x3333
Процесс 0x4444

Инициализировав массив описателей, как показано в следующей таблице, мы со общаем функции WaitForMultipleExpressions приостановить вызывающий поток до тех пор, пока не освободятся поток AND семафор OR семафор AND событие AND про цесс OR поток AND процесс,

Индекс Значение описателя Набор
0 0x1111 (поток) 0
1 0x2222 (семафор)
2 0x0000 (OR)
3 0x2222 (семафор) 1
4 0x3333 (событие)
5 0x4444 (процесс)
6 0x0000 (OR)
7 0x1 1 1 1 (поток) 2
8 0x4444 (процесс)
<
Вы, наверное, помните, что функции WaitForMultipleObjects нельзя передать массив описателей, число элементов в котором превышает 64 (MAXIMUM_WAIT_OBJECTS). Так вот, при использовании WaitForMultipleExpressions массив описателей может быть го раздо больше. Однако у Вас не должно быть более 64 выражений, а в каждом — более 63 описателей. Кроме того, WaitForMulttpleExpresstons будет работать некорректно, если Вы передадите ей хотя бы один описатель мыотекса. (Почему — объясню позже.)

Возвращаемые значения функции WaitForMultipleExpressions показаны в следующей таблице. Если заданное выражение становится истинным, WaitForMultipleExpressions возвращает индекс этого выражения относительно WAIT_OBJECT_0. Если взять тот же пример, то при освобождении объектов "поток" и "процесс" WaitforMultipleExpressions вернет индекс в виде WAIT_OBJECT_0 + 2.

Возвращаемое значение Описание
От WAIT_OBJECT_0 до (WAIT_OBJECT_0 + число выражений - 1) Указывает, какое выражение стало истинным
WAIT_TIMEOUT Ни одно выражение не стало истинным в течение заданного времени.
WAIT_FAILED Произошла ошибка. Чтобы получить более подробную инфор мацию, вызовите GetLastError. Код ERROR_TOO_MANY_SECRETS означает, что Вы указали более 61 выражений, a ERROR_SEC RET_ТОО_LONG — что по крайней мере в одном выражении указано более 63 объектов. Могут возвращаться коды и других ошибок

Содержание раздела