1 //------------------------------------------------------------------------------ 2 // File: MsgThrd.h 3 // 4 // Desc: DirectShow base classes - provides support for a worker thread 5 // class to which one can asynchronously post messages. 6 // 7 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved. 8 //------------------------------------------------------------------------------ 9 10 11 // Message class - really just a structure. 12 // 13 class CMsg { 14 public: 15 UINT uMsg; 16 DWORD dwFlags; 17 LPVOID lpParam; 18 CAMEvent *pEvent; 19 CMsg(UINT u,DWORD dw,LPVOID lp,CAMEvent * pEvnt)20 CMsg(UINT u, DWORD dw, LPVOID lp, CAMEvent *pEvnt) 21 : uMsg(u), dwFlags(dw), lpParam(lp), pEvent(pEvnt) {} 22 CMsg()23 CMsg() 24 : uMsg(0), dwFlags(0L), lpParam(NULL), pEvent(NULL) {} 25 }; 26 27 // This is the actual thread class. It exports all the usual thread control 28 // functions. The created thread is different from a normal WIN32 thread in 29 // that it is prompted to perform particaular tasks by responding to messages 30 // posted to its message queue. 31 // 32 class AM_NOVTABLE CMsgThread { 33 private: 34 static DWORD WINAPI DefaultThreadProc(LPVOID lpParam); 35 DWORD m_ThreadId; 36 HANDLE m_hThread; 37 38 protected: 39 40 // if you want to override GetThreadMsg to block on other things 41 // as well as this queue, you need access to this 42 CGenericList<CMsg> m_ThreadQueue; 43 CCritSec m_Lock; 44 HANDLE m_hSem; 45 LONG m_lWaiting; 46 47 public: CMsgThread()48 CMsgThread() 49 : m_ThreadId(0), 50 m_hThread(NULL), 51 m_lWaiting(0), 52 m_hSem(NULL), 53 // make a list with a cache of 5 items 54 m_ThreadQueue(NAME("MsgThread list"), 5) 55 { 56 } 57 58 ~CMsgThread(); 59 // override this if you want to block on other things as well 60 // as the message loop 61 void virtual GetThreadMsg(CMsg *msg); 62 63 // override this if you want to do something on thread startup OnThreadInit()64 virtual void OnThreadInit() { 65 }; 66 67 BOOL CreateThread(); 68 WaitForThreadExit(LPDWORD lpdwExitCode)69 BOOL WaitForThreadExit(LPDWORD lpdwExitCode) { 70 if (m_hThread != NULL) { 71 WaitForSingleObject(m_hThread, INFINITE); 72 return GetExitCodeThread(m_hThread, lpdwExitCode); 73 } 74 return FALSE; 75 } 76 ResumeThread()77 DWORD ResumeThread() { 78 return ::ResumeThread(m_hThread); 79 } 80 SuspendThread()81 DWORD SuspendThread() { 82 return ::SuspendThread(m_hThread); 83 } 84 GetThreadPriority()85 int GetThreadPriority() { 86 return ::GetThreadPriority(m_hThread); 87 } 88 SetThreadPriority(int nPriority)89 BOOL SetThreadPriority(int nPriority) { 90 return ::SetThreadPriority(m_hThread, nPriority); 91 } 92 GetThreadHandle()93 HANDLE GetThreadHandle() { 94 return m_hThread; 95 } 96 GetThreadId()97 DWORD GetThreadId() { 98 return m_ThreadId; 99 } 100 101 102 void PutThreadMsg(UINT uMsg, DWORD dwMsgFlags, 103 LPVOID lpMsgParam, CAMEvent *pEvent = NULL) { 104 CAutoLock lck(&m_Lock); 105 CMsg* pMsg = new CMsg(uMsg, dwMsgFlags, lpMsgParam, pEvent); 106 m_ThreadQueue.AddTail(pMsg); 107 if (m_lWaiting != 0) { 108 ReleaseSemaphore(m_hSem, m_lWaiting, 0); 109 m_lWaiting = 0; 110 } 111 } 112 113 // This is the function prototype of the function that the client 114 // supplies. It is always called on the created thread, never on 115 // the creator thread. 116 // 117 virtual LRESULT ThreadMessageProc( 118 UINT uMsg, DWORD dwFlags, LPVOID lpParam, CAMEvent *pEvent) = 0; 119 }; 120 121