Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

244 lines
7.3 KiB

///////////////////////////////////////////////////////////////////////////
//
// Copyright(C) 1999 Microsoft Corporation all rights reserved.
//
// Module: workerthread.cpp
//
// Project: Chameleon
//
// Description: Generic Worker Thread Class Implementation
//
// Log:
//
// When Who What
// ---- --- ----
// 02/08/1999 TLP Initial Version
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "workerthread.h"
#include <process.h>
//////////////////////////////////////////////////////////////////////////
//
// Function: Constructor
//
// Synopsis: Initialize the worker thread object
//
//////////////////////////////////////////////////////////////////////////
CTheWorkerThread::CTheWorkerThread()
{
m_ThreadInfo.bExit = true;
m_ThreadInfo.bSuspended = true;
m_ThreadInfo.hWait = NULL;
m_ThreadInfo.hExit = NULL;
m_ThreadInfo.hThread = NULL;
m_ThreadInfo.dwThreadId = 0;
m_ThreadInfo.dwWaitInterval = 0;
m_ThreadInfo.pfnCallback = NULL;
}
//////////////////////////////////////////////////////////////////////////
//
// Function: Destructor
//
// Synopsis: Syncronize the destruction of the worker thread with
// the worker thread object.
//
//////////////////////////////////////////////////////////////////////////
CTheWorkerThread::~CTheWorkerThread()
{
End(INFINITE, false);
}
//////////////////////////////////////////////////////////////////////////
//
// Function: StartThread
//
// Synopsis: Start the worker thread on its merry way
//
//////////////////////////////////////////////////////////////////////////
bool CTheWorkerThread::Start(
/*[in]*/ DWORD dwWaitInterval,
/*[in]*/ Callback* pfnCallback
)
{
_ASSERT( m_ThreadInfo.hThread == NULL && NULL != pfnCallback );
bool bReturn = false;
if ( NULL == m_ThreadInfo.hThread )
{
m_ThreadInfo.pfnCallback = pfnCallback;
if ( dwWaitInterval )
{
m_ThreadInfo.dwWaitInterval = dwWaitInterval;
m_ThreadInfo.bExit = false;
}
m_ThreadInfo.hWait = CreateEvent(NULL, TRUE, FALSE, NULL);
if ( NULL != m_ThreadInfo.hWait )
{
m_ThreadInfo.hExit = CreateEvent(NULL, TRUE, FALSE, NULL);
if ( NULL != m_ThreadInfo.hExit )
{
m_ThreadInfo.hThread = (HANDLE) _beginthreadex(
NULL,
0,
CTheWorkerThread::ThreadFunc,
&m_ThreadInfo,
0,
&m_ThreadInfo.dwThreadId
);
if ( m_ThreadInfo.hThread )
{
bReturn = true;
}
}
}
}
return bReturn;
}
//////////////////////////////////////////////////////////////////////////
//
// Function: EndThread
//
// Synopsis: Attempt to end the worker thread
//
//////////////////////////////////////////////////////////////////////////
bool CTheWorkerThread::End(
/*[in]*/ DWORD dwTimeOut,
/*[in]*/ bool bTerminateAfterWait
)
{
bool bReturn = true;
if ( m_ThreadInfo.hThread )
{
bReturn = false;
// Set thread exiting flag to true (see ThreadFunc below...)
m_ThreadInfo.bExit = true;
// Resume our worker (if its currently suspended otherwise no-op)
Resume();
// Wake it up if its idle
SetEvent(m_ThreadInfo.hWait);
// Wait for it to exit
if ( WAIT_OBJECT_0 != WaitForSingleObjectEx(m_ThreadInfo.hExit, dwTimeOut, FALSE) )
{
if ( bTerminateAfterWait )
{
_endthreadex((unsigned)m_ThreadInfo.hThread);
// OK, we're without a thread now...
CloseHandle(m_ThreadInfo.hWait);
CloseHandle(m_ThreadInfo.hExit);
CloseHandle(m_ThreadInfo.hThread);
m_ThreadInfo.hThread = NULL;
bReturn = true;
}
}
else
{
// OK, we're without a thread now...
CloseHandle(m_ThreadInfo.hWait);
CloseHandle(m_ThreadInfo.hExit);
CloseHandle(m_ThreadInfo.hThread);
m_ThreadInfo.hThread = NULL;
bReturn = true;
}
}
return bReturn;
}
//////////////////////////////////////////////////////////////////////////
//
// Function: SuspendThread
//
// Synopsis: Suspend the worker thread
//
//////////////////////////////////////////////////////////////////////////
void CTheWorkerThread::Suspend(void)
{
_ASSERT(m_ThreadInfo.hThread);
m_ThreadInfo.bSuspended = true;
::SuspendThread(m_ThreadInfo.hThread);
}
//////////////////////////////////////////////////////////////////////////
//
// Function: ResumeThread
//
// Synopsis: Resume the worker thread
//
//////////////////////////////////////////////////////////////////////////
void CTheWorkerThread::Resume(void)
{
_ASSERT(m_ThreadInfo.hThread);
m_ThreadInfo.bSuspended = false;
::ResumeThread(m_ThreadInfo.hThread);
}
//////////////////////////////////////////////////////////////////////////
//
// Function: GetHandle()
//
// Synopsis: Return the thread handle
//
//////////////////////////////////////////////////////////////////////////
HANDLE CTheWorkerThread::GetHandle(void)
{
return m_ThreadInfo.hThread;
}
//////////////////////////////////////////////////////////////////////////
//
// Function: ThreadFunc
//
// Synopsis: The worker thread function
//
//////////////////////////////////////////////////////////////////////////
unsigned _stdcall CTheWorkerThread::ThreadFunc(LPVOID pThreadInfo)
{
// If One Shot Then
// Do some work
// Else
// While not time to exit
// Do some work
// Go idle for the wait interval
// End While
// End While
// End If
// Set exit event (synchronize thread termination)
SetThreadPriority(((PTHREADINFO)pThreadInfo)->hThread, THREAD_PRIORITY_HIGHEST);
if ( ((PTHREADINFO)pThreadInfo)->bExit )
{
((PTHREADINFO)pThreadInfo)->pfnCallback->DoCallback();
}
else
{
while ( ! ((PTHREADINFO)pThreadInfo)->bExit )
{
((PTHREADINFO)pThreadInfo)->pfnCallback->DoCallback();
WaitForSingleObjectEx(
((PTHREADINFO)pThreadInfo)->hWait,
((PTHREADINFO)pThreadInfo)->dwWaitInterval,
FALSE
);
}
}
SetEvent(((PTHREADINFO)pThreadInfo)->hExit);
return 0;
}