我在IOCP服务器上工作(重叠I / O,4个线程,CreateIoCompletionPort,GetQueuedCompletionStatus,WSASend等)。我的目标是发送单个引用计数缓冲区所有连接的套接字。(我遵循了Len Holgate的帖子WSAsend to all connected socket in multithreaded iocp server的建议)。在向所有连接的客户端发送缓冲区后,应将其删除。
这是带有要发送的缓冲区的类
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收到所有通知时,mRefCount达到0并执行删除。
我的问题:这种方法是否合适?如果有100个或更多客户端怎么办?当一个线程可以在另一个线程之前删除对象仍然使用它时避免情况吗如何在此scernario中实现原子引用计数?提前谢谢。
答案 0 :(得分:1)
明显的问题;按重要性顺序......
InterlockedIncrement()
等TakeOvl()
每次操作都会获得新的OVERLAPPED
和WSABUF
结构。grab()
而不是AddRef()
,TakeOvl()
取得了什么?那些Tmp变量是最重要的东西,它们是“临时的”,所以在更重要的东西之后命名它们。去阅读代码完成。