TIP 5: IOCP cleanup. (IOCP清理)
The most important thing to remember when performing ICOP cleanup is the same when using overlapped I/O: do not free an overlapped structure if the I/O for it has not yet completed. The HasOverlappedIoCompleted macro allows you to detect if an I/O has completed from its overlapped structure.
切记很重要的一点,当执行使用重叠IO方式的IOCP的清理的时候,如果该I/O仍然没有完成的时候,不要释放重叠结构,HasOverlappedIoCompleted 宏允许你检测,一个I/O是否从它的重叠结构中完成了
There are typically two scenarios for shutting down a server. In the first scenario, you do not care about the completion status of outstanding I/Os and you just want to shut down as fast as you can. In the second scenario, you want to shut down the server, but you do need to know the completion status of each outstanding I/O.
有两种比较好的方案可以关闭一个服务端,第一种方案,你不需要关心未完成的I/O的完成状态,你只要尽可能快地关闭。第二种方案,你想关闭服务端,但是你必须知道每一个未完成的I/O的完成状态。
In the first scenario, you can call PostQueueCompletionStatus (N times, where N is the number of worker threads) to post a special completion packet that informs the worker thread to exit immediately, close all socket handles and their associated overlapped structures, and then close the completion port. Again, make sure you use HasOverlappedIoCompleted to check the completion status of an overlapped structure before you free it. If a socket is closed, all outstanding I/O on the socket eventually complete quickly.
在第一个方案中,你可以调用PostQueueCompletionStatus(N times(次),这里的N是工作器线程的数量)投递一个指定的完成通知包通知工作器线程立即退出,关闭所有的套接字句柄和他们关联的重叠结构,并且关闭其对应的完成端口。再次在释放重叠结构之前用HasOverlappedIoCompleted 来检查和确认这个重叠结构的完成状态,如果套接字被关闭了,所有在这个套接字上的未完成的I/O最终很快会完成
In the second scenario, you can delay exiting worker threads so that all completion packets can be properly dequeued. You can start by closing all socket handles and the IOCP. However, you need to maintain a count of the number of outstanding I/Os so that your worker thread can know when it is safe to exit the thread. The performance penalty of having a global I/O counter protected with a critical section for an IOCP server is not as bad as might be expected because the active worker thread does not switch out if there are more completion packets waiting in the queue.
第二种方案,你可以延迟退出工作器线程,以便所有的完成通知包都能够出列。可以关闭所有套接字jub和IOCP句柄。然而,你需要维护一个未完成的I/O的计数器,以便你的工作器线程能够知道,它什么时候可以安全退出线程。
如果有很多完成通知包在队列中等待的话,激活的工作器线程将无法切换出去,由于这个原因,拥有一个被临界区保护的全局I/O计数器的IOCP服务器的性能将会急剧的下降并导致异常