160 lines
3.0 KiB
C++
160 lines
3.0 KiB
C++
|
#include "priv.h"
|
||
|
#include <mluisupp.h>
|
||
|
|
||
|
#include "SmallUtil.hpp"
|
||
|
|
||
|
|
||
|
CCancellableThread::CCancellableThread()
|
||
|
{
|
||
|
_hCancelEvent = NULL;
|
||
|
_hThread = NULL;
|
||
|
_fIsFinished = FALSE;
|
||
|
_dwThreadResult = 0;
|
||
|
}
|
||
|
|
||
|
CCancellableThread::~CCancellableThread()
|
||
|
{
|
||
|
if (_hCancelEvent)
|
||
|
CloseHandle(_hCancelEvent);
|
||
|
|
||
|
if (_hThread)
|
||
|
{
|
||
|
DWORD dwThreadStatus;
|
||
|
if (0 != GetExitCodeThread(_hThread, &dwThreadStatus)
|
||
|
&& dwThreadStatus == STILL_ACTIVE)
|
||
|
{
|
||
|
ASSERT(0); // bad error case, shouldn't need to terminate thread.
|
||
|
TerminateThread(_hThread, 0);
|
||
|
}
|
||
|
CloseHandle(_hThread);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CCancellableThread::Initialize()
|
||
|
{
|
||
|
BOOL retVal = FALSE;
|
||
|
|
||
|
_hCancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
|
||
|
if (!_hCancelEvent)
|
||
|
goto doneCCancellableThreadInitialize;
|
||
|
|
||
|
retVal = TRUE;
|
||
|
doneCCancellableThreadInitialize:
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CCancellableThread::IsCancelled()
|
||
|
{
|
||
|
if (!_hCancelEvent)
|
||
|
return FALSE;
|
||
|
|
||
|
DWORD dwEventWaitResult;
|
||
|
dwEventWaitResult = WaitForSingleObject(_hCancelEvent, 0);
|
||
|
|
||
|
if (dwEventWaitResult == WAIT_OBJECT_0)
|
||
|
return TRUE;
|
||
|
else
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CCancellableThread::IsFinished()
|
||
|
{
|
||
|
return _fIsFinished;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CCancellableThread::GetResult(PDWORD pdwResult)
|
||
|
{
|
||
|
BOOL retVal = FALSE;
|
||
|
|
||
|
if (IsFinished() != TRUE)
|
||
|
goto doneCCancellableThreadGetStatus;
|
||
|
|
||
|
*pdwResult = _dwThreadResult;
|
||
|
retVal = TRUE;
|
||
|
|
||
|
doneCCancellableThreadGetStatus:
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CCancellableThread::WaitForNotRunning(DWORD dwMilliseconds, PBOOL pfFinished)
|
||
|
{
|
||
|
BOOL retVal = FALSE;
|
||
|
BOOL result;
|
||
|
|
||
|
if (NULL == _hThread)
|
||
|
{
|
||
|
result = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DWORD dwWaitResult;
|
||
|
|
||
|
dwWaitResult = WaitForSingleObject(_hThread, dwMilliseconds);
|
||
|
|
||
|
if (dwWaitResult == WAIT_OBJECT_0)
|
||
|
result = TRUE;
|
||
|
else if (dwWaitResult == WAIT_TIMEOUT)
|
||
|
result = FALSE;
|
||
|
else
|
||
|
{
|
||
|
DWORD dwError = GetLastError();
|
||
|
goto doneCCancellableThreadWaitForComplete;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
retVal = TRUE;
|
||
|
|
||
|
doneCCancellableThreadWaitForComplete:
|
||
|
if (retVal == TRUE && pfFinished != NULL)
|
||
|
*pfFinished = result;
|
||
|
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CCancellableThread::Run()
|
||
|
{
|
||
|
BOOL retVal = FALSE;
|
||
|
|
||
|
if (!_hThread)
|
||
|
{
|
||
|
DWORD dw;
|
||
|
retVal = (NULL != (_hThread = CreateThread(NULL, 0, threadProc, (void *)this, 0, &dw)));
|
||
|
}
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CCancellableThread::NotifyCancel()
|
||
|
{
|
||
|
if (!_hCancelEvent)
|
||
|
return FALSE;
|
||
|
|
||
|
if (0 == SetEvent(_hCancelEvent))
|
||
|
return FALSE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD WINAPI CCancellableThread::threadProc(void *pParameter)
|
||
|
{
|
||
|
CCancellableThread *pThis = (CCancellableThread *)pParameter;
|
||
|
|
||
|
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
|
||
|
{
|
||
|
pThis->_dwThreadResult = pThis->run();
|
||
|
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
pThis->_fIsFinished = TRUE;
|
||
|
return 0;
|
||
|
}
|
||
|
|