EventThread.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include "StdAfx.h"
  2. #include "EventThread.h"
  3. #include "Misc.h"
  4. #define EXIT_EVENT -1
  5. CEventThread::CEventThread(void)
  6. {
  7. AddEvent(EXIT_EVENT);
  8. m_hEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
  9. m_waitTimeout = INFINITE;
  10. m_threadRunning = false;
  11. m_exitThread = false;
  12. m_threadWasStarted = false;
  13. }
  14. CEventThread::~CEventThread(void)
  15. {
  16. Stop();
  17. for(EventMapType::iterator it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  18. {
  19. CloseHandle(it->first);
  20. }
  21. }
  22. UINT CEventThread::EventThreadFnc(void* thisptr)
  23. {
  24. CEventThread *threadClass = (CEventThread*)thisptr;
  25. threadClass->RunThread();
  26. return 0;
  27. }
  28. void CEventThread::AddEvent(int eventId)
  29. {
  30. HANDLE handle = CreateEvent(NULL, FALSE, FALSE, _T(""));
  31. m_eventMap[handle] = eventId;
  32. }
  33. void CEventThread::AddEvent(int eventId, CString name)
  34. {
  35. //handle creating events cross users/cross process
  36. //https://stackoverflow.com/questions/29976596/shared-global-event-between-a-service-user-mode-processes-doesnt-work
  37. SECURITY_DESCRIPTOR sd;
  38. InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
  39. SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
  40. SECURITY_ATTRIBUTES sa = { 0 };
  41. sa.nLength = sizeof(sa);
  42. sa.bInheritHandle = FALSE;
  43. sa.lpSecurityDescriptor = &sd;
  44. HANDLE handle = CreateEvent(&sa, FALSE, FALSE, name);
  45. m_eventMap[handle] = eventId;
  46. }
  47. bool CEventThread::FireEvent(int eventId)
  48. {
  49. //Log(StrF(_T("Begin FireEvent, eventId: %d"), eventId));
  50. bool ret = false;
  51. HANDLE eventHandle = NULL;
  52. for(EventMapType::iterator it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  53. {
  54. if(it->second == eventId)
  55. {
  56. eventHandle = it->first;
  57. break;
  58. }
  59. }
  60. if(eventHandle != NULL)
  61. {
  62. SetEvent(eventHandle);
  63. ret = true;
  64. }
  65. //Log(StrF(_T("End FireEvent, eventId: %d"), eventId));
  66. return false;
  67. }
  68. bool CEventThread::UndoFireEvent(int eventId)
  69. {
  70. HANDLE eventHandle = NULL;
  71. for(EventMapType::iterator it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  72. {
  73. if(it->second == eventId)
  74. {
  75. eventHandle = it->first;
  76. break;
  77. }
  78. }
  79. if(eventHandle != NULL)
  80. {
  81. ResetEvent(eventHandle);
  82. return true;
  83. }
  84. return false;
  85. }
  86. void CEventThread::Start(void *param)
  87. {
  88. if(m_threadRunning == false)
  89. {
  90. ResetEvent(m_hEvt);
  91. m_exitThread = false;
  92. m_param = param;
  93. m_thread = (HANDLE)_beginthreadex(NULL, 0, EventThreadFnc, this, 0, &m_threadID);
  94. // now wait until the thread is up and really running
  95. WaitForSingleObject(m_hEvt, 1000);
  96. }
  97. else
  98. {
  99. UndoFireEvent(EXIT_EVENT);
  100. }
  101. }
  102. void CEventThread::WaitForThreadToExit(int waitTime)
  103. {
  104. WaitForSingleObject(m_hEvt, waitTime);
  105. }
  106. void CEventThread::Stop(int waitTime)
  107. {
  108. Log(StrF(_T("Start of CEventThread::Stop(int waitTime) %d - Name: %s"), waitTime, m_threadName));
  109. if(m_threadRunning)
  110. {
  111. m_exitThread = true;
  112. FireEvent(EXIT_EVENT);
  113. if(waitTime > 0)
  114. {
  115. if (WAIT_OBJECT_0 != WaitForSingleObject(m_hEvt, waitTime))
  116. {
  117. Log(_T("Start of TerminateThread CEventThread::Stop(int waitTime) "));
  118. TerminateThread(m_thread, 0);
  119. Log(_T("End of TerminateThread CEventThread::Stop(int waitTime) "));
  120. m_threadRunning = false;
  121. }
  122. }
  123. }
  124. Log(StrF(_T("End of CEventThread::Stop(int waitTime) %d - Name: %s"), waitTime, m_threadName));
  125. };
  126. void CEventThread::RunThread()
  127. {
  128. Log(StrF(_T("Start of CEventThread::RunThread() Name: %s"), m_threadName));
  129. m_threadRunning = true;
  130. m_threadWasStarted = true;
  131. HANDLE *pHandleArray = new HANDLE[m_eventMap.size()];
  132. int indexPos = 0;
  133. for(EventMapType::iterator it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  134. {
  135. if (it->first != 0)
  136. {
  137. pHandleArray[indexPos] = it->first;
  138. indexPos++;
  139. }
  140. }
  141. SetEvent(m_hEvt);
  142. ResetEvent(m_hEvt);
  143. while(m_exitThread == false)
  144. {
  145. DWORD event = WaitForMultipleObjects((DWORD)m_eventMap.size(), pHandleArray, FALSE, m_waitTimeout);
  146. if(event == WAIT_FAILED)
  147. {
  148. LPVOID lpMsgBuf = NULL;
  149. DWORD dwErr = GetLastError();
  150. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  151. FORMAT_MESSAGE_FROM_SYSTEM |
  152. FORMAT_MESSAGE_IGNORE_INSERTS,
  153. NULL,
  154. dwErr,
  155. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  156. (LPTSTR) &lpMsgBuf,
  157. 0,
  158. NULL);
  159. ASSERT(!lpMsgBuf);
  160. LocalFree(lpMsgBuf);
  161. Sleep(1000);
  162. }
  163. else if(event == WAIT_TIMEOUT)
  164. {
  165. OnTimeOut(m_param);
  166. }
  167. else
  168. {
  169. HANDLE firedHandle = pHandleArray[event - WAIT_OBJECT_0];
  170. int eventId = m_eventMap[firedHandle];
  171. if(eventId == EXIT_EVENT)
  172. {
  173. break;
  174. }
  175. else
  176. {
  177. Log(StrF(_T("Start of CEventThread::RunThread() - OnEvent %d - Name %s"), eventId, m_threadName));
  178. OnEvent(eventId, m_param);
  179. Log(StrF(_T("End of CEventThread::RunThread() - OnEvent %d - Name: %d"), eventId, m_threadName));
  180. }
  181. }
  182. }
  183. UndoFireEvent(EXIT_EVENT);
  184. SetEvent(m_hEvt);
  185. Log(StrF(_T("End of CEventThread::RunThread() Name: %s"), m_threadName));
  186. m_threadRunning = false;
  187. }