I'm trying to use IOCP relying on Windows API CreateThreadpoolIo
and StartThreadpoolIo
, but I found the thread pool is just to make the code behind the IO completed parallel. The async IO submit operations are also execute sequentially in the main thread. So why we need this? I think make the IO submit operations parallel can improve the throughput even if they are async operations, right?
The other cost is if we make them parallel, we might need to lock something to guarantee data consistency (thread safe operation).
CodePudding user response:
It is possible to do IOCP without using CreateThreadpool / StartThreadpoolIo, in that case you have to manage calling GetQueuedCompletionStatus yourself (whether in a self-managed thread pool or otherwise - it is even conceivable that it could be interleaved into the actions of the thread that started the I/O, but in that case why bother with IOCP?). StartThreadpoolIO is needed in order to have a thread waiting on GetQueuedCompletionStatus instead of WaitForMultipleObjects (or one of its variants). CancelThreadpoolIo decrements a counter saying how many IOCP operations are outstanding and if that counter reaches 0 the thread pool knows it can stop waiting on GetQueuedCompletionStatus.
CodePudding user response:
CreateThreadpoolIo
- create object TP_IO
and call ZwSetInformationFile
with FileCompletionInformation
and FILE_COMPLETION_INFORMATION
for set CompletionContext
in FILE_OBJECT
. as result - if we do I/O on file, when it finished (if no synchronous error returned and we pass not zero ApcContext
) - system queue packet to I/O port ( which we provide in FILE_COMPLETION_INFORMATION
) with Key
(from FILE_COMPLETION_INFORMATION
) and ApcContext
(form concrete I/O call. win32 api always pass pointer to OVERLAPPED
here). the user callback address (IoCompletionCallback
) stored inside TP_IO
StartThreadpoolIO
increment reference count on TP_IO
and CancelThreadpoolIo
(and CloseThreadpoolIo
) decrement this reference count. this need for manage life time of TP_IO
- before we start any I/O operation - need increment reference count on TP_IO
. when I/O finished - packet will be queued to I/O port. one of Threads from pool pop this packet. got Key
( lpCompletionKey
) convert it to pointer to TP_IO
and call user callback IoCompletionCallback
. after callback return - system decrement reference count to TP_IO
. if the I/O fail synchronous - will be no packet, no callback. so need direct decrement reference count to TP_IO
- for this need call CancelThreadpoolIo