windows-nt/Source/XPSP1/NT/enduser/netmeeting/av/rrcm/rtp/thread.cpp
2020-09-26 16:20:57 +08:00

119 lines
2.5 KiB
C++

#include "stdafx.h"
#include "thread.h"
// general purpose worker thread
// The thread exists in an alertable Wait state and does most of its work
// in APCs.
CEventThread::CEventThread()
{
InitializeCriticalSection(&m_cs);
m_uRef=0;
m_dwFlags = 0;
m_hThread = 0;
m_hSignalEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
m_hAckEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
}
CEventThread::~CEventThread()
{
DeleteCriticalSection(&m_cs);
if (m_hSignalEvent)
CloseHandle(m_hSignalEvent);
if (m_hAckEvent)
CloseHandle(m_hAckEvent);
}
BOOL
CEventThread::Start()
{
BOOL fRet;
EnterCriticalSection(&m_cs);
if (++m_uRef == 1)
{
m_hThread = CreateThread(
NULL,0,
EventThreadProc,
this, 0, &m_idThread);
}
fRet = !!m_hThread;
LeaveCriticalSection(&m_cs);
return fRet;
}
BOOL
CEventThread::Stop()
{
BOOL fRet;
EnterCriticalSection(&m_cs);
if (--m_uRef == 0)
{
m_dwFlags |= CTHREADF_STOP;
SetEvent(m_hSignalEvent);
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
m_hThread = NULL;
m_dwFlags &= ~CTHREADF_STOP;
}
LeaveCriticalSection(&m_cs);
return TRUE;
}
DWORD
CEventThread::ThreadMethod()
{
DWORD dwWait;
while (1) {
dwWait = WaitForSingleObjectEx(m_hSignalEvent, INFINITE, TRUE);
if (dwWait == WAIT_OBJECT_0)
{
if (m_dwFlags & CTHREADF_STOP)
{
break; // exit thread
}
}
else if (dwWait == WAIT_IO_COMPLETION)
{
}
else
if (dwWait == WAIT_FAILED)
{
break; // exit thread
}
}
return dwWait;
}
// Executes the CallProc in the worker thread in a synchronous fashion
// (similar to SendMessage). When this method returns the CallProc has been called
// and the return value is returned.
BOOL CEventThread::CallNow(THREADCALLBACK CallProc, PVOID pParam, DWORD dwParam)
{
BOOL fRet = FALSE;
EnterCriticalSection(&m_cs);
m_Callback.CallProc = CallProc;
m_Callback.pParam = pParam;
m_Callback.dwParam = dwParam;
ResetEvent(m_hAckEvent);
if (QueueUserAPC(HandleCallNowAPC, m_hThread, (DWORD)this))
{
DWORD dwWait;
dwWait = WaitForSingleObject(m_hAckEvent, INFINITE);
if (dwWait == WAIT_OBJECT_0)
fRet = (BOOL) m_Callback.dwParam; //get the cached return value
}
LeaveCriticalSection(&m_cs);
return fRet;
}
void APIENTRY CEventThread::HandleCallNowAPC(DWORD dwArg)
{
CEventThread *pThis = (CEventThread *)dwArg;
if (pThis->m_Callback.CallProc)
{
pThis->m_Callback.dwParam = pThis->m_Callback.CallProc(pThis->m_Callback.pParam, pThis->m_Callback.dwParam);
SetEvent(pThis->m_hAckEvent);
}
}