windows – I / O完成端口* LAST *称为回调,或:清除事物的安全
我想这个论点很重要,值得一些空间.
让我们考虑一下C/C++中最常见的I / O完成端口设计, class Stream { enum { Open = 1,Closed = 0 }; // Dtor virtual ~Stream() { if (m_read_packet != 0) delete_packet(m_read_packet); // the same for write packet } // Functions: bool read(...) { if (m_read_packet != 0) m_read_packet = allocate_packet(); ReadFile(m_handle ...); } bool write(...); bool close() { m_state = Closed; if (!CloseHandle(m_handle)) return false; else return true; } // Callbacks: virtual void onRead(...); virtual void onWrite(...); virtual void onEof(); virtual void onClose(); // Other stuff .... // Properties: HANDLE m_handle; int m_state; int m_pending_reads; int m_pending_writes; IoPacket * m_read_packet; IoPacket * m_write_packet; }; 这非常简单,你有这个抽象HANDLE的类,而且 您可以通过自己分配Stream对象来使用此类,或者仅通过让其他类进行分配来使用此类 现在,在这两种情况下,你选择[1]自己分配流(客户端)或2)从其他对象(服务器)] 让我们看看为什么:在执行i / o时,Stream对象指针将包含在IoPacket对象中,而IoPacket对象又由线程池中的其他线程处理和使用,而线程池中的其他线程又使用该指针来调用回调[onRead(),onWrite()等……].您还有`m_pending_reads / writes’变量来查看有多少挂起的读/写.因此,Stream对象指针将在线程之间共享. 此时,让我们考虑您不再需要该连接,并且您希望关闭并释放相关的Stream对象. 如何安全地做到这一点? 我的意思是,如果你只是这样做: stream->close(); delete stream; 你最终会遇到一些崩溃,因为另一个线程可能仍在使用’stream’指针. stream->close(); while ((stream->m_pending_reads != 0) && (stream->m_pending_writes != 0)); delete stream; 但这完全是无效的,因为这会阻塞执行路径,阻塞等待其他线程 void onClose() { delete this; } 所以我的问题是:如何识别我正在处理(在任何线程中)给定句柄的LAST IoPacket(或OVERLAPPED),所以在我可以安全地调用onClose()例程之后删除Stream对象,其中dtor in转而删除缓存的IoPackets,用于执行i / o操作. 现在我使用这个方法:if(用于读取完成)`GetQueuedCompletionStatus()’返回ERROR_OPERATION_ABORTED [所以它意味着CloseHandle(m_handle);已被调用] OR bytes_read == 0 [表示EOF]或者if(state!= Open)那么这意味着它是最后一个读取数据包挂起,然后调用onClose();经过处理后.写数据包将忽略onClose(). 我不确定这是正确的方法,因为即使读取数据包是那些 那些Stream对象衍生物(例如TcpClient)还有其他IoPackets呢?例如一个用于ConnectEx(). 一个可能的解决方案是使用AtomicInt m_total_pending_requests; < - 当这个原子整数达到0时,完成线程调用onClose(); 但是,这最后的解决方案是无效的吗?为什么我使用原子整数来做一个基本的事情,如关闭连接和解除分配它的结构? 也许我完全没有使用那些Stream对象设计IOCPs,但我想这是一个非常常用的抽象HANDLEs设计,所以我想听听IOCP大师的一些意见. 解决方法
引用计数解决了这个问题.
当您执行任何将生成IOCP完成的任何内容时,您只需递增引用计数,并在完成处理完成后递减它.虽然有一些未完成的操作,但您的参考资料是> 1,句柄对象有效.完成所有操作后,您的引用将降为0,并且句柄可以自行删除. 我对数据缓冲区做同样的事情,因为我的代码允许每个连接进行多个并发发送/ recv操作,因此在句柄本身中存储重叠结构不是一种选择. 我有一些代码演示上面的内容,你可以从here下载它. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- windows – NT密码的无效字符
- windows – 内存映射文件:如何监视内存使用情况
- DLL – 为什么VB6编译的应用程序需要VB5 VM?
- windows-service – 从命令提示符显示Windows服务的状态
- ViewMinder方向与Windows Phone 7芒果PhotoCamera
- windows-phone-7 – 如何使用LocationCollection缩放以适应
- 分辨率术语的含义 分辨率术语的含义
- 脚本 – 可以通过Windows登录脚本设置系统环境变量吗?
- user-interface – 使用Winelib移植仅限Windows的GUI工具包
- 从用户空间冻结窗口的方法
- windbg – 如何从DLL堆标记中受益?
- active-directory – AD CS:证书模板不可用
- media-player – 可以在Windows媒体播放器中显示
- 使用 window.requestAnimationFrame 实现动画效果
- windows-server-2012-r2 – 应用dotdefender ISA
- windows-7 – X11桌面与服务器上Win7 VM guest虚
- 如何解决 Windows 实例出现身份验证错误及更正 C
- windows(xshell)免密码登录
- 有了专家系统管理员,Windows和Linux等于安全性
- windows-8 – Windows 8 HTML / JavaScript Metr