///////////////////////////////////////////////////////////////////////////////////// // BroadcastEventService.h : Declaration of the CBroadcastEventService // Copyright (c) Microsoft Corporation 2001. #ifndef __BROADCASTEVENTSERVICE_H_ #define __BROADCASTEVENTSERVICE_H_ #pragma once #include #include "w32extend.h" #include "regexthread.h" #include #include "tuner.h" namespace BDATuningModel { typedef CComQIPtr PQBroadcastEvent; typedef std::list AdviseList; typedef std::queue EventQ; class CReflectionThread : public CBaseThread { public: typedef enum OP { RETHREAD_NOREQUEST, RETHREAD_FIRE, RETHREAD_EXIT, } OP; private: virtual DWORD ThreadProc(void) { PQGIT pGIT(CLSID_StdGlobalInterfaceTable, 0, CLSCTX_INPROC_SERVER); if (!pGIT) { TRACELM(TRACE_ERROR, "CReflectionThread::ThreadProc() can't create GIT"); return 1; } for (;;) { OP req = GetRequest(); switch (req) { case RETHREAD_FIRE: { Fire(pGIT); break; } case RETHREAD_EXIT: goto exit_thread; }; }; exit_thread: return 0; } OP GetRequest() { HANDLE h[2]; h[0] = m_EventSend; h[1] = m_EventTerminate; for (;;) { DWORD rc = MsgWaitForMultipleObjectsEx(2, h, INFINITE, QS_ALLEVENTS, 0); if (rc == WAIT_OBJECT_0) { m_EventSend.Reset(); return RETHREAD_FIRE; } else if (rc == WAIT_OBJECT_0 + 1) { return RETHREAD_EXIT; } else { // pump messages so com runs MSG msg; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } } HRESULT Fire(PQGIT& pGIT); bool GetNextEvent(GUID& g); void GetAdviseList(AdviseList& l); PQGIT m_pGIT; DWORD m_dwCookie; EventQ m_FiringQ; CAMEvent m_EventTerminate; AdviseList m_AdviseList; public: CReflectionThread() : CBaseThread(COINIT_APARTMENTTHREADED), m_dwCookie(0) {} ~CReflectionThread() { m_EventTerminate.Set(); Close(); } HRESULT PostFire(GUID& g) { CAutoLock lock(&m_WorkerLock); m_FiringQ.push(g); // signal the worker thread m_EventSend.Set(); return NOERROR; } HRESULT Advise(PUnknown& p, DWORD* pdwCookie); HRESULT Unadvise(DWORD dwCookie); }; // class CReflectionThread ///////////////////////////////////////////////////////////////////////////// // CBroadcastEventService class ATL_NO_VTABLE CBroadcastEventService : public CComObjectRootEx, public CComCoClass, public IObjectWithSiteImplSec, public IBroadcastEvent, public IConnectionPoint { public: CBroadcastEventService() { m_pRT = new CReflectionThread; if (!m_pRT->Create()) { THROWCOM(E_UNEXPECTED); } } virtual ~CBroadcastEventService() { if (m_pRT) { delete m_pRT; m_pRT = NULL; } } REGISTER_NONAUTOMATION_OBJECT_WITH_TM(IDS_REG_TUNEROBJ, IDS_REG_TUNINGSPACECONTAINER_DESC, LIBID_TunerLib, CLSID_BroadcastEventService, tvBoth); DECLARE_NOT_AGGREGATABLE(CBroadcastEventService) BEGIN_COM_MAP(CBroadcastEventService) COM_INTERFACE_ENTRY(IBroadcastEvent) COM_INTERFACE_ENTRY(IConnectionPoint) COM_INTERFACE_ENTRY(IObjectWithSite) END_COM_MAP_WITH_FTM() public: // IConnectionPointContainer // IBroadcastEventService STDMETHOD(Fire)(/*[in]*/ GUID EventID) { try { return m_pRT->PostFire(EventID); } catch(...) { return E_UNEXPECTED; } } STDMETHOD(Advise)(LPUNKNOWN pUnk, LPDWORD pdwCookie) { if (!pUnk || !pdwCookie) { return E_POINTER; } try { return m_pRT->Advise(PUnknown(pUnk), pdwCookie); } catch(...) { return E_UNEXPECTED; } } STDMETHOD(Unadvise)(DWORD dwCookie) { try { return m_pRT->Unadvise(dwCookie); } catch(...) { return E_UNEXPECTED; } } STDMETHOD(EnumConnections)(IEnumConnections **ppEnum) { return E_NOTIMPL; } STDMETHOD(GetConnectionInterface)(IID* pIID) { if (!pIID) { return E_POINTER; } try { memcpy(pIID, &IID_IBroadcastEvent, sizeof(*pIID)); return NOERROR; } catch(...) { return E_UNEXPECTED; } } STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer** pContainer) { return E_NOTIMPL; } protected: CReflectionThread *m_pRT; // worker thread }; }; #endif //__BROADCASTEVENTSERVICE_H_