I/O 保留中の要求をキューから取り出し、処理し、割り当てを解除する従来の IOCP コールバックがあります。
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 ループの使い方を誤解しているのかもしれません。誰かがこのトピックに光を当てることができますか?