我在 IOCP 服务器上工作(重叠 I/O、4 线程、CreateIoCompletionPort、GetQueuedCompletionStatus、WSASend 等)。我的目标是向所有连接的套接字发送单个引用计数缓冲区。(我遵循了 Len Holgate 在这篇文章中的建议WSAsend 到多线程 iocp 服务器中所有已连接的套接字 https://stackoverflow.com/questions/19760522/wsasend-to-all-connected-socket-in-multithreaded-iocp-sever)。将缓冲区发送到所有连接的客户端后,应将其删除。
这是带有要发送的缓冲区的类
class refbuf
{
private:
int m_nLength;
int m_wsk;
char *m_pnData; // buffer to send
mutable int mRefCount;
public:
...
void grab() const
{
++mRefCount;
}
void release() const
{
if(mRefCount > 0);
--mRefCount;
if(mRefCount == 0) {delete (refbuf *)this;}
}
...
char* bufadr() { return m_pnData;}
};
发送缓冲区到所有套接字
refbuf *refb = new refbuf(4);
...
EnterCriticalSection(&g_CriticalSection);
pTmp1 = g_pCtxtList; // start of linked list with sockets
while( pTmp1 )
{
pTmp2 = pTmp1->pCtxtBack;
ovl=TakeOvl(); // ovl -struct containing WSAOVERLAPPED
ovl->wsabuf.buf=refb->bufadr();// adress m_pnData from refbuf
ovl->rcb=refb; //when GQCS get notification rcb is used to decrease mRefCount
ovl->wsabuf.len=4;
refb->grab(); // mRefCount ++
WSASend(pTmp1->Socket, &(ovl->wsabuf),1,&dwSendNumBytes,0,&(ovl->Overlapped), NULL);
pTmp1 = pTmp2;
}
LeaveCriticalSection(&g_CriticalSection);
和 4 个线程中的 1 个
GetQueuedCompletionStatus(hIOCP, &dwIoSize,(PDWORD_PTR)&lpPerSocketContext, (LPOVERLAPPED *)&lpOverlapped, INFINITE);
...
lpIOContext = (PPER_IO_CONTEXT)lpOverlapped;
lpIOContext->rcb->release(); //mRefCount --,if mRefCount reach 0, delete object
我用 5 个连接的客户端检查了这一点,它似乎有效。当GQCS收到所有通知时,RefCount达到0并执行删除。
我的问题是:这种方法合适吗?如果有 100 个或更多客户怎么办?当一个线程可以在另一个线程仍然使用对象之前删除该对象时,是否可以避免这种情况?在这种情况下如何实现原子引用计数?提前致谢。