Все ограничения функции работают в совокупности: если не выполняется хотя бы одно из условий, ограничения всей функции считаются невыполненными

Клиент столкнулся с проблемой при использовании функции WaitForMultipleObjects:

Мы пытаемся прояснить детали поведения функции WaitForMultipleObjects. У нас есть поток, который ожидает два дескриптора (назовем их Handle1 и Handle2) при помощи функции WaitForMultipleObjects, параметр bWaitAll которой установлен в FALSE. В некоторых случаях, в процессе ожидания мы переводим дескриптор Handle1 в сигнальное состояние и закрываем из другого потока дескриптор Handle2. Это приводит к тому, что функция возвращает WAIT_FAILED. Из документации в MSDN не совсем понятно, каким должно быть поведение функции в этом случае. С одной стороны там написано:

  1. Когда параметр bWait равен FALSE, функция проверяет дескрипторы в массиве по порядку, начиная с элемента с индексом 0, пока не найдет дескриптор, находящийся в сигнальном состоянии. Если в сигнальном состоянии находятся несколько объектов, функция вернет индекс первого элемента массива, соответствующего дескриптору, находящемуся в сигнальном состоянии.

Это описание подразумевает, что ожидание будет завершаться успешно всегда, поскольку функция должна будет определить, что Handle1 находится в сигнальном состоянии до того, как она обнаружит, что Handle2 некорректен.

С другой стороны в документации также написано:

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

Какое поведение гарантируется в этом случае?

Как только вы нарушаете ограничение (в данном случае ограничением является условие корректности дескриптора на протяжении всего процесса ожидания), требования функции считаются невыполненными и ее поведение становится неопределенным. Вы не можете сказать: «Ну, конечно, так делать нельзя, но если в точности следовать алгоритму, приведенному в описании процесса выбора сигнального объекта, то функция вообще не должна об этом узнать. Следовательно, тот факт, что я нарушил одно из правил, ни на что не влияет!»

Описание поведения функции WaitForMultipleObjects с параметром bWait, равным FALSE, не является техническим описанием реализации функции. Это описание того, как следует интерпретировать поведение функции. Алгоритмический способ описания поведения функции выбран лишь для того, чтобы проще было понять поведение функции. Это не означает, что функция в действительности выполняет этот алгоритм, шаг за шагом. (В действительности, в реализации функции нет никакого цикла опроса, как это указано в описании. Ожидание всех дескрипторов производится одновременно. Это что-то вроде интеграла Лебега, в котором интегрируется сразу всю область значений).

Описание поведения функции, когда параметр bWait равен FALSE, в неалгоритмическом виде будет примерно таким:

  1. Когда параметр bWait равен FALSE, функция не возвращает значения до тех пор, пока один из дескрипторов в массиве не перейдет в сигнальное состояние. Возвращаемое значение будет равно наименьшему индексу элемента массива, соответствующего дескриптору, перешедшему в сигнальное состояние.

Это описание является исключительно повествовательным, но при этом оно сложнее для понимания.

Это все равно что сказать: «Вода сохраняет свой уровень одинаковым в пределах сосуда». Вода не может вести себя как одушевленный предмет, но описание ее поведения в такой форме гораздо понятнее.