The parameters to PostQueuedCompletionStatus are not interpreted

Date:May 25, 2007 / year-entry #187
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20070525-00/?p=26693
Comments:    6
Summary:Larry Osterman mentioned this almost in passing quite a while ago, that the parameters to PostQueuedCompletionStatus are not interpreted by the operating system. Well, obviously the first parameter, the handle to the completion port, is interpreted as the handle to the completion port. But the other parameters, dwNumberOfBytesTransferred, dwCompletionKey, and lpOverlapped are not interpreted at...

Larry Osterman mentioned this almost in passing quite a while ago, that the parameters to PostQueuedCompletionStatus are not interpreted by the operating system. Well, obviously the first parameter, the handle to the completion port, is interpreted as the handle to the completion port. But the other parameters, dwNumberOfBytesTransferred, dwCompletionKey, and lpOverlapped are not interpreted at all. Even though they have names, the names don't mean anything. Whatever values you pass for those three parameters merely pop out of GetQueuedCompletionStatus when the notification packet makes it to the head of the queue.

Why do the parameters have names if the names don't mean anything?

Because the operating system itself will post notifications to the completion port if you ask it to, and in that case, the values returned by the GetQueuedCompletionStatus function really mean something related to their names. For example, if you issued an asynchronous read to a file that is associated with a completion port, then the dwNumberOfBytesTransferred really is the number of bytes transferred, the dwCompletionKey really is the completion key that you associated with the file handle when you called CreateIoCompletionPort, and the lpOverlapped really is the pointer to the OVERLAPPED structure that you originally issued the read request against.

But if you call PostQueuedCompletionStatus manually, then you can choose any values you want. Of course, if you're going to mix operating system-generated completion port activity with manually-generated completion port activity, it would be in your best interest to use the dwCompletionKey (or if you're really clever, the lpOverlapped) in a consistent manner so that you can tell whether a notification came from the I/O subsystem or was one you generated manually.

But it's up to you.


Comments (6)
  1. Nathan says:

    Ray, is there a, uh, deeper motivation for today’s entry ? Or was this (next?)  in your ‘list of articles I plan on writing’ ?

    [Somebody asked about it, so I figured I’d answer. -Raymond]
  2. Yoni says:

    You know, while programming in Win32, I’ve come across many cases where it seemed as if a certain interface’s design is influenced directly by another part of the operating system. Sure, the UI team, the kernel team, and the Internet Explorer team are all working on the OS together. But sometimes it feels like I’m disadvantaged that they can have such a direct effect on each other, and I can’t add functions to kernel32 as I wish.

    GetQueuedCompletionStatus could easily have had 1 extra ULONG_PTR-sized parameter, like most callback mechanisms do. But it has 3, because in the part of the operating system that sometimes posts queued completion status, this way is more convenient.

    Just my ranting…

  3. Leo Davidson says:

    I’m happy so long as there is at least one void* (or equivalent typedef such as ULONG_PTR) argument that we can specify. If there’s more than one then it doesn’t get in the way. If there are zero, however, then things are painful.

    I recently had to use the EnumSystemCodePages API which calls your callback function with just a string. What should’ve been 5 lines of code turned into a wrapper class with critical sections that enumerated into a static vector and then copied the results to the calling thread’s vector. It’s strange that there isn’t an EnumSystemCodePagesEx which fixes the obvious mistake. I guess the API doesn’t get used enough to warrant it or something.

  4. KJK::Hyperion says:

    Leo: you can use TLS when you have no other way of passing data to a synchronous callback

  5. kb says:

    Is there a way to query the number of items currently waiting in the queue?

  6. BryanK says:

    kb — No, since as soon as the query function returns, the data is old and probably invalid.

    Any thread can post to the queue, and any thread (in theory anyway) can read from the queue.  So the thread that asks the size of the queue may be running concurrently with threads that are modifying its size.

    The only possible good reason for asking the queue how large it is (that I can think of) is if you need to know when it’s empty to know when your work is done.  You’d have to be sure to post all the items to it before you start asking its length, though.

    But that problem is (IMO) better solved by having a single "end of queue" item that gets posted to the queue at the end, and then having the worker thread(s) signal a "work finished" event when they pull this item off.  The thread interested in the queue’s state can wait on this event.  (Then you don’t care how often the queue’s count goes to zero, either: you won’t get signaled until the last item is consumed.)

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index