The CreateIoCompletionPort
function allows the creation of a new I/O completion port and the registration of file handles to an existing I/O completion port.
Then, I can use any function, like a recv
on a socket or a ReadFile
on a file with a OVERLAPPED
structure to start an asynchronous operation.
I have to check whether the function call returned synchronously although it was called with an OVERLAPPED
structure and in this case handle it directly. In the other case, when ERROR_IO_PENDING
is returned, I can use the GetQueuedCompletionStatus
function to be notified when the operation completes.
The question which arise are:
How can I remove a handle from the I/O completion port? For example, when I add sockets to the IOCP, how can I remove closed ones? Should I just re-register another socket with the same completion key?
Also, is there a way to make the calls ALWAYS go over the I/O completion port and don't return synchronously?
And finally, is it possible for example to recv
asynchronously but to send
synchronously? For example when a simple echo service is implemented: Can I wait with an asynchronous recv
for new data but send
the response in a synchronous way so that code complexity is reduced? In my case, I wouldn't recv
a second time anyways before the first request was processed.
What happens if an asynchronous ReadFile
has been requested, but before it completes, a WriteFile
to the same file should be processed. Will the ReadFile
be cancelled with an error message and I have to restart the read process as soon as the write is complete? Or do I have to cancel the ReadFile
manually before writing? This question arises in combination with a communication device; so, the write and read should not do problems if happening concurrently.
How can I remove a handle from the I/O completion port?
In my experience you can't disassociate a handle from a completion port. However, you may disable completion port notification by setting the low-order bit of your OVERLAPPED
structure's hEvent
field: See the documentation for GetQueuedCompletionStatus.
For example, when I add sockets to the IOCP, how can I remove closed ones? Should I just re-register another socket with the same completion key?
It is not necessary to explicitly disassociate a handle from an I/O completion port; closing the handle is sufficient. You may associate multiple handles with the same completion key; the best way to figure out which request is associated with the I/O completion is by using the OVERLAPPED
structure. In fact, you may even extend OVERLAPPED
to store additional data.
Also, is there a way to make the calls ALWAYS go over the I/O completion port and don't return synchronously?
That is the default behavior, even when ReadFile
/WriteFile
returns TRUE
. You must explicitly call SetFileCompletionNotificationModes to tell Windows to not enqueue a completion packet when TRUE
and ERROR_SUCCESS
are returned.
is it possible for example to
recv
asynchronously but tosend
synchronously?
Not by using recv
and send
; you need to use functions that accept OVERLAPPED
structures, such as WSARecv
, WSASend
, or alternatively ReadFile
and WriteFile
. It might be more handy to use the latter if your code is meant to work multiple types of I/O handles, such as both sockets and named pipes. Those functions provide a synchronous mode, so if you use those them you can mix asynchronous and synchronous calls.
What happens if an asynchronous ReadFile has been requested, but before it completes, a WriteFile to the same file should be processed?
There is no implicit cancellation. As long as you're using separate OVERLAPPED
structures for each read/write to a full-duplex device, I see no reason why you can't do concurrent I/O operations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With