Структуры OVERLAPPED
Структуры OVERLAPPED
С помощью структуры OVERLAPPED (указываемой, например, параметром lpOverlapped функции ReadFile) можно указывать следующую информацию:
• Позицию в файле (64 бита), с которой должно начинаться выполнение операции чтения или записи в соответствии с обсуждением, которое содержится в главе 3.
• Событие (сбрасываемое вручную), которое будет переходить в сигнальное состояние по завершении соответствующей операции.
Ниже приводится определение структуры OVERLAPPED.
typedef struct_OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED
Для задания позиции в файле (указателя) должны использоваться оба поля Offset и OffsetHigh, хотя старшая часть указателя (OffsetHigh) во многих случаях равна 0. Не следует использовать поля Internal и InternalHigh, зарезервированные для системных нужд.
Параметр hEvent — дескриптор события (созданного посредством функции CreateEvent). Это событие может быть как именованным, так и неименованным, но оно должно быть обязательно сбрасываемым вручную (см. главу 8), если используется для перекрывающегося ввода/вывода; причины этого будут вскоре объяснены. По завершении операции ввода/вывода событие переходит в сигнальное состояние.
В другом возможном варианте его использования дескриптор hEvent имеет значение NULL; в этом случае программа может ожидать перехода в сигнальное состояние дескриптора файла, который также может выступать в роли объекта синхронизации (см. приведенные далее предостережения). Система использует для отслеживания завершения операций сигнальные состояния дескриптора файла, если дескриптор hEvent равен NULL, то есть объектом синхронизации в этом случае является дескриптор файла.
Примечание
В целях удобства термин "дескриптор файла" ("file handle"), используемый по отношению к дескрипторам, указываемым при вызове функций ReadFile, WriteFile и так далее, будет применяться нами даже в тех случаях, когда речь идет о дескрипторах именованного канала или устройства, а не файла.
При выполнении вызова функций ввода/вывода это событие сразу же сбрасывается системой (устанавливается в несигнальное состояние). Когда операция ввода/вывода завершается, событие устанавливается в сигнальное состояние и остается в нем до тех пор, пока не будет использовано другой операцией ввода/вывода. Событие должно быть сбрасываемым вручную, если его перехода в сигнальное состояние могут ожидать несколько потоков (хотя в наших примерах используется всего один поток), и на момент завершения операции они могут не находиться в состоянии ожидания.
Даже если дескриптор файла является синхронным (то есть созданным без флага FILE_FLAG_OVERLAPPED), структура OVERLAPPED может послужить в качестве альтернативы функции SetFilePointer для указания позиции в файле. В этом случае возврат после вызова функции ReadFile или иного вызова не происходит до тех пор, операция ввода/вывода пока не завершится. Этой возможностью мы уже воспользовались в главе 3. Также обратите внимание на то, что незавершенные операции ввода/вывода однозначно идентифицируются комбинацией дескриптора файла и соответствующей структуры OVERLAPPED.
Ниже перечислены некоторые предостережения, которые следует принимать во внимание.
• Не допускайте повторного использования структуры OVERLAPPED в то время, когда связанная с ней операция ввода/вывода, если таковая имеется, еще не успела завершиться.
• Аналогичным образом, избегайте повторного использования события, указанного в структуре OVERLAPPED.
• Если существует несколько незакрытых запросов, относящихся к одному и тому же перекрывающемуся дескриптору, используйте для синхронизации не дескрипторы файлов, а дескрипторы событий.
• Если структура OVERLAPPED или событие выступают в качестве автоматических переменных внутри блока, обеспечьте невозможность выхода из блока до синхронизации с операцией ввода/вывода. Кроме того, во избежание утечки ресурсов следует позаботиться о закрытии дескриптора до выхода из блока.