1 // Win32++ Version 7.3
\r
2 // Released: 30th November 2011
\r
6 // url: https://sourceforge.net/projects/win32-framework
\r
9 // Copyright (c) 2005-2011 David Nash
\r
11 // Permission is hereby granted, free of charge, to
\r
12 // any person obtaining a copy of this software and
\r
13 // associated documentation files (the "Software"),
\r
14 // to deal in the Software without restriction, including
\r
15 // without limitation the rights to use, copy, modify,
\r
16 // merge, publish, distribute, sublicense, and/or sell
\r
17 // copies of the Software, and to permit persons to whom
\r
18 // the Software is furnished to do so, subject to the
\r
19 // following conditions:
\r
21 // The above copyright notice and this permission notice
\r
22 // shall be included in all copies or substantial portions
\r
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
\r
26 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
\r
27 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
\r
28 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
\r
29 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
\r
30 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
31 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
32 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
\r
33 // OR OTHER DEALINGS IN THE SOFTWARE.
\r
35 ////////////////////////////////////////////////////////
\r
38 // The CThread class simplifies the use of threads with Win32++.
\r
39 // To use threads in your Win32++ application, inherit a class from
\r
40 // CThread, and override InitInstance. When your class is instanciated,
\r
41 // a new thread is started, and the InitInstance function is called to
\r
42 // run in the new thread.
\r
44 // If your thread is used to run one or more windows, InitInstance should
\r
45 // return TRUE, causing the MessageLoop function to be called. If your
\r
46 // thread doesn't require a MessageLoop, it should return FALSE. Threads
\r
47 // which don't run a message loop as sometimes referred to as "worker" threads.
\r
49 // Note: It is your job to end the thread before CThread ends!
\r
50 // To end a thread with a message loop, use PostQuitMessage on the thread.
\r
51 // To end a thread without a message loop, set an event, and end the thread
\r
52 // when the event is received.
\r
54 // Hint: It is never a good idea to use things like TerminateThread or ExitThread to
\r
55 // end your thread. These represent poor programming techniques, and are likely
\r
56 // to leak memory and resources.
\r
58 // More Hints for thread programming:
\r
59 // 1) Avoid using SendMessage between threads, as this will cause one thread to wait for
\r
60 // the other to respond. Use PostMessage between threads to avoid this problem.
\r
61 // 2) Access to variables and resources shared between threads need to be made thread safe.
\r
62 // Having one thread modify a resouce or variable while another thread is accessing it is
\r
63 // a recipe for disaster.
\r
64 // 3) Thread Local Storage (TLS) can be used to replace global variables to make them thread
\r
65 // safe. With TLS, each thread gets its own copy of the variable.
\r
66 // 4) Critical Sections can be used to make shared resources thread safe.
\r
67 // 5) Window messages (including user defined messages) can be posted between GUI threads to
\r
68 // communicate information between them.
\r
69 // 6) Events (created by CreateEvent) can be used to comunicate information between threads
\r
70 // (both GUI and worker threads).
\r
71 // 7) Avoid using sleep to synchronise threads. Generally speaking, the various wait
\r
72 // functions (e.g. WaitForSingleObject) will be better for this.
\r
75 // Each program that executes has a "process" allocated to it. A process has one or more
\r
76 // threads. Threads run independantly of each other. It is the job of the operating system
\r
77 // to manage the running of the threads, and do the task switching between threads as required.
\r
78 // Systems with multiple CPUs will be able to run as many threads simultaneously as there are
\r
81 // Threads behave like a program within a program. When the main thread starts, the application
\r
82 // runs the WinMain function and ends when WinMain ends. When another thread starts, it too
\r
83 // will run the function provided to it, and end when that function ends.
\r
86 #ifndef _WIN32XX_WINTHREAD_H_
\r
87 #define _WIN32XX_WINTHREAD_H_
\r
90 #include <process.h>
\r
96 //////////////////////////////////////
\r
97 // Declaration of the CThread class
\r
103 CThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag);
\r
104 virtual ~CThread();
\r
107 virtual BOOL InitInstance();
\r
108 virtual int MessageLoop();
\r
111 HANDLE GetThread() const;
\r
112 int GetThreadID() const;
\r
113 int GetThreadPriority() const;
\r
114 DWORD ResumeThread() const;
\r
115 BOOL SetThreadPriority(int nPriority) const;
\r
116 DWORD SuspendThread() const;
\r
119 CThread(const CThread&); // Disable copy construction
\r
120 CThread& operator = (const CThread&); // Disable assignment operator
\r
121 void CreateThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag);
\r
122 static UINT WINAPI StaticThreadCallback(LPVOID pCThread);
\r
124 HANDLE m_hThread; // Handle of this thread
\r
125 UINT m_nThreadID; // ID of this thread
\r
130 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
135 ///////////////////////////////////////
\r
136 // Definitions for the CThread class
\r
138 inline CThread::CThread() : m_hThread(0), m_nThreadID(0)
\r
140 CreateThread(0, 0, CREATE_SUSPENDED);
\r
143 inline CThread::CThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag)
\r
144 : m_hThread(0), m_nThreadID(0)
\r
147 // Valid argument values:
\r
148 // pSecurityAttributes Either a pointer to SECURITY_ATTRIBUTES or 0
\r
149 // stack_size Either the stack size or 0
\r
150 // initflag Either CREATE_SUSPENDED or 0
\r
152 CreateThread(pSecurityAttributes, stack_size, initflag);
\r
155 inline CThread::~CThread()
\r
157 // A thread's state is set to signalled when the thread terminates.
\r
158 // If your thread is still running at this point, you have a bug.
\r
159 if (0 != WaitForSingleObject(m_hThread, 0))
\r
160 TRACE(_T("*** Error *** Ending CThread before ending its thread\n"));
\r
162 // Close the thread's handle
\r
163 ::CloseHandle(m_hThread);
\r
166 inline void CThread::CreateThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag)
\r
168 // NOTE: By default, the thread is created in the default state.
\r
169 m_hThread = (HANDLE)_beginthreadex(pSecurityAttributes, stack_size, CThread::StaticThreadCallback, (LPVOID) this, initflag, &m_nThreadID);
\r
171 if (0 == m_hThread)
\r
172 throw CWinException(_T("Failed to create thread"));
\r
175 inline HANDLE CThread::GetThread() const
\r
181 inline int CThread::GetThreadID() const
\r
184 return m_nThreadID;
\r
187 inline int CThread::GetThreadPriority() const
\r
190 return ::GetThreadPriority(m_hThread);
\r
193 inline BOOL CThread::InitInstance()
\r
195 // Override this function to perform tasks when the thread starts.
\r
197 // return TRUE to run a message loop, otherwise return FALSE.
\r
198 // A thread with a window must run a message loop.
\r
202 inline int CThread::MessageLoop()
\r
204 // Override this function if your thread needs a different message loop
\r
205 return GetApp()->MessageLoop();
\r
208 inline DWORD CThread::ResumeThread() const
\r
211 return ::ResumeThread(m_hThread);
\r
214 inline DWORD CThread::SuspendThread() const
\r
217 return ::SuspendThread(m_hThread);
\r
220 inline BOOL CThread::SetThreadPriority(int nPriority) const
\r
223 return ::SetThreadPriority(m_hThread, nPriority);
\r
226 inline UINT WINAPI CThread::StaticThreadCallback(LPVOID pCThread)
\r
227 // When the thread starts, it runs this function.
\r
229 // Get the pointer for this CMyThread object
\r
230 CThread* pThread = (CThread*)pCThread;
\r
232 if (pThread->InitInstance())
\r
233 return pThread->MessageLoop();
\r
240 #endif // #define _WIN32XX_WINTHREAD_H_
\r