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.

118 lines
2.6 KiB

  1. #include "stdafx.h"
  2. #include "thread.h"
  3. // general purpose worker thread
  4. // The thread exists in an alertable Wait state and does most of its work
  5. // in APCs.
  6. CEventThread::CEventThread()
  7. {
  8. InitializeCriticalSection(&m_cs);
  9. m_uRef=0;
  10. m_dwFlags = 0;
  11. m_hThread = 0;
  12. m_hSignalEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  13. m_hAckEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  14. }
  15. CEventThread::~CEventThread()
  16. {
  17. DeleteCriticalSection(&m_cs);
  18. if (m_hSignalEvent)
  19. CloseHandle(m_hSignalEvent);
  20. if (m_hAckEvent)
  21. CloseHandle(m_hAckEvent);
  22. }
  23. BOOL
  24. CEventThread::Start()
  25. {
  26. BOOL fRet;
  27. EnterCriticalSection(&m_cs);
  28. if (++m_uRef == 1)
  29. {
  30. m_hThread = CreateThread(
  31. NULL,0,
  32. EventThreadProc,
  33. this, 0, &m_idThread);
  34. }
  35. fRet = !!m_hThread;
  36. LeaveCriticalSection(&m_cs);
  37. return fRet;
  38. }
  39. BOOL
  40. CEventThread::Stop()
  41. {
  42. BOOL fRet;
  43. EnterCriticalSection(&m_cs);
  44. if (--m_uRef == 0)
  45. {
  46. m_dwFlags |= CTHREADF_STOP;
  47. SetEvent(m_hSignalEvent);
  48. WaitForSingleObject(m_hThread, INFINITE);
  49. CloseHandle(m_hThread);
  50. m_hThread = NULL;
  51. m_dwFlags &= ~CTHREADF_STOP;
  52. }
  53. LeaveCriticalSection(&m_cs);
  54. return TRUE;
  55. }
  56. DWORD
  57. CEventThread::ThreadMethod()
  58. {
  59. DWORD dwWait;
  60. while (1) {
  61. dwWait = WaitForSingleObjectEx(m_hSignalEvent, INFINITE, TRUE);
  62. if (dwWait == WAIT_OBJECT_0)
  63. {
  64. if (m_dwFlags & CTHREADF_STOP)
  65. {
  66. break; // exit thread
  67. }
  68. }
  69. else if (dwWait == WAIT_IO_COMPLETION)
  70. {
  71. }
  72. else
  73. if (dwWait == WAIT_FAILED)
  74. {
  75. break; // exit thread
  76. }
  77. }
  78. return dwWait;
  79. }
  80. // Executes the CallProc in the worker thread in a synchronous fashion
  81. // (similar to SendMessage). When this method returns the CallProc has been called
  82. // and the return value is returned.
  83. BOOL CEventThread::CallNow(THREADCALLBACK CallProc, PVOID pParam, DWORD dwParam)
  84. {
  85. BOOL fRet = FALSE;
  86. EnterCriticalSection(&m_cs);
  87. m_Callback.CallProc = CallProc;
  88. m_Callback.pParam = pParam;
  89. m_Callback.dwParam = dwParam;
  90. ResetEvent(m_hAckEvent);
  91. if (QueueUserAPC(HandleCallNowAPC, m_hThread, (DWORD)this))
  92. {
  93. DWORD dwWait;
  94. dwWait = WaitForSingleObject(m_hAckEvent, INFINITE);
  95. if (dwWait == WAIT_OBJECT_0)
  96. fRet = (BOOL) m_Callback.dwParam; //get the cached return value
  97. }
  98. LeaveCriticalSection(&m_cs);
  99. return fRet;
  100. }
  101. void APIENTRY CEventThread::HandleCallNowAPC(DWORD dwArg)
  102. {
  103. CEventThread *pThis = (CEventThread *)dwArg;
  104. if (pThis->m_Callback.CallProc)
  105. {
  106. pThis->m_Callback.dwParam = pThis->m_Callback.CallProc(pThis->m_Callback.pParam, pThis->m_Callback.dwParam);
  107. SetEvent(pThis->m_hAckEvent);
  108. }
  109. }