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