Многопоточный сервер IOCP и класс подсчета ссылок
Я работаю на сервере IOCP (перекрывающийся ввод-вывод, 4 потока, CreateIoCompletionPort, GetQueuedCompletionStatus, WSASend и т. Д.). И моя цель состоит в том, чтобы отправить единый буфер с подсчетом ссылок на все подключенные сокеты (я следовал совету Лена Холгейта из этого поста WSAsend на все подключенные сокеты в многопоточном сервере iocp). После отправки буфера всем подключенным клиентам он должен быть удален.
это класс с буфером для отправки
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);
и 1 из 4 потоков
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? Заранее спасибо.
1 ответ
Очевидные проблемы; в порядке важности...
- Ваш класс refbuf не использует потокобезопасную обработку подсчета ссылок. использование
InterlockedIncrement()
и т.п. - Я предполагаю что
TakeOvl()
получает новыйOVERLAPPED
а такжеWSABUF
структура на операцию. - Ваше имя может быть лучше, почему
grab()
скорее, чемAddRef()
, что значитTakeOvl()
принять от? Эти переменные Tmp являются чем-то, и наименее важным является то, что они являются "временными", поэтому назовите их после чего-то более важного. Перейти читать код завершен.