Remark from MSDN about CompletionKey in CreateIoCompletionPort function:
Use the CompletionKey parameter to help your application track which I/O operations have completed. This value is not used by CreateIoCompletionPort for functional control; rather, it is attached to the file handle specified in the FileHandle parameter at the time of association with an I/O completion port. This completion key should be unique for each file handle, and it accompanies the file handle throughout the internal completion queuing process. It is returned in the GetQueuedCompletionStatus function call when a completion packet arrives. The CompletionKey parameter is also used by the PostQueuedCompletionStatus function to queue your own special-purpose completion packets.
The above remarks leave me a question. Why use the CompletionKey given that we can associate user context with the file handle in an extended overlapped structure like this:
typedef struct s_overlappedplus
{
OVERLAPPED ol;
int op_code;
/*we can alternatively put user context over here instead of CompletionKey*/
LPVOID user_context;
} t_overlappedplus;
and retreive through CONTAINING_RECORD macro after completion?
Cool, I'm only convinced that CompletionKey is per-handle context while the extended overlapped structure is per-I/O one. But what's the philosophy behind such design and in what circumstance can it be necessary to use CompletionKey instead of an extended overlapped structure in term of user context?
GWLP_USERDATA
. In theory you could just cram everything in theGWLP_USERDATA
and never use window bytes. But sometimes it's convenient to have multiple places to stash data, so you don't need to do the multiplexing. (I'm surprised you didn't say "Can't we get rid of the hEvent member, too? I could infer that from the extended overlapped structure too!") – Spirogyra