Monday, July 23, 2007

C++: A nice thread class

Java and .Net have very nice and easy ways to create threads. We can trun any class into a thread within seconds and that's probably one of their coolest features. As a Win32 C++ programmer, we don't have this advantage. But we can achieve this very easily. Here is how.

Following is my thread class which you need to include to make threading a piece of cake.

The class:
  1 class Thread
2
{
3
public:
4
Thread()
5
{
6
hThread = 0;
7
}
8
9
void start()
10
{
11
_threadObj = this;
12
13
DWORD threadID;
14
hThread = CreateThread(0, 0, threadProc, _threadObj, 0, &threadID);
15
}
16
17
void stop()
18
{
19
if (hThread)
20
TerminateThread (hThread, 0);
21
}
22
23
virtual void run() = 0;
24
25
protected:
26
static unsigned long __stdcall threadProc(void* ptr)
27
{
28
((Thread*)ptr)->run();
29
return 0;
30
}
31
32
Thread *_threadObj;
33
HANDLE hThread;
34
};
35

Example of usages:
 36 class YourClass: public Thread
37
{
38
public:
39
YourClass() { }
40
~YourClass() { }
41
42
//the run function, you need to override this one
43
void run();
44
45
private:
46
//private variables
47
};
48
49
void YourClass::run()
50
{
51
//Add your threaded code here
52
}
53
54
int main()
55
{
56
YourClass obj;
57
obj.start();
58
59
//the thread is running
60
61
obj.stop();
62
63
//the thread is stopped
64
return 0;
65
}
66


Looks cool, right? It's your turn to try it. Happy threading.

6 comments:

M. Kaisar Ul Haque said...

As I've moved this post from my another blog, I'm posting previous comments here:

Ishtiaque said...

As far as I remember "TerminateThread" should be the last resort to to end a thread. I normally end a thread by returning from the Thread function or calling ExitThread within the thread function. To close a thread from outside we can use wait and signal function accordingly. Heres a qoute about TerminateThread from the MSDN.

"TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
If the target thread owns a critical section, the critical section will not be released.
If the target thread is allocating memory from the heap, the heap lock will not be released.
If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
A thread cannot protect itself against TerminateThread, other than by controlling access to its handles. The thread handle returned by the CreateThread and CreateProcess functions has THREAD_TERMINATE access, so any caller holding one of these handles can terminate your thread."
July 23, 2007 3:52 AM




M. Kaisar Ul Haque said...

Thanks Touhid bhai for your comments. I agree to the problems regarding TerminateThread. This class is just a quick 'proof of concept' and of course, there several more problems/issues with this design including synchronization, etc.

However, according to the purpose, the Thread class will handle 'threading' codes and stuffs, and the coder will derive his own class from it and use threading with ease. So if the coder needs to use 'ExitThread' or 'return' within the run() method, then the coder will again have the headaches about thread related codes.

We need some alternatives to asking coder to call ExitThread or returning. We need to have some code in stop() method so that it can 'gracefully' terminate the thread without any hazzard.

For that, we can have the following scenario: There will be another function threadrun() which will be called first when the Thread is started using start(). The threadrun() will have a message loop for the thread. Inside the loop it will can run() which will contain user code. run() will return bool value, if the value is true, the message loop in threadrun() will continue. The stop() method will contain code like: PostThreadMessage(ThreadId, WM_QUIT). So, in the threadrun() method when the message is received, we can quit the thread safely.

So, if the user don't want a loop to run he'll return false from run(). And he can gracefully terminate the thread using stop().

This look safer, what do you think?

July 23, 2007 4:40 AM

Anonymous said...

Thanks. It is exactly what I needed.

Bujal Hassan said...

Thanks...this class really help me alot...

i have an enquiry...

if let say i called twice

Obj->start();

does it means...it will create two threads....if the first call thread is not finish yet... ??

Mohammad Kaisar Ul Haque said...

@Bujal Hassan:

Sorry for the late reply.

Yes, calling start() twice will create a second thread (two threadds in total) and you'll loose reference/handle to the first thread created with the first call.

Andy said...

Doesn't your class require a virtual destructor since it's a base class?

koby said...

Beautiful code