EventThread.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include "StdAfx.h"
  2. #include "EventThread.h"
  3. #include "Misc.h"
  4. #define EXIT_EVENT -1
  5. #define REBUILD_EVENTS -2
  6. CEventThread::CEventThread(void)
  7. {
  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. AddEvent(EXIT_EVENT);
  14. AddEvent(REBUILD_EVENTS);
  15. }
  16. CEventThread::~CEventThread(void)
  17. {
  18. Stop();
  19. for(EventMapType::iterator it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  20. {
  21. CloseHandle(it->first);
  22. }
  23. }
  24. UINT CEventThread::EventThreadFnc(void* thisptr)
  25. {
  26. CEventThread *threadClass = (CEventThread*)thisptr;
  27. threadClass->RunThread();
  28. return 0;
  29. }
  30. void CEventThread::AddEvent(int eventId)
  31. {
  32. HANDLE handle = CreateEvent(NULL, FALSE, FALSE, _T(""));
  33. {
  34. ATL::CCritSecLock csLock(m_lock.m_sect);
  35. m_eventMap[handle] = eventId;
  36. }
  37. if (m_threadRunning)
  38. {
  39. FireEvent(REBUILD_EVENTS);
  40. }
  41. }
  42. void CEventThread::AddEvent(int eventId, HANDLE handle)
  43. {
  44. {
  45. ATL::CCritSecLock csLock(m_lock.m_sect);
  46. m_eventMap[handle] = eventId;
  47. }
  48. if (m_threadRunning)
  49. {
  50. FireEvent(REBUILD_EVENTS);
  51. }
  52. }
  53. void CEventThread::AddEvent(int eventId, CString name)
  54. {
  55. //handle creating events cross users/cross process
  56. //https://stackoverflow.com/questions/29976596/shared-global-event-between-a-service-user-mode-processes-doesnt-work
  57. SECURITY_DESCRIPTOR sd;
  58. InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
  59. SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
  60. SECURITY_ATTRIBUTES sa = { 0 };
  61. sa.nLength = sizeof(sa);
  62. sa.bInheritHandle = FALSE;
  63. sa.lpSecurityDescriptor = &sd;
  64. HANDLE handle = CreateEvent(&sa, FALSE, FALSE, name);
  65. {
  66. ATL::CCritSecLock csLock(m_lock.m_sect);
  67. m_eventMap[handle] = eventId;
  68. }
  69. if (m_threadRunning)
  70. {
  71. FireEvent(REBUILD_EVENTS);
  72. }
  73. }
  74. bool CEventThread::FireEvent(int eventId)
  75. {
  76. HANDLE eventHandle = GetHandle(eventId);
  77. if(eventHandle != nullptr)
  78. {
  79. SetEvent(eventHandle);
  80. return true;
  81. }
  82. return false;
  83. }
  84. bool CEventThread::UndoFireEvent(int eventId)
  85. {
  86. HANDLE eventHandle = GetHandle(eventId);
  87. if (eventHandle != nullptr)
  88. {
  89. ResetEvent(eventHandle);
  90. return true;
  91. }
  92. return false;
  93. }
  94. HANDLE CEventThread::GetHandle(int eventId)
  95. {
  96. ATL::CCritSecLock csLock(m_lock.m_sect);
  97. for (auto it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  98. {
  99. if (it->second == eventId)
  100. {
  101. return it->first;
  102. }
  103. }
  104. return nullptr;
  105. }
  106. bool CEventThread::RemoveEvent(int eventId)
  107. {
  108. ATL::CCritSecLock csLock(m_lock.m_sect);
  109. for (auto it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  110. {
  111. if (it->second == eventId)
  112. {
  113. if (m_threadRunning)
  114. {
  115. FireEvent(REBUILD_EVENTS);
  116. }
  117. CloseHandle(it->first);
  118. m_eventMap.erase(it);
  119. return true;
  120. }
  121. }
  122. return false;
  123. }
  124. void CEventThread::Start(void *param)
  125. {
  126. if(m_threadRunning == false)
  127. {
  128. ResetEvent(m_hEvt);
  129. m_exitThread = false;
  130. m_param = param;
  131. m_thread = (HANDLE)_beginthreadex(NULL, 0, EventThreadFnc, this, 0, &m_threadID);
  132. // now wait until the thread is up and really running
  133. WaitForSingleObject(m_hEvt, 1000);
  134. }
  135. else
  136. {
  137. UndoFireEvent(EXIT_EVENT);
  138. }
  139. }
  140. void CEventThread::WaitForThreadToExit(int waitTime)
  141. {
  142. WaitForSingleObject(m_hEvt, waitTime);
  143. }
  144. void CEventThread::Stop(int waitTime)
  145. {
  146. Log(StrF(_T("Start of CEventThread::Stop(int waitTime) %d - Name: %s"), waitTime, m_threadName));
  147. if(m_threadRunning)
  148. {
  149. m_exitThread = true;
  150. FireEvent(EXIT_EVENT);
  151. if(waitTime > 0)
  152. {
  153. if (WAIT_OBJECT_0 != WaitForSingleObject(m_hEvt, waitTime))
  154. {
  155. Log(_T("Start of TerminateThread CEventThread::Stop(int waitTime) "));
  156. TerminateThread(m_thread, 0);
  157. Log(_T("End of TerminateThread CEventThread::Stop(int waitTime) "));
  158. m_threadRunning = false;
  159. }
  160. }
  161. }
  162. Log(StrF(_T("End of CEventThread::Stop(int waitTime) %d - Name: %s"), waitTime, m_threadName));
  163. };
  164. void CEventThread::GetHandleVector(std::vector<HANDLE> &handles)
  165. {
  166. ATL::CCritSecLock csLock(m_lock.m_sect);
  167. handles.clear();
  168. for (auto it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  169. {
  170. if (it->first != 0)
  171. {
  172. handles.push_back(it->first);
  173. }
  174. }
  175. }
  176. void CEventThread::CheckForRebuildHandleVector(std::vector<HANDLE>& handles)
  177. {
  178. ATL::CCritSecLock csLock(m_lock.m_sect);
  179. for (auto it = m_eventMap.begin(); it != m_eventMap.end(); it++)
  180. {
  181. if (it->second == REBUILD_EVENTS)
  182. {
  183. DWORD result = WaitForSingleObject(it->first, 0);
  184. if (result == WAIT_OBJECT_0)
  185. {
  186. GetHandleVector(handles);
  187. }
  188. break;
  189. }
  190. }
  191. }
  192. void CEventThread::RunThread()
  193. {
  194. Log(StrF(_T("Start of CEventThread::RunThread() Name: %s"), m_threadName));
  195. m_threadRunning = true;
  196. m_threadWasStarted = true;
  197. std::vector<HANDLE> handles;
  198. GetHandleVector(handles);
  199. SetEvent(m_hEvt);
  200. ResetEvent(m_hEvt);
  201. while(m_exitThread == false)
  202. {
  203. CheckForRebuildHandleVector(handles);
  204. DWORD event = WaitForMultipleObjects((DWORD)handles.size(), handles.data(), FALSE, m_waitTimeout);
  205. if(event == WAIT_FAILED)
  206. {
  207. const DWORD errorMessageId = GetLastError();
  208. LPSTR messageBuffer = nullptr;
  209. size_t size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorMessageId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, nullptr);
  210. CString message(messageBuffer, (int)size);
  211. LocalFree(messageBuffer);
  212. Log(StrF(_T("CEventThread::RunThread() Error, error: %s - Name %s"), message, m_threadName));
  213. Sleep(1000);
  214. }
  215. else if(event == WAIT_TIMEOUT)
  216. {
  217. OnTimeOut(m_param);
  218. }
  219. else
  220. {
  221. const int handleIndex = event - WAIT_OBJECT_0;
  222. if (handleIndex < 0 || handleIndex >= handles.size())
  223. {
  224. Log(StrF(_T("CEventThread::RunThread() Error, Invalid handle index, index: %d, size: %d - Name %s"), handleIndex, handles.size(), m_threadName));
  225. continue;
  226. }
  227. HANDLE firedHandle = handles[handleIndex];
  228. const int eventId = m_eventMap[firedHandle];
  229. if(eventId == EXIT_EVENT)
  230. {
  231. break;
  232. }
  233. else if (eventId == REBUILD_EVENTS)
  234. {
  235. GetHandleVector(handles);
  236. }
  237. else
  238. {
  239. Log(StrF(_T("Start of CEventThread::RunThread() - OnEvent %d - Name %s"), eventId, m_threadName));
  240. OnEvent(eventId, m_param);
  241. Log(StrF(_T("End of CEventThread::RunThread() - OnEvent %d - Name: %s"), eventId, m_threadName));
  242. }
  243. }
  244. }
  245. UndoFireEvent(EXIT_EVENT);
  246. SetEvent(m_hEvt);
  247. Log(StrF(_T("End of CEventThread::RunThread() Name: %s"), m_threadName));
  248. m_threadRunning = false;
  249. }