我有经典的 IOCP 回调,它将 i/o 挂起的请求出列,处理它们,并以这种方式释放它们:
struct MyIoRequest { OVERLAPPED o; /* ... other params ... */ };
bool is_iocp_active = true;
DWORD WINAPI WorkerProc(LPVOID lpParam)
{
ULONG_PTR dwKey;
DWORD dwTrans;
LPOVERLAPPED io_req;
while(is_iocp_active)
{
GetQueuedCompletionStatus((HANDLE)lpParam, &dwTrans, &dwKey, (LPOVERLAPPED*)&io_req, WSA_INFINITE);
// NOTE, i could use GetQueuedCompletionStatusEx() here ^ and set it in the
// alertable state TRUE, so i can wake up the thread with an ACP request from another thread!
printf("dequeued an i/o request\n");
// [ process i/o request ]
...
// [ destroy request ]
destroy_request(io_req);
}
// [ clean up some stuff ]
return 0;
}
然后,在代码中我将有某个地方:
MyIoRequest * io_req = allocate_request(...params...);
ReadFile(..., (OVERLAPPED*)io_req);
这很完美。
现在我的问题是:我想立即关闭 IOCP 队列而不引起泄漏怎么办?(例如应用程序必须退出)我的意思是:如果我将 is_iocp_active 设置为'false',下一次 GetQueuedCompletionStatus() 将出列一个新的 i/o 请求,这将是最后一个 i/o 请求:它将返回,导致线程根据 MSDN,当一个线程退出时,系统会简单地取消其所有挂起的 i/o 请求。
但是我在调用 ReadFile() 时实例化的“MyIoRequest”类型的结构根本不会被销毁:系统已取消挂起的 i/o 请求,但我必须手动销毁我创建的那些结构,否则我将当我停止循环时泄漏所有待处理的 i/o 请求!
那么,我该怎么做呢?仅将该变量设置为 false 来停止 IOCP 循环是错误的吗?请注意,即使我使用 APC 请求停止可警报线程,也会发生这种情况。
我想到的解决方案是将每个“MyIoRequest”结构添加到队列/列表中,然后在 GetQueuedCompletionStatusEx 返回时将它们出列,但这不应该造成瓶颈,因为此类 MyIoRequest 结构的入队/出队过程必须是互锁?也许我误解了如何使用 IOCP 循环。有人可以对这个话题有所了解吗?