| //------------------------------------------------------------------------------ | |
| // File: MsgThrd.h | |
| // | |
| // Desc: DirectShow base classes - provides support for a worker thread | |
| // class to which one can asynchronously post messages. | |
| // | |
| // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. | |
| //------------------------------------------------------------------------------ | |
| // Message class - really just a structure. | |
| // | |
| class CMsg { | |
| public: | |
| UINT uMsg; | |
| DWORD dwFlags; | |
| LPVOID lpParam; | |
| CAMEvent *pEvent; | |
| CMsg(UINT u, DWORD dw, __inout_opt LPVOID lp, __in_opt CAMEvent *pEvnt) | |
| : uMsg(u), dwFlags(dw), lpParam(lp), pEvent(pEvnt) {} | |
| CMsg() | |
| : uMsg(0), dwFlags(0L), lpParam(NULL), pEvent(NULL) {} | |
| }; | |
| // This is the actual thread class. It exports all the usual thread control | |
| // functions. The created thread is different from a normal WIN32 thread in | |
| // that it is prompted to perform particaular tasks by responding to messages | |
| // posted to its message queue. | |
| // | |
| class AM_NOVTABLE CMsgThread { | |
| private: | |
| static DWORD WINAPI DefaultThreadProc(__inout LPVOID lpParam); | |
| DWORD m_ThreadId; | |
| HANDLE m_hThread; | |
| protected: | |
| // if you want to override GetThreadMsg to block on other things | |
| // as well as this queue, you need access to this | |
| CGenericList<CMsg> m_ThreadQueue; | |
| CCritSec m_Lock; | |
| HANDLE m_hSem; | |
| LONG m_lWaiting; | |
| public: | |
| CMsgThread() | |
| : m_ThreadId(0), | |
| m_hThread(NULL), | |
| m_lWaiting(0), | |
| m_hSem(NULL), | |
| // make a list with a cache of 5 items | |
| m_ThreadQueue(NAME("MsgThread list"), 5) | |
| { | |
| } | |
| ~CMsgThread(); | |
| // override this if you want to block on other things as well | |
| // as the message loop | |
| void virtual GetThreadMsg(__out CMsg *msg); | |
| // override this if you want to do something on thread startup | |
| virtual void OnThreadInit() { | |
| }; | |
| BOOL CreateThread(); | |
| BOOL WaitForThreadExit(__out LPDWORD lpdwExitCode) { | |
| if (m_hThread != NULL) { | |
| WaitForSingleObject(m_hThread, INFINITE); | |
| return GetExitCodeThread(m_hThread, lpdwExitCode); | |
| } | |
| return FALSE; | |
| } | |
| DWORD ResumeThread() { | |
| return ::ResumeThread(m_hThread); | |
| } | |
| DWORD SuspendThread() { | |
| return ::SuspendThread(m_hThread); | |
| } | |
| int GetThreadPriority() { | |
| return ::GetThreadPriority(m_hThread); | |
| } | |
| BOOL SetThreadPriority(int nPriority) { | |
| return ::SetThreadPriority(m_hThread, nPriority); | |
| } | |
| HANDLE GetThreadHandle() { | |
| return m_hThread; | |
| } | |
| DWORD GetThreadId() { | |
| return m_ThreadId; | |
| } | |
| void PutThreadMsg(UINT uMsg, DWORD dwMsgFlags, | |
| __in_opt LPVOID lpMsgParam, __in_opt CAMEvent *pEvent = NULL) { | |
| CAutoLock lck(&m_Lock); | |
| CMsg* pMsg = new CMsg(uMsg, dwMsgFlags, lpMsgParam, pEvent); | |
| m_ThreadQueue.AddTail(pMsg); | |
| if (m_lWaiting != 0) { | |
| ReleaseSemaphore(m_hSem, m_lWaiting, 0); | |
| m_lWaiting = 0; | |
| } | |
| } | |
| // This is the function prototype of the function that the client | |
| // supplies. It is always called on the created thread, never on | |
| // the creator thread. | |
| // | |
| virtual LRESULT ThreadMessageProc( | |
| UINT uMsg, DWORD dwFlags, __inout_opt LPVOID lpParam, __in_opt CAMEvent *pEvent) = 0; | |
| }; | |