Здравствуйте!
Имеется программа, которая создаёт очередь и шесть тредов, первые пять ложат сообщения в очередь, шестой их оттуда вынимает по мере готовности и обрабатывает. Все шесть тредов созданы стандартным вызовом 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 написано, что она должна самостоятельно уменьшать счётчик использования семафора при наступлении отпускающих условий. На практике такого не происходит. Может кто нибудь подсказать, что я не так делаю, почему такое вопиющее несоответствие документации?
С уважением,
Артём.