我正在使用Windows中的I/O完成端口,我有一个叫做"Stream"的对象,它类似于抽象HANDLE(因此它可以是套接字、文件等)。
当我调用Stream::read()或Stream::write()(如在文件情况下的ReadFile()/WriteFile()和在套接字情况下的WSARecv()/WSASend())时,我会分配一个新的OVERLAPPED结构,以便创建一个挂起的I/O请求,该请求将由其他线程在IOCP循环中完成。
然后,当OVERLAPPED结构由IOCP循环完成时,它将在那里被销毁。如果是这种情况,Stream::read()或Stream::write()将再次从IOCP循环调用,它们将实例化新的OVERLAPPED结构,并且会一直进行下去。
这很好用。但现在我想通过添加OVERLAPPED对象的缓存来改进它:当我的Stream对象执行大量读取或写入时,缓存OVERLAPPED结构是绝对有意义的。
但现在出现了一个问题:当我取消分配Stream对象时,我必须取消分配缓存的OVERLAPPED结构,但我怎么知道它们已经完成还是仍在挂起,而某个IOCP循环最终会完成它们呢?因此,这里需要一个原子引用计数,但现在问题是,如果我使用原子引用计数,我必须为每个读取或写入操作增加该引用计数,并在完成OVERLAPPED结构的IOCP循环或Stream删除时减少,这在服务器上是大量的操作,因此我最终会大量的增加/减少原子计数器。
这会非常负面地影响多线程的并发性吗?这是我唯一担心的事情,阻止我将此原子引用计数器放在每个OVERLAPPED结构中。
我的担忧是无基础的吗?
我认为这是一个重要的话题,值得指出,在SO上提问,以了解其他人对此的看法和使用IOCP缓存OVERLAPPED结构的方法是值得的。如果可能的话,我希望找到一个聪明的解决方案,而不使用原子引用计数器。
当我调用Stream::read()或Stream::write()(如在文件情况下的ReadFile()/WriteFile()和在套接字情况下的WSARecv()/WSASend())时,我会分配一个新的OVERLAPPED结构,以便创建一个挂起的I/O请求,该请求将由其他线程在IOCP循环中完成。
然后,当OVERLAPPED结构由IOCP循环完成时,它将在那里被销毁。如果是这种情况,Stream::read()或Stream::write()将再次从IOCP循环调用,它们将实例化新的OVERLAPPED结构,并且会一直进行下去。
这很好用。但现在我想通过添加OVERLAPPED对象的缓存来改进它:当我的Stream对象执行大量读取或写入时,缓存OVERLAPPED结构是绝对有意义的。
但现在出现了一个问题:当我取消分配Stream对象时,我必须取消分配缓存的OVERLAPPED结构,但我怎么知道它们已经完成还是仍在挂起,而某个IOCP循环最终会完成它们呢?因此,这里需要一个原子引用计数,但现在问题是,如果我使用原子引用计数,我必须为每个读取或写入操作增加该引用计数,并在完成OVERLAPPED结构的IOCP循环或Stream删除时减少,这在服务器上是大量的操作,因此我最终会大量的增加/减少原子计数器。
这会非常负面地影响多线程的并发性吗?这是我唯一担心的事情,阻止我将此原子引用计数器放在每个OVERLAPPED结构中。
我的担忧是无基础的吗?
我认为这是一个重要的话题,值得指出,在SO上提问,以了解其他人对此的看法和使用IOCP缓存OVERLAPPED结构的方法是值得的。如果可能的话,我希望找到一个聪明的解决方案,而不使用原子引用计数器。