
![]()
The IO Completion Port
An I/O Completion Port is a mechanism to deal with asynchronous file I/O. It achieves this by managing a small number of threads in an efficient manner. It is possible to extend the usage of I/O Completion Ports to ignore file operations and utilise the ability to manage threads efficiently. This subject IO Completion Port is typically a chapter of a book.
All this is achieved with 3 procedures
CreateIoCompletionPort()
GetQueuedCompletionStatus()
PostQueuedCompletionstatus()
CreateIoCompletionPort() performs 2 functions
The above operations are done typically during the process initialisation
CreateIoCompletionPort() // Create Port and specify number of
threads (n)
CreateIoCompletionPort() // Associate a file with port - Optional
Createthreads() // (n) identical threads
Now the main cycle of the worker threads begins and each uses GetQueuedCompletionStatus() which will only return when a file operation completes. The worker threads (all identical) have the following structure.
While(1){
GetQueuedCompletionStatus(); // wait for completion of an IO
Process What ever has completed ();
Start another file operation();
}
That is it, all the rest such as how many threads, how threads enter the queues LIFO are either implementation details or too technical at this stage of learning and can come later.
Note. any one who is used to asynchronous operation will find the main loop interesting as normal asynchronous programming is as below
Start Read or Write Overlapped IO()
Do something else()
Wait on file object() // or alert mechanism
I always had trouble finding something else to do. The IO completion is simple and elegant and "Process What ever has completed" makes more sense than do something else.
Yes there is something missing, between the initialisation section and the main loop some operation must be started otherwise GetQueuedCompletionStatus() can never return. This can be done by starting the first file operation before the main loop.
Let us now use an IO port with no IO, we will use the property that IO Ports schedule their threads efficiently.
CreateIoCompletionPort() // Create Port and specify number of
threads (say 8 threads)
// Do not Associate a file with the port
Createthreads() // (8) identical threads
PostQueuedCompletionstatus() // send 8 completion messages, that
is we simulate completed file IO
Now the main cycle of the worker threads begins and each uses GetQueuedCompletionStatus() which will only return when it receives a IO COMPLETION OR AS IN THIS CASE A PostQueuedCompletionstatus() message.
While(1){
GetQueuedCompletionStatus(); // wait for message
This threads job();
PostQueuedCompletionstatus(); // throw in another completion
message - ad infintum
}
What have I missed, a lot
IO Completion Ports are a lot simpler than they first appear, a good article in C/C++ Users Journal April 1998, General-purpose Threads with I/O Completion ports, Kevin T. Manley wraps the above function calls in C++ classes to provide easy to use interfaces.
Summary
CreateIoCompletionPort creates port and attaches file, socket
etc
Create identical threads, this is a bit obvious, but I like to
stress it
GetQueuedCompletionStatus waits for an IO to complete, as above
stress, any IO associated with this port.
PostQueuedCompletionstatus allows us too simulate IO completing
and use IO ports for other non file IO uses.
End

@Copyright 2003 by Dwarf .