Why CompletionKey in I/O completion port?
Asked Answered
P

0

6

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?

Prisca answered 15/10, 2011 at 18:3 Comment(4)
I've wondered this too. In my servers, the OL struct, buffer instance array, socket class instance and other stuff needed for an IOCP call are all members of an 'IOCPcall' class and the instance stored in the 'hEvent' field. Upon queued completions, I cast the hEvent back to retrieve the IOCPcall and hence the socket object instance. The 'key' is redundant, AFAIK.Ese
Sometimes it's useful to have multiple pieces of independently tracked data. And the "add additional stuff to the overlapped struct" trick isn't always possible.Huynh
It's like asking why window handles have both window bytes and GWLP_USERDATA. In theory you could just cram everything in the GWLP_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
Well it could be that they (Microsoft staffs) didn't realize the use of CONTAINING_RECORD here :). Anyway it's more or less a cheating one...Prisca

© 2022 - 2024 — McMap. All rights reserved.