Source code of Windows XP (NT5)
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.

212 lines
4.1 KiB

  1. #include "priv.h"
  2. #include <mluisupp.h>
  3. #include "SmallUtil.hpp"
  4. CCancellableThread::CCancellableThread()
  5. {
  6. _hCancelEvent = NULL;
  7. _hThread = NULL;
  8. _fIsFinished = FALSE;
  9. _dwThreadResult = 0;
  10. }
  11. CCancellableThread::~CCancellableThread()
  12. {
  13. if( _hCancelEvent)
  14. CloseHandle( _hCancelEvent);
  15. if( _hThread)
  16. {
  17. DWORD dwThreadStatus;
  18. if(0 != GetExitCodeThread( _hThread, &dwThreadStatus)
  19. && dwThreadStatus == STILL_ACTIVE)
  20. {
  21. ASSERT( 0); // bad error case, shouldn't need to terminate thread.
  22. TerminateThread( _hThread, 0);
  23. }
  24. CloseHandle( _hThread);
  25. }
  26. }
  27. BOOL CCancellableThread::Initialize()
  28. {
  29. BOOL retVal = FALSE;
  30. _hCancelEvent = CreateEvent( NULL, TRUE, FALSE, NULL);
  31. if( !_hCancelEvent)
  32. goto doneCCancellableThreadInitialize;
  33. retVal = TRUE;
  34. doneCCancellableThreadInitialize:
  35. return retVal;
  36. }
  37. BOOL CCancellableThread::IsCancelled()
  38. {
  39. if( !_hCancelEvent)
  40. return FALSE;
  41. DWORD dwEventWaitResult;
  42. dwEventWaitResult = WaitForSingleObject( _hCancelEvent, 0);
  43. if( dwEventWaitResult == WAIT_OBJECT_0)
  44. return TRUE;
  45. else
  46. return FALSE;
  47. }
  48. BOOL CCancellableThread::IsRunning()
  49. {
  50. if( NULL == _hThread)
  51. return FALSE;
  52. else
  53. return _fIsFinished ? FALSE : TRUE;
  54. }
  55. BOOL CCancellableThread::IsFinished()
  56. {
  57. return _fIsFinished;
  58. }
  59. BOOL CCancellableThread::GetResult( PDWORD pdwResult)
  60. {
  61. BOOL retVal = FALSE;
  62. if( IsFinished() != TRUE)
  63. goto doneCCancellableThreadGetStatus;
  64. *pdwResult = _dwThreadResult;
  65. retVal = TRUE;
  66. doneCCancellableThreadGetStatus:
  67. return retVal;
  68. }
  69. BOOL CCancellableThread::WaitForNotRunning( DWORD dwMilliseconds, PBOOL pfFinished)
  70. {
  71. BOOL retVal = FALSE;
  72. BOOL result;
  73. if( NULL == _hThread)
  74. {
  75. result = TRUE;
  76. }
  77. else
  78. {
  79. DWORD dwWaitResult;
  80. dwWaitResult = WaitForSingleObject( _hThread, dwMilliseconds);
  81. if( dwWaitResult == WAIT_OBJECT_0)
  82. result = TRUE;
  83. else if ( dwWaitResult == WAIT_TIMEOUT)
  84. result = FALSE;
  85. else
  86. {
  87. DWORD dwError = GetLastError();
  88. goto doneCCancellableThreadWaitForComplete;
  89. }
  90. }
  91. retVal = TRUE;
  92. doneCCancellableThreadWaitForComplete:
  93. if( retVal == TRUE && pfFinished != NULL)
  94. *pfFinished = result;
  95. return retVal;
  96. }
  97. BOOL CCancellableThread::WaitForCancel( DWORD dwMilliseconds, PBOOL pfCanceled)
  98. {
  99. BOOL retVal = FALSE;
  100. BOOL result;
  101. if( NULL == _hCancelEvent)
  102. {
  103. result = FALSE;
  104. }
  105. else
  106. {
  107. DWORD dwWaitResult;
  108. dwWaitResult = WaitForSingleObject( _hCancelEvent, dwMilliseconds);
  109. if( dwWaitResult == WAIT_OBJECT_0)
  110. result = TRUE;
  111. else if ( dwWaitResult == WAIT_TIMEOUT)
  112. result = FALSE;
  113. else
  114. {
  115. DWORD dwError = GetLastError();
  116. goto doneCCancellableThreadWaitForComplete;
  117. }
  118. }
  119. retVal = TRUE;
  120. doneCCancellableThreadWaitForComplete:
  121. if( retVal == TRUE && pfCanceled != NULL)
  122. *pfCanceled = result;
  123. return retVal;
  124. }
  125. BOOL CCancellableThread::Run()
  126. {
  127. BOOL retVal = FALSE;
  128. DWORD dw;
  129. if( _hThread != NULL)
  130. goto doneCCancellableThreadRun;
  131. if( NULL == (_hThread = CreateThread( NULL, 0, threadProc, (LPVOID)this, 0, &dw)))
  132. goto doneCCancellableThreadRun;
  133. retVal = TRUE;
  134. doneCCancellableThreadRun:
  135. return retVal;
  136. }
  137. BOOL CCancellableThread::NotifyCancel()
  138. {
  139. if( !_hCancelEvent)
  140. return FALSE;
  141. if( 0 == SetEvent( _hCancelEvent))
  142. return FALSE;
  143. return TRUE;
  144. }
  145. DWORD WINAPI CCancellableThread::threadProc( LPVOID lpParameter)
  146. {
  147. PCCancellableThread pThis = (PCCancellableThread)lpParameter;
  148. if( FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
  149. goto doneCCancellableThreadThreadProc;
  150. pThis->_dwThreadResult = ((CCancellableThread*)lpParameter)->run();
  151. CoUninitialize();
  152. pThis->_fIsFinished = TRUE;
  153. doneCCancellableThreadThreadProc:
  154. return 0;
  155. }