Создание инверсных семафоров и типов данных, безопасных в многопоточной среде - часть 7
Нет — все делается наоборот. Теперь, если Вы хотите, чтобы поток ждал нулевого значения объекта данных, от Вас требуется лишь следующее:
CWhenZero<BYTE> b = 0; // безопасная переменная типа BYTE
// немедленно возвращает управление, так как b равна 0
WaitForSingleObject(b, INFINITE);
b = 5;
// возвращает управление, только если другой поток присваивает D нулевое значение
WaitForSingleObject(b, INFINITE);
Вы можете вызывать WaitForSingleObject именно таким образом, потому что класс CWhenZero включает и функцию-член оператора приведения, которая приводит объект CWhenZero к типу HANDLE объекта ядра. Иначе говоря, передача С++-объекта CWhenZero любой Windows-функции, ожидающей HANDLE, приводит к автоматическому вызову функции-члена оператора приведения, возвращаемое значение которой и передастся Windows-функции. В данном случае эта функция-член возвращает описатель объекта ядра "событие" m_hevtZero.
Описатель события m_hevtNotZero внутри класса CWhenZero позволяет писать код, ждущий ненулевого значения объекта данных. К сожалению, в класс нельзя включить второй оператор приведения HANDLE — для получения описателя m_hevtNotZero. Поэтому мне пришлось добавить функцию-член GetNotZeroHandle, которая используется так.
CWhenZero<BYTE> b = 5; // безопасная переменная типа BYTE
// немедленно возвращает управление, так как b не равна 0
WaitForSingleObject(b GetNotZeroHandle(), INFINITE);
b = 0,
// возвращает управление, только если другой поток присваивает b ненулевое значение WaitForSingleObject(b.GetNotZeroHandle(), INFINITE);