|
|
/////////////////////////////////////////////////////////////////////////////////////
// RegExThread.h : Declaration of the CSystemTuningSpaces
// Copyright (c) Microsoft Corporation 1999.
#ifndef __RegExThread_H_
#define __RegExThread_H_
#pragma once
#include "w32extend.h"
#include <regexp.h>
#define EXECUTE_ASSERT(x) x
typedef CComQIPtr<IRegExp> PQRegExp;
namespace BDATuningModel {
////////////////////////////////////////////////////////
// this is a private copy of some stuff from dshow's wxutil.h, .cpp. i just need some of the win32
// synchronization objects and thread stuff and i don't want to pull in all the rest of the
// baggage in that file
// i've made some minor changes to CAMThread and renamed it to CBaseThread in order to avoid
// any problems in the future
#ifndef __WXUTIL__
// wrapper for whatever critical section we have
class CCritSec {
// make copy constructor and assignment operator inaccessible
CCritSec(const CCritSec &refCritSec); CCritSec &operator=(const CCritSec &refCritSec);
CRITICAL_SECTION m_CritSec;
public: CCritSec() { InitializeCriticalSection(&m_CritSec); };
~CCritSec() { DeleteCriticalSection(&m_CritSec); };
void Lock() { EnterCriticalSection(&m_CritSec); };
void Unlock() { LeaveCriticalSection(&m_CritSec); }; };
// locks a critical section, and unlocks it automatically
// when the lock goes out of scope
class CAutoLock {
// make copy constructor and assignment operator inaccessible
CAutoLock(const CAutoLock &refAutoLock); CAutoLock &operator=(const CAutoLock &refAutoLock);
protected: CCritSec * m_pLock;
public: CAutoLock(CCritSec * plock) { m_pLock = plock; m_pLock->Lock(); };
~CAutoLock() { m_pLock->Unlock(); }; };
// wrapper for event objects
class CAMEvent {
// make copy constructor and assignment operator inaccessible
CAMEvent(const CAMEvent &refEvent); CAMEvent &operator=(const CAMEvent &refEvent);
protected: HANDLE m_hEvent; public: CAMEvent(BOOL fManualReset = FALSE) { m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL); ASSERT(m_hEvent); } ~CAMEvent() { HANDLE hEvent = (HANDLE)InterlockedExchangePointer(&m_hEvent, 0); if (hEvent) { EXECUTE_ASSERT(CloseHandle(hEvent)); } }
// Cast to HANDLE - we don't support this as an lvalue
operator HANDLE () const { return m_hEvent; };
void Set() {EXECUTE_ASSERT(SetEvent(m_hEvent));}; BOOL Wait(DWORD dwTimeout = INFINITE) { return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0); }; BOOL Check() { return Wait(0); }; void Reset() { ResetEvent(m_hEvent); }; };
#endif // __WXUTIL__
// support for a worker thread
// simple thread class supports creation of worker thread, synchronization
// and communication. Can be derived to simplify parameter passing
class __declspec(novtable) CBaseThread {
// make copy constructor and assignment operator inaccessible
CBaseThread(const CBaseThread &refThread); CBaseThread &operator=(const CBaseThread &refThread);
CAMEvent m_EventComplete;
DWORD m_dwParam; DWORD m_dwReturnVal; DWORD m_dwCoInitFlags;
protected: CAMEvent m_EventSend; HANDLE m_hThread;
// thread will run this function on startup
// must be supplied by derived class
virtual DWORD ThreadProc() = 0;
public: CBaseThread(DWORD dwFlags = COINIT_DISABLE_OLE1DDE) : // standard dshow behavior
m_EventSend(TRUE), // must be manual-reset for CheckRequest()
m_dwCoInitFlags(dwFlags) { m_hThread = NULL; }
virtual ~CBaseThread() { Close(); }
CCritSec m_AccessLock; // locks access by client threads
CCritSec m_WorkerLock; // locks access to shared objects
// thread initially runs this. param is actually 'this'. function
// just gets this and calls ThreadProc
static DWORD WINAPI InitialThreadProc(LPVOID pv);
// start thread running - error if already running
BOOL Create();
// signal the thread, and block for a response
//
DWORD CallWorker(DWORD);
// accessor thread calls this when done with thread (having told thread
// to exit)
void Close() { HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0); if (hThread) { for (;;) { DWORD rc = MsgWaitForMultipleObjectsEx(1, &hThread, INFINITE, QS_ALLEVENTS, 0); if (rc == WAIT_OBJECT_0) { break; } else { // pump messages so com runs
MSG msg; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } }
CloseHandle(hThread); } };
// ThreadExists
// Return TRUE if the thread exists. FALSE otherwise
BOOL ThreadExists(void) const { if (m_hThread == 0) { return FALSE; } else { return TRUE; } }
#if 0
// wait for the next request
DWORD GetRequest(); #endif
// is there a request?
BOOL CheckRequest(DWORD * pParam);
// reply to the request
void Reply(DWORD);
// If you want to do WaitForMultipleObjects you'll need to include
// this handle in your wait list or you won't be responsive
HANDLE GetRequestHandle() const { return m_EventSend; };
// Find out what the request was
DWORD GetRequestParam() const { return m_dwParam; };
// call CoInitializeEx (COINIT_DISABLE_OLE1DDE) if
// available. S_FALSE means it's not available.
static HRESULT CoInitializeHelper(DWORD dwCoInitFlags); };
///////////////////////////////////////
class CRegExThread : public CBaseThread { public: typedef enum OP { RETHREAD_NOREQUEST, RETHREAD_CREATEREGEX, RETHREAD_EXIT, } OP; private: virtual DWORD ThreadProc(void) { for (;;) { OP req = GetRequest(); switch (req) { case RETHREAD_CREATEREGEX: { HRESULT hr = CreateRegEx(); Reply(hr); if (FAILED(hr)) { goto exit_thread; } break; } case RETHREAD_EXIT: Reply(NOERROR); goto exit_thread; }; }; exit_thread: CAutoLock lock(&m_WorkerLock); if (m_pGIT && m_dwCookie) { m_pGIT->RevokeInterfaceFromGlobal(m_dwCookie); m_dwCookie = 0; m_pGIT.Release(); } return 0; }
OP GetRequest() { HANDLE h = GetRequestHandle(); for (;;) { DWORD rc = MsgWaitForMultipleObjectsEx(1, &h, INFINITE, QS_ALLEVENTS, 0); if (rc == WAIT_OBJECT_0) { return (OP)GetRequestParam(); } else { // pump messages so com runs
MSG msg; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
} }
HRESULT CreateRegEx() { CAutoLock lock(&m_WorkerLock); if (!m_pGIT) { HRESULT hr = m_pGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable, 0, CLSCTX_INPROC_SERVER); if (FAILED(hr)) { return hr; } // this is an expensive object to create. so, once we have one we hang onto it.
PQRegExp pRE; hr = pRE.CoCreateInstance(__uuidof(RegExp), NULL, CLSCTX_INPROC); if (FAILED(hr)) { return hr; } hr = pRE->put_IgnoreCase(VARIANT_TRUE); if (FAILED(hr)) { return hr; } hr = pRE->put_Global(VARIANT_TRUE); if (FAILED(hr)) { return hr; } ASSERT(!m_dwCookie); hr = m_pGIT->RegisterInterfaceInGlobal(pRE, __uuidof(IRegExp), &m_dwCookie); if (FAILED(hr)) { return hr; } } ASSERT(m_pGIT); ASSERT(m_dwCookie); return NOERROR; }
PQGIT m_pGIT; DWORD m_dwCookie; public: CRegExThread() : CBaseThread(COINIT_APARTMENTTHREADED), m_dwCookie(0) {} ~CRegExThread() { CallWorker(RETHREAD_EXIT); Close(); } DWORD GetCookie() { CAutoLock lock(&m_WorkerLock); return m_dwCookie; } }; // class CRegExThread
}; // namespace BDATuningModel
#endif //__RegExThread_H_
|