Порты завершения ввода-вывода и управление OVERLAPPED

Как win32 управляет экземплярами структуры OVERLAPPED в контексте двух функций:

GetQueuedCompletionStatus
PostQueuedCompletionStatus
  1. Когда я вызываю GetQueuedCompletionStatus, освобождает ли win32 экземпляр структуры OVERLAPPED или я должен сделать это самостоятельно?

  2. Когда я отправляю данные с PostQueuedCompletionStatus, Win32 копирует их во внутренние структуры? Когда я должен освободить память отправленных данных?

  3. Где найти картинку со схемой обработки данных OVERLAPPED между GetQueuedCompletionStatus, PostQueuedCompletionStatus и очередью IOCP?


person Edward83    schedule 14.08.2013    source источник


Ответы (2)


Структура OVERLAPPED должна существовать с момента успешной операции ввода-вывода (или вручную PostQueuedCompletionStatus()) выполняется до тех пор, пока OVERLAPPED не появится из вызова GetQueuedCompletionStatus().

Вы несете ответственность за срок службы конструкции.

Из документов MSDN вы увидите, что GetQueuedCompletionStatus() на самом деле принимает «указатель на переменную, которая получает адрес структуры OVERLAPPED, которая была указана при запуске завершенной операции ввода-вывода». На самом деле вы получаете от этого вызова указатель на исходный OVERLAPPED, который вы передали, когда делали вызов PostQueuedCompletionStatus() (или инициировали перекрывающуюся операцию ввода-вывода).

Все это на самом деле очень полезно, так как «обычный» способ использования структуры OVERLAPPED состоит в том, чтобы поместить ее в более крупную структуру, которая содержит всю информацию «для каждой операции», которая может вам понадобиться, так что это идеальный способ навигации непосредственно из ограниченная информация, которую вы получаете, когда вы вызываете GetQueuedCompletionStatus(), например, буфер данных, который вы использовали в своем перекрывающемся вызове чтения...

Я считаю, что лучший способ справиться со структурами OVERLAPPED - это а) встроить их в буфер, который вы используете для чтения/записи, б) подсчитать их ссылки и в) вернуть их в пул для повторного использования, когда счетчик ссылок упадет до 0.

У меня есть исходный код, который вы можете скачать (здесь), который может сделать это немного более понятным (это полный пример сервера IOCP, поэтому он немного сложен, но он работает и показывает, как эти вещи можно использовать).

person Len Holgate    schedule 14.08.2013
comment
Лен, подскажи пожалуйста, если вызов PostQueuedCompletionStatus() был сделан ОС, а не мной, то должен ли я освобождать полученные данные после GetQueuedCompletionStatus() или в этом случае я не являюсь их владельцем? Под вызовом ОС я подразумеваю, например, может быть сообщение о том, что файл изменен. - person Edward83; 14.08.2013
comment
Все структуры OVERLAPPED, возникающие в результате вызова GetQueuedCompletionStatus(), в какой-то момент изначально принадлежали вам. Вы вызовете функцию, например WSARecv() или ReadDirectoryChangesW(), и передадите OVERLAPPED. НЕТ ситуаций (насколько я знаю), когда вы можете вызвать API, который вызывает завершение, используя OVERLAPPED, который изначально не был предоставлен вами. - person Len Holgate; 14.08.2013

  1. Вы должны передать адрес OVERLAPPED * в GetQueuedCompletionStatus. Это заполняется значением, переданным в PostQueuedCompletionStatus.
  2. Вы не должны освобождать эти данные в контексте PostQueuedCompletionStatus. Это должно быть сделано контекстом с использованием GetQueuedCompletionStatus. (Предполагая, что она была размещена динамически в первую очередь - нет требования, чтобы это была динамически размещенная структура, она могла быть извлечена из фиксированного пула или размещена в стеке функции, которая не возвращается до тех пор, пока не будет получил сигнал о завершении операции).
  3. Я не уверен, что есть такая картина.
person Mats Petersson    schedule 14.08.2013
comment
Матс спасибо! Как я понял, по умолчанию я должен освобождать только свои данные (которые я отправил через PostQueuedCompletionStatus) и только после GetQueuedCompletionStatus? - person Edward83; 14.08.2013