Ожидающие функции

Для синхронизации выполнения программных потоков могут быть использованы различные объекты ядра Windows: процессы, потоки, задания, файлы, консольный ввод, уведомления об изменении файлов, события, ожидаемые таймеры, семафоры, мьютексы. Перечисленные объекты имеют различное назначение, но всех их объединяет свойство находиться в свободном (signaled) или занятом (notsignaled) состояниях. Например, объекты ядра «процесс» сразу после создания всегда находятся в занятом состоянии. В момент завершения процесса операционная система автоматически освобождает его объект ядра «процесс», и он навсегда остается в этом состоянии. Разработчики Windows для каждого из объектов определили свои правила перехода между свободным и занятым состоянием (см. таблицу). Для реализации синхронизации необходимо унифицированное средство, позволяющее «усыпить» потоки и в таком состоянии ожидать освобождения объекта синхронизации, не конкурируя за время процессора, т.е. реализуя эффективное ожидание. В Windows таким средством являются ожидающие функции (wait-функции).

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

Ожидающие функции приостанавливают выполнение потока до освобождения объекта (ов) ядра или до завершения времени ожидания. К ожидающим функциям относятся: WaitForMultipleObjects, WaitForMultipleObjectsEx, WaitForSingleObject, WaitForSingleObjectEx, MsgWaitForMultipleObjects, MsgWaitForMultipleObjectsEx, WaitForInputIdle, SleepEx, SignalObjectAndWait. Наиболее часто используются функции WaitForSingleObject и WaitForMultipleObjects.

Функция WaitForSingleObject осуществляет ожидание перехода в свободное состояние одного объекта

DWORD WaitForSingleObject(
HANDLE hObject,
DWORD dwMilliseconds);

Первый параметр, hObject, идентифицирует объект ядра, поддерживающий состояния «свободен-занят». Второй параметр, dwMilliseconds, указывает, сколько времени (в миллисекундах) поток готов ждать освобождения объекта. В качестве значения второго параметра может быть использована константа INFINITE (OxFFFFFFFF -1), указывающая, что вызывающий поток готов ждать этого события хоть бесконечно. Очевидно, передача INFINITE не всегда безопасна; если объект так и не перейдет в свободное состояние, вызывающий поток никогда не проснется. В параметре dwMilliseconds можно передать 0, и тогда WaitForSingleObject немедленно вернет управление.

Возвращаемое значение функции WaitForSingleObject указывает на причину завершения функции. Если функция возвращает WAIT_OBJECT_0, объект ожидания свободен, а если WAIT_TIMEOUT - заданное время ожидания (таймаут) истекло. При передаче неверного параметра (например, недопустимого описателя) WaitForSingleObject возвращает WAIT_FAILED.

Функция WaitForMultipleObjects аналогична WaitForSingleObject с тем исключением, что позволяет ждать освобождения сразу нескольких объектов или какого-то одного из списка объектов:

DWORD WaitForMultipleObjects(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds
);

Параметр nCount определяет количество объектов ядра, на которых будет происходить ожидание. Параметр lpHandles – это указатель на массив описателей объектов ядра.

Параметр bWaitAll определяет событие завершения ожидания. Если он равен TRUE, функция не позволит потоку возобновить свою работу, пока не освободятся все объекты.

Параметр dwMilliseconds идентичен одноименному параметру функции WaitForSingleObject, Если Вы указываете конкретное время ожидания, то по его истечении функция в любом случае возвращает управление. В этом параметре обычно передают INFINITE.

Возвращаемое значение функции WaitForMultipleObjects сообщает, почему возобновилось выполнение вызвавшего ее потока. Значения WAIT_FAILED и WAIT_TIMEOUT аналогичны предыдущей функции. Если параметре bWaitAll было передано значение TRUE в и все объекты перешли в свободное состояние, функция возвращает значение WAIT_OBJECT_0. Если же bWaitAll приравнен FALSE, она возвращает управление, как только освобождается любой из объектов. В этом случае возвращается значение от WAIT_OBJECT_0 до WAIT_OBJECT_0 + nCount– 1. Иначе говоря, если возвращаемое значение не равно WAIT_TIMEOUT или WAIT_FAILED, то если вычесть из него значение WAIT_OBJECT_0, то будет получен индекс в массиве описателей, переданном в качестве второго параметра. Индекс подскажет Вам, какой объект перешел в незанятое состояние.

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


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: