summaryrefslogtreecommitdiffstats
path: root/mmc_updater/depends/win32cpp/thread.h
blob: 5564d8883ab82cc785c2886f3c0f9af5d13d5762 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
// Win32++   Version 7.2
// Released: 5th AUgust 2011
//
//      David Nash
//      email: dnash@bigpond.net.au
//      url: https://sourceforge.net/projects/win32-framework
//
//
// Copyright (c) 2005-2011  David Nash
//
// Permission is hereby granted, free of charge, to
// any person obtaining a copy of this software and
// associated documentation files (the "Software"),
// to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify,
// merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom
// the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.
//
////////////////////////////////////////////////////////


// The CThread class simplifies the use of threads with Win32++.
// To use threads in your Win32++ application, inherit a class from
// CThread, and override InitInstance. When your class is instanciated,
// a new thread is started, and the InitInstance function is called to
// run in the new thread.

// If your thread is used to run one or more windows, InitInstance should 
// return TRUE, causing the MessageLoop function to be called. If your
// thread doesn't require a MessageLoop, it should return FALSE. Threads
// which don't run a message loop as sometimes referred to as "worker" threads.

// Note: It is your job to end the thread before CThread ends!
//       To end a thread with a message loop, use PostQuitMessage on the thread.
//       To end a thread without a message loop, set an event, and end the thread 
//       when the event is received.

// Hint: It is never a good idea to use things like TerminateThread or ExitThread to 
//       end your thread. These represent poor programming techniques, and are likely 
//       to leak memory and resources.

// More Hints for thread programming:
// 1) Avoid using SendMessage between threads, as this will cause one thread to wait for
//    the other to respond. Use PostMessage between threads to avoid this problem.
// 2) Access to variables and resources shared between threads need to be made thread safe.
//    Having one thread modify a resouce or variable while another thread is accessing it is
//    a recipe for disaster.
// 3) Thread Local Storage (TLS) can be used to replace global variables to make them thread
//    safe. With TLS, each thread gets its own copy of the variable.
// 4) Critical Sections can be used to make shared resources thread safe.
// 5) Window messages (including user defined messages) can be posted between GUI threads to
//    communicate information between them.
// 6) Events (created by CreateEvent) can be used to comunicate information between threads 
//    (both GUI and worker threads).
// 7) Avoid using sleep to synchronise threads. Generally speaking, the various wait 
//    functions (e.g. WaitForSingleObject) will be better for this.

// About Threads:
// Each program that executes has a "process" allocated to it. A process has one or more
// threads. Threads run independantly of each other. It is the job of the operating system
// to manage the running of the threads, and do the task switching between threads as required.
// Systems with multiple CPUs will be able to run as many threads simultaneously as there are
// CPUs. 

// Threads behave like a program within a program. When the main thread starts, the application 
// runs the WinMain function and ends when WinMain ends. When another thread starts, it too
// will run the function provided to it, and end when that function ends.


#ifndef _WIN32XX_WINTHREAD_H_
#define _WIN32XX_WINTHREAD_H_


#include <process.h>


namespace Win32xx
{

	//////////////////////////////////////
	// Declaration of the CThread class
	//
	class CThread
	{
	public:
		CThread();
		CThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag);
		virtual ~CThread();
		
		// Overridables
		virtual BOOL InitInstance();
		virtual int MessageLoop();

		// Operations
		HANDLE	GetThread()	const;
		int		GetThreadID() const;
		int		GetThreadPriority() const;
		DWORD	ResumeThread() const;
		BOOL	SetThreadPriority(int nPriority) const;
		DWORD	SuspendThread() const;

	private:
		CThread(const CThread&);				// Disable copy construction
		CThread& operator = (const CThread&);	// Disable assignment operator
		void CreateThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag);
		static	UINT WINAPI StaticThreadCallback(LPVOID pCThread);

		HANDLE m_hThread;			// Handle of this thread
		UINT m_nThreadID;			// ID of this thread
	};
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

namespace Win32xx
{

	///////////////////////////////////////
	// Definitions for the CThread class
	//
	inline CThread::CThread() : m_hThread(0), m_nThreadID(0)
	{
		CreateThread(0, 0, CREATE_SUSPENDED);
	}

	inline CThread::CThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag)
		: m_hThread(0), m_nThreadID(0)
										
	{
		// Valid argument values:
		// pSecurityAttributes		Either a pointer to SECURITY_ATTRIBUTES or 0
		// stack_size				Either the stack size or 0
		// initflag					Either CREATE_SUSPENDED or 0
		
		CreateThread(pSecurityAttributes, stack_size, initflag);
	}

	inline CThread::~CThread()
	{	
		// A thread's state is set to signalled when the thread terminates.
		// If your thread is still running at this point, you have a bug.
		if (0 != WaitForSingleObject(m_hThread, 0))
			TRACE(_T("*** Error *** Ending CThread before ending its thread\n"));

		// Close the thread's handle
		::CloseHandle(m_hThread);
	}

	inline void CThread::CreateThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag)
	{
		// NOTE:  By default, the thread is created in the default state.
		m_hThread = (HANDLE)_beginthreadex(pSecurityAttributes, stack_size, CThread::StaticThreadCallback, (LPVOID) this, initflag, &m_nThreadID);

		if (0 == m_hThread)
			throw CWinException(_T("Failed to create thread"));
	}

	inline HANDLE CThread::GetThread() const
	{
		assert(m_hThread);
		return m_hThread;
	}

	inline int CThread::GetThreadID() const 
	{
		assert(m_hThread);
		return m_nThreadID;
	}

	inline int CThread::GetThreadPriority() const
	{
		assert(m_hThread);
		return ::GetThreadPriority(m_hThread);
	}

	inline BOOL CThread::InitInstance()
	{
		// Override this function to perform tasks when the thread starts.

		// return TRUE to run a message loop, otherwise return FALSE.
		// A thread with a window must run a message loop.
		return FALSE;
	}

	inline int CThread::MessageLoop()
	{
		// Override this function if your thread needs a different message loop
		return GetApp()->MessageLoop();
	}

	inline DWORD CThread::ResumeThread() const
	{
		assert(m_hThread);
		return ::ResumeThread(m_hThread);
	}

	inline DWORD CThread::SuspendThread() const
	{
		assert(m_hThread);
		return ::SuspendThread(m_hThread); 
	}
	
	inline BOOL CThread::SetThreadPriority(int nPriority) const
	{
		assert(m_hThread);
		return ::SetThreadPriority(m_hThread, nPriority);
	}

	inline UINT WINAPI CThread::StaticThreadCallback(LPVOID pCThread)
	// When the thread starts, it runs this function.
	{
		// Get the pointer for this CMyThread object
		CThread* pThread = (CThread*)pCThread;

		if (pThread->InitInstance())
			return pThread->MessageLoop();

		return 0;
	}
	
}

#endif // #define _WIN32XX_WINTHREAD_H_