【发布时间】:2013-03-21 12:36:49
【问题描述】:
我有经典的 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 循环。有人可以对这个话题有所了解吗?
【问题讨论】:
-
提防过早停止。
标签: windows multithreading io iocp