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.

335 lines
7.7 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////
  2. // RegExThread.h : Declaration of the CSystemTuningSpaces
  3. // Copyright (c) Microsoft Corporation 1999.
  4. #ifndef __RegExThread_H_
  5. #define __RegExThread_H_
  6. #pragma once
  7. #include "w32extend.h"
  8. #include <regexp.h>
  9. #define EXECUTE_ASSERT(x) x
  10. typedef CComQIPtr<IRegExp> PQRegExp;
  11. namespace BDATuningModel {
  12. ////////////////////////////////////////////////////////
  13. // this is a private copy of some stuff from dshow's wxutil.h, .cpp. i just need some of the win32
  14. // synchronization objects and thread stuff and i don't want to pull in all the rest of the
  15. // baggage in that file
  16. // i've made some minor changes to CAMThread and renamed it to CBaseThread in order to avoid
  17. // any problems in the future
  18. #ifndef __WXUTIL__
  19. // wrapper for whatever critical section we have
  20. class CCritSec {
  21. // make copy constructor and assignment operator inaccessible
  22. CCritSec(const CCritSec &refCritSec);
  23. CCritSec &operator=(const CCritSec &refCritSec);
  24. CRITICAL_SECTION m_CritSec;
  25. public:
  26. CCritSec() {
  27. InitializeCriticalSection(&m_CritSec);
  28. };
  29. ~CCritSec() {
  30. DeleteCriticalSection(&m_CritSec);
  31. };
  32. void Lock() {
  33. EnterCriticalSection(&m_CritSec);
  34. };
  35. void Unlock() {
  36. LeaveCriticalSection(&m_CritSec);
  37. };
  38. };
  39. // locks a critical section, and unlocks it automatically
  40. // when the lock goes out of scope
  41. class CAutoLock {
  42. // make copy constructor and assignment operator inaccessible
  43. CAutoLock(const CAutoLock &refAutoLock);
  44. CAutoLock &operator=(const CAutoLock &refAutoLock);
  45. protected:
  46. CCritSec * m_pLock;
  47. public:
  48. CAutoLock(CCritSec * plock)
  49. {
  50. m_pLock = plock;
  51. m_pLock->Lock();
  52. };
  53. ~CAutoLock() {
  54. m_pLock->Unlock();
  55. };
  56. };
  57. // wrapper for event objects
  58. class CAMEvent
  59. {
  60. // make copy constructor and assignment operator inaccessible
  61. CAMEvent(const CAMEvent &refEvent);
  62. CAMEvent &operator=(const CAMEvent &refEvent);
  63. protected:
  64. HANDLE m_hEvent;
  65. public:
  66. CAMEvent(BOOL fManualReset = FALSE)
  67. {
  68. m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
  69. ASSERT(m_hEvent);
  70. }
  71. ~CAMEvent()
  72. {
  73. HANDLE hEvent = (HANDLE)InterlockedExchangePointer(&m_hEvent, 0);
  74. if (hEvent) {
  75. EXECUTE_ASSERT(CloseHandle(hEvent));
  76. }
  77. }
  78. // Cast to HANDLE - we don't support this as an lvalue
  79. operator HANDLE () const { return m_hEvent; };
  80. void Set() {EXECUTE_ASSERT(SetEvent(m_hEvent));};
  81. BOOL Wait(DWORD dwTimeout = INFINITE) {
  82. return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0);
  83. };
  84. BOOL Check() { return Wait(0); };
  85. void Reset() { ResetEvent(m_hEvent); };
  86. };
  87. #endif // __WXUTIL__
  88. // support for a worker thread
  89. // simple thread class supports creation of worker thread, synchronization
  90. // and communication. Can be derived to simplify parameter passing
  91. class __declspec(novtable) CBaseThread {
  92. // make copy constructor and assignment operator inaccessible
  93. CBaseThread(const CBaseThread &refThread);
  94. CBaseThread &operator=(const CBaseThread &refThread);
  95. CAMEvent m_EventComplete;
  96. DWORD m_dwParam;
  97. DWORD m_dwReturnVal;
  98. DWORD m_dwCoInitFlags;
  99. protected:
  100. CAMEvent m_EventSend;
  101. HANDLE m_hThread;
  102. // thread will run this function on startup
  103. // must be supplied by derived class
  104. virtual DWORD ThreadProc() = 0;
  105. public:
  106. CBaseThread(DWORD dwFlags = COINIT_DISABLE_OLE1DDE) : // standard dshow behavior
  107. m_EventSend(TRUE), // must be manual-reset for CheckRequest()
  108. m_dwCoInitFlags(dwFlags)
  109. {
  110. m_hThread = NULL;
  111. }
  112. virtual ~CBaseThread() {
  113. Close();
  114. }
  115. CCritSec m_AccessLock; // locks access by client threads
  116. CCritSec m_WorkerLock; // locks access to shared objects
  117. // thread initially runs this. param is actually 'this'. function
  118. // just gets this and calls ThreadProc
  119. static DWORD WINAPI InitialThreadProc(LPVOID pv);
  120. // start thread running - error if already running
  121. BOOL Create();
  122. // signal the thread, and block for a response
  123. //
  124. DWORD CallWorker(DWORD);
  125. // accessor thread calls this when done with thread (having told thread
  126. // to exit)
  127. void Close() {
  128. HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0);
  129. if (hThread) {
  130. for (;;) {
  131. DWORD rc = MsgWaitForMultipleObjectsEx(1, &hThread, INFINITE, QS_ALLEVENTS, 0);
  132. if (rc == WAIT_OBJECT_0) {
  133. break;
  134. } else {
  135. // pump messages so com runs
  136. MSG msg;
  137. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  138. TranslateMessage(&msg);
  139. DispatchMessage(&msg);
  140. }
  141. }
  142. }
  143. CloseHandle(hThread);
  144. }
  145. };
  146. // ThreadExists
  147. // Return TRUE if the thread exists. FALSE otherwise
  148. BOOL ThreadExists(void) const
  149. {
  150. if (m_hThread == 0) {
  151. return FALSE;
  152. } else {
  153. return TRUE;
  154. }
  155. }
  156. #if 0
  157. // wait for the next request
  158. DWORD GetRequest();
  159. #endif
  160. // is there a request?
  161. BOOL CheckRequest(DWORD * pParam);
  162. // reply to the request
  163. void Reply(DWORD);
  164. // If you want to do WaitForMultipleObjects you'll need to include
  165. // this handle in your wait list or you won't be responsive
  166. HANDLE GetRequestHandle() const { return m_EventSend; };
  167. // Find out what the request was
  168. DWORD GetRequestParam() const { return m_dwParam; };
  169. // call CoInitializeEx (COINIT_DISABLE_OLE1DDE) if
  170. // available. S_FALSE means it's not available.
  171. static HRESULT CoInitializeHelper(DWORD dwCoInitFlags);
  172. };
  173. ///////////////////////////////////////
  174. class CRegExThread : public CBaseThread {
  175. public:
  176. typedef enum OP {
  177. RETHREAD_NOREQUEST,
  178. RETHREAD_CREATEREGEX,
  179. RETHREAD_EXIT,
  180. } OP;
  181. private:
  182. virtual DWORD ThreadProc(void) {
  183. for (;;) {
  184. OP req = GetRequest();
  185. switch (req) {
  186. case RETHREAD_CREATEREGEX: {
  187. HRESULT hr = CreateRegEx();
  188. Reply(hr);
  189. if (FAILED(hr)) {
  190. goto exit_thread;
  191. }
  192. break;
  193. } case RETHREAD_EXIT:
  194. Reply(NOERROR);
  195. goto exit_thread;
  196. };
  197. };
  198. exit_thread:
  199. CAutoLock lock(&m_WorkerLock);
  200. if (m_pGIT && m_dwCookie) {
  201. m_pGIT->RevokeInterfaceFromGlobal(m_dwCookie);
  202. m_dwCookie = 0;
  203. m_pGIT.Release();
  204. }
  205. return 0;
  206. }
  207. OP GetRequest() {
  208. HANDLE h = GetRequestHandle();
  209. for (;;) {
  210. DWORD rc = MsgWaitForMultipleObjectsEx(1, &h, INFINITE, QS_ALLEVENTS, 0);
  211. if (rc == WAIT_OBJECT_0) {
  212. return (OP)GetRequestParam();
  213. } else {
  214. // pump messages so com runs
  215. MSG msg;
  216. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  217. TranslateMessage(&msg);
  218. DispatchMessage(&msg);
  219. }
  220. }
  221. }
  222. }
  223. HRESULT CreateRegEx() {
  224. CAutoLock lock(&m_WorkerLock);
  225. if (!m_pGIT) {
  226. HRESULT hr = m_pGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable, 0, CLSCTX_INPROC_SERVER);
  227. if (FAILED(hr)) {
  228. return hr;
  229. }
  230. // this is an expensive object to create. so, once we have one we hang onto it.
  231. PQRegExp pRE;
  232. hr = pRE.CoCreateInstance(__uuidof(RegExp), NULL, CLSCTX_INPROC);
  233. if (FAILED(hr)) {
  234. return hr;
  235. }
  236. hr = pRE->put_IgnoreCase(VARIANT_TRUE);
  237. if (FAILED(hr)) {
  238. return hr;
  239. }
  240. hr = pRE->put_Global(VARIANT_TRUE);
  241. if (FAILED(hr)) {
  242. return hr;
  243. }
  244. ASSERT(!m_dwCookie);
  245. hr = m_pGIT->RegisterInterfaceInGlobal(pRE, __uuidof(IRegExp), &m_dwCookie);
  246. if (FAILED(hr)) {
  247. return hr;
  248. }
  249. }
  250. ASSERT(m_pGIT);
  251. ASSERT(m_dwCookie);
  252. return NOERROR;
  253. }
  254. PQGIT m_pGIT;
  255. DWORD m_dwCookie;
  256. public:
  257. CRegExThread() :
  258. CBaseThread(COINIT_APARTMENTTHREADED),
  259. m_dwCookie(0)
  260. {}
  261. ~CRegExThread() {
  262. CallWorker(RETHREAD_EXIT);
  263. Close();
  264. }
  265. DWORD GetCookie() {
  266. CAutoLock lock(&m_WorkerLock);
  267. return m_dwCookie;
  268. }
  269. }; // class CRegExThread
  270. }; // namespace BDATuningModel
  271. #endif //__RegExThread_H_