Subversion Repositories HomeAutomation

Rev

Go to most recent revision | Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
270 johboh 1
#ifndef __THREAD_H__
2
#define __THREAD_H__
3
 
4
class CThread
5
{
6
public:
7
		/*
8
		 *	Info: Default Constructor
9
		 */
10
		CThread()
11
		{ 
12
			m_pThreadFunc = CThread::EntryPoint; // Can call Detach() also.
13
		}
14
 
15
		/*
16
		 *	Info: Plug Constructor
17
		 *
18
		 *	Use this to migrate/port existing worker threads to objects immediately
19
		 *  Although you lose the benefits of ThreadCTOR and ThreadDTOR.
20
		 */
21
		CThread(LPTHREAD_START_ROUTINE lpExternalRoutine)
22
		{
23
			Attach(lpExternalRoutine);
24
		}
25
 
26
		/*
27
		 *	Info: Default Destructor
28
		 *
29
		 *	I think it is wise to destroy the thread even if it is running,
30
		 *  when the main thread reaches here.
31
		 */
32
		~CThread()
33
		{
34
			if ( m_ThreadCtx.m_hThread )
35
				Stop(true);
36
		}
37
		/*
38
		 *	Info: Starts the thread.
39
		 *	
40
		 *	This function starts the thread pointed by m_pThreadFunc with default attributes
41
		 */
42
		DWORD Start( void* arg = NULL )
43
		{
44
			m_ThreadCtx.m_pUserData = arg;
45
			m_ThreadCtx.m_hThread = CreateThread(NULL, 0, m_pThreadFunc, this, 0, &m_ThreadCtx.m_dwTID);
46
			m_ThreadCtx.m_dwExitCode = (DWORD)-1;
47
 
48
			return GetLastError();
49
		}
50
 
51
		/*
52
		 *	Info: Stops the thread.
53
		 *	
54
		 *	This function stops the current thread. 
55
		 *	We can force kill a thread which results in a TerminateThread.
56
		 */
57
		DWORD Stop ( bool bForceKill = false )
58
		{
59
			if ( m_ThreadCtx.m_hThread )
60
			{
61
				GetExitCodeThread(m_ThreadCtx.m_hThread, &m_ThreadCtx.m_dwExitCode);
62
 
63
				if ( m_ThreadCtx.m_dwExitCode == STILL_ACTIVE && bForceKill )
64
					TerminateThread(m_ThreadCtx.m_hThread, DWORD(-1));
65
 
66
				m_ThreadCtx.m_hThread = NULL;
67
			}
68
 
69
			return m_ThreadCtx.m_dwExitCode;
70
		}
71
 
72
		/*
73
		 *	Info: Starts the thread.
74
		 *	
75
		 *	This function starts the thread pointed by m_pThreadFunc with default attributes
76
		 */
77
		DWORD GetExitCode() const 
78
		{ 
79
			if ( m_ThreadCtx.m_hThread )
80
				GetExitCodeThread(m_ThreadCtx.m_hThread, (LPDWORD)&m_ThreadCtx.m_dwExitCode);
81
			return m_ThreadCtx.m_dwExitCode;
82
		}
83
 
84
		/*
85
		 *	Info: Attaches a Thread Function
86
		 *	
87
		 *	Used primarily for porting but can serve in developing generic thread objects
88
		 */
89
		void Attach( LPTHREAD_START_ROUTINE lpThreadFunc ){
90
			m_pThreadFunc = lpThreadFunc;
91
		}
92
 
93
		/*
94
		 *	Info: Detaches the Attached Thread Function
95
		 *	
96
		 *	Detaches the Attached Thread Function, If any.
97
		 *	by resetting the thread function pointer to EntryPoint1
98
		 */
99
		void  Detach( void ){
100
			m_pThreadFunc = CThread::EntryPoint; 
101
		}
102
 
103
protected:
104
 
105
		/*
106
		 *	Info: DONT override this method.
107
		 *	
108
		 *	This function is like a standard template. 
109
		 *	Override if you are sure of what you are doing.
110
		 */
111
		static DWORD WINAPI EntryPoint( LPVOID pArg)
112
		{
113
			CThread *pParent = reinterpret_cast<CThread*>(pArg);
114
 
115
			pParent->ThreadCtor();
116
 
117
			pParent->Run( pParent->m_ThreadCtx.m_pUserData );
118
 
119
			pParent->ThreadDtor();
120
 
121
			return STILL_ACTIVE;
122
		}
123
 
124
		/*
125
		 *	Info: Override this method.
126
		 *	
127
		 *	This function should contain the body/code of your thread.
128
		 *	Notice the signature is similar to that of any worker thread function
129
		 *  except for the calling convention.
130
		 */
131
		virtual DWORD Run( LPVOID /* arg */ )
132
		{ return m_ThreadCtx.m_dwExitCode; }
133
 
134
		/*
135
		 *	Info: Constructor-like function. 
136
		 *	
137
		 *	Will be called by EntryPoint before executing the thread body.
138
		 *  Override this function to provide your extra initialization.
139
		 *
140
		 *  NOTE: do not confuse it with the classes constructor
141
		 */
142
		virtual void ThreadCtor(){	}
143
 
144
		/*
145
		 *	Info: Destructor-like function. 
146
		 *	
147
		 *	Will be called by EntryPoint after executing the thread body.
148
		 *  Override this function to provide your extra destruction.
149
		 *
150
		 *  NOTE: do not confuse it with the classes constructor
151
		 */
152
		virtual void ThreadDtor(){	}
153
 
154
private:
155
		/*
156
		 *	Info: Thread Context Inner Class
157
		 *	
158
		 *	Every thread object needs to be associated with a set of values.
159
		 *	like UserData Pointer, Handle, Thread ID etc.
160
		 *  
161
		 *  NOTE: This class can be enhanced to varying functionalities
162
		 *		  eg.,
163
		 *				* Members to hold StackSize
164
		 *				* SECURITY_ATTRIBUTES member.
165
		 */
166
		class CThreadContext
167
		{
168
		public:
169
			CThreadContext(){
170
				memset(this, 0, sizeof(this));
171
			}
172
 
173
			/*
174
			 *	Attributes Section
175
			 */
176
		public:
177
			HANDLE m_hThread;					//	The Thread Handle
178
			DWORD  m_dwTID;						//	The Thread ID
179
			LPVOID m_pUserData;						//	The user data pointer
180
			LPVOID m_pParent;					//	The this pointer of the parent CThread object
181
			DWORD  m_dwExitCode;				//	The Exit Code of the thread
182
		};
183
 
184
		/*
185
		 *	Attributes Section
186
		 */
187
protected:
188
		/*
189
		 *	Info: Members of CThread
190
		 */
191
		CThreadContext			m_ThreadCtx;	//	The Thread Context member
192
		LPTHREAD_START_ROUTINE	m_pThreadFunc;	//	The Worker Thread Function Pointer
193
};
194
 
195
#endif //__THREAD_H__