Многопоточный сервер 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 ответ

Решение

Очевидные проблемы; в порядке важности...

  1. Ваш класс refbuf не использует потокобезопасную обработку подсчета ссылок. использование InterlockedIncrement() и т.п.
  2. Я предполагаю что TakeOvl() получает новый OVERLAPPED а также WSABUF структура на операцию.
  3. Ваше имя может быть лучше, почему grab() скорее, чем AddRef(), что значит TakeOvl() принять от? Эти переменные Tmp являются чем-то, и наименее важным является то, что они являются "временными", поэтому назовите их после чего-то более важного. Перейти читать код завершен.
Другие вопросы по тегам