CMultiLock странное поведение с семафором
От: tyoma75  
Дата: 28.03.10 02:21
Оценка:
Здравствуйте!

Имеется программа, которая создаёт очередь и шесть тредов, первые пять ложат сообщения в очередь, шестой их оттуда вынимает по мере готовности и обрабатывает. Все шесть тредов созданы стандартным вызовом MFC — AfxBeginThread();

m_pInsertingThreadn = AfxBeginThread(InsertingThread, this, 0, 0, CREATE_SUSPENDED);
m_pInsertingThreadn->m_bAutoDelete = FALSE;
m_pInsertingThreadn->ResumeThread();


Каждый тред, который ложит сообщение в очередь работает одинаково

class CMyClass
{
public:
     CMyClass(void) 
       : m_Sync1(0, MAX_ELEMENTS)
       , m_Sync2(0, MAX_ELEMENTS)
       , m_Sync3(0, MAX_ELEMENTS)
       , m_Sync4(0, MAX_ELEMENTS)
       , m_Sync5(0, MAX_ELEMENTS)
      {
            m_Syncs.Add(m_Sync1);
            m_Syncs.Add(m_Sync2);
            m_Syncs.Add(m_Sync3);
            m_Syncs.Add(m_Sync4);
            m_Syncs.Add(m_Sync5);
      }

     ~CMyClass(void) 
     {
     }

private:
     CSemaphore m_Sync1;
     CSemaphore m_Sync2;
     CSemaphore m_Sync3;
     CSemaphore m_Sync4;
     CSemaphore m_Sync5;
     CArray<CSyncObject *> m_Syncs;
     

private:
     static UINT AFX_CDECL InsertingThread1(LPVOID pParam);
     static UINT AFX_CDECL InsertingThread2(LPVOID pParam);
     static UINT AFX_CDECL InsertingThread3(LPVOID pParam);
     static UINT AFX_CDECL InsertingThread4(LPVOID pParam);
     static UINT AFX_CDECL InsertingThread5(LPVOID pParam);
     static UINT AFX_CDECL RemovingThread(LPVOID pParam);
};

UINT AFX_CDECL CMyClass::InsertingThreadn(LPVOID pParam)
{
    CMyClass *pThis = static_cast<CMyClass *>(pParam);
    ASSERT(pThis);

        while(true)
        {
            // Что-то делаем здесь, по готовности отпускаем семафор
            pThis->m_Syncn.Unlock;
        }

    return 0;
}


UINT AFX_CDECL CMyClass::RemovingThread(LPVOID pParam)
{
    CMyClass *pThis = static_cast<CMyClass *>(pParam);
    ASSERT(pThis);
         
        CMultiLock cLock(m_Syncs.GetData(), m_Syncs.GetCount);

        while(true)
        {
           DWORD dwRet = cLock.Lock(INFINITE, FALSE) - WAIT_OBJECT_0;

m_Syncs.GetAt(dwRet).Lock(); // Без этого вызова программа не работает

           switch(dwRet)
           {
             case 0:
                // обрабатываем событие
                break;  
             case 1:
                // обрабатываем событие
                break;  
             case 2:
                // обрабатываем событие
                break;  
             case 3:
                // обрабатываем событие
                break;  
             case 4:
                // обрабатываем событие
                break;  
             default:
                break;
           }
        }

    return 0;
}


Требование — программа должна обрабатывать поступившие сообщения в одном треде.
В этом коде, при первом же отпускании любого семафора в функции InsertingThread, цикл в функции RemovingThread начинает выполняться без остановки на вызове cLock.Lock(), даже если Unlock для соответствующего семафора вызывался только раз. Добавление m_Syncs.GetAt(dwRet).Lock(); проблему решает. Но в доке к WaitForMultipleObject написано, что она должна самостоятельно уменьшать счётчик использования семафора при наступлении отпускающих условий. На практике такого не происходит. Может кто нибудь подсказать, что я не так делаю, почему такое вопиющее несоответствие документации?

С уважением,
Артём.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.