Click here to Skip to main content
15,881,803 members
Articles / Programming Languages / C++
Article

A C++ Thread Class

Rate me:
Please Sign up or sign in to vote.
2.95/5 (34 votes)
28 Jan 2004CPOL3 min read 197.9K   2.4K   33   18
An article on wrapping the Win32 threading APIs.

Introduction

The C++ language invites for object oriented programming. The Win32 API is entirely based on the C programming language. Writing software for the Windows platform always requires the use of the Win32 API. Many developers who prefer C++ and object oriented programming would wish to have available appropriate C++ class libraries, to give their software a consistent object oriented look and feel.

The immense popularity of Java, and now .NET, is mostly based on the large number of classes that in fact make up the programming platform. Java and .NET application programmers just simply write their applications utilizing these classes whereas, by contrast, C++ programmers first write an infrastructure and then use it to write the applications. In this article, I will show you how to write a simple C++ class that wraps the Win32 thread related APIs.

Class Thread

The Java and .NET platform already have proposed some very good models and so we might as well make our model look similar. The advantage of it is that anyone familiar with Java or .NET can easily relate to it.

The threading models in Java as well as in .NET require that a thread object accepts a class method as its thread procedure. Here is an illustration:

Threading in Java

JavaScript
// define class with a threadable method
public class MyObject implements Runnable {
  // the thread procedure
  public void run() {
    // TODO: put the code here
  }
}

MyObject obj = new MyObject();
Thread thread = new Thread(obj);
tread.start();

Threading in .NET

C#
// define class with a threadable method
public class MyObject {
  // the thread procedure
  public void Run() {
    // TODO: put the code here
  }
}

MyObject obj = new MyObject();
Thread thread = new Thread(new ThreadStart(obj.Run));
tread.Start();

The models are remarkably similar. Java requires the threadable object to implement the Runnable interface, and .NET, in a way, requires the same thing because the Thread classes on either platform expects a threadable procedure to be of this form: public void run().

The Java specification is rather simple. Just one simple interface exposing one simple method. The .NET specification is more sophisticated. The 'delegate' concept lends greater flexibility to the writing of multi-threaded programs. Here is an illustration:

C#
// create a threadable object
public class MyObject {
  // first thread procedure
  public void ThreadProc1() {
    // TODO:    
  }
  // second thread procedure
  public void ThreadProc2() {
    // TODO:
  }
}

MyObject obj = new MyObject();

// create first thread
Thread thread1 = new Thread( new ThreadStart(obj.ThreadProc1) );
thread1.Start();

//create second thread
Thread thread2 = new Thread( new ThreadStart(obj.ThreadProc2) );
thread2.Start();

The .NET threading model offers more advantages. Any class method that is compatible with the ThreadStart delegate can be run as a thread procedure. And as the code snippet above illustrates, a single object instance can concurrently be accessed and manipulated by multiple threads. This is a very powerful feature.

We naturally prefer a C++ threading model to be as simple as that of Java and as flexible as that of .NET. Let us focus first on the Java-like simplicity. Here is a proposal:

// define the interface
struct IRunnable {
  virtual void run() = 0;
};

// define the thread class
class Thread {
public:
  Thread(IRunnable *ptr) {
    _threadObj = ptr;
  }
  void start() {
    // use the Win32 API here
    DWORD threadID;
    ::CreateThread(0, 0, threadProc, _threadObj, 0, &threadID);
  }
  
protected:
  // Win32 compatible thread parameter and procedure 
  IRunnable *_threadObj; 
  static unsigned long __stdcall threadProc(void* ptr) {
    ((IRunnable*)ptr)->run();
    return 0;
  }   
};

We can now write a multi-threaded program as elegantly as the Java folks can do.

// define class with a threadable method
class MyObject : IRunnable {
public:
  // the thread procedure
  virtual void run() {
    // TODO: put the code here
  }
}

MyObject *obj = new MyObject();
Thread thread = new Thread(obj);
tread->start();

It is so simple because we have buried the Win32 API call into a wrapper class. The neat trick here is the static method defined as part of our Thread class. We have thus emulated the simpler Java Thread class.

The .NET Thread and ThreadStart approach is a little harder to emulate. But we can still realize it in a way by using pointers to class methods. Here is the example:

// define class with a threadable method
class MyObject : IRunnable {
 // pointer to a class method
 typedef void (MyObject::* PROC)();
 PROC fp;
 
 // first thread procedure
 void threadProc1() {
   //TODO: code for this thread procedure
 }
 // second thread procedure
 void threadProc2() {
   //TODO: code for this thread procedure
 }
    
public:
  MyObject() {
    fp = threadProc1;
  }
  void setThreadProc(int n) {
    if(n == 1) 
        fp = threadProc1;
    else
    if(n == 2)
        fp = threadProc2;
  }
  // the thread procedure
  virtual void run() {
    (this->*fp)();
  }
};

MyObject *obj = new MyObject();

obj->setThreadProc(1);
Thread *thread1 = new Thread(obj);
thread1->start();

obj->setThreadProc(2);
Thread *thread2 = new Thread(obj);
thread2->start();

The actual threadable method run() now uses a pointer to a class method to run the appropriate thread procedure. That pointer must be correctly initialized before a new thread is started.

Conclusion

Wrapping the Win32 APIs into C++ classes is the preferred practice. The Java and .NET platforms provide us with well defined models. And by comparison, these models are so similar that defining C++ classes for a thread class, socket class, stream class, etc. should just be a matter of following the provided documentation.

You may download the Thread class and try it out. I have designed it to be as simple as possible but you may enhance it by wrapping an additional number of thread related APIs, e.g. SetThreadPriority, GetThreadPriority etc.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
I am a consultant, trainer, software archtect/engineer, since the early 1980s, working in the greater area of Boston, MA, USA.

My work comprises the entire spectrum of software, shrink-wrapped applications, IT client-server, systems and protocol related work, compilers and operating systems, and more ....

I am currently focused on platform development for distributed computing in service oriented data centers.

Comments and Discussions

 
GeneralMy vote of 4 Pin
Patz Huang9-Aug-10 7:48
Patz Huang9-Aug-10 7:48 
Generali have to leave a mesage to you ! Pin
chenli051330-Mar-09 23:07
chenli051330-Mar-09 23:07 
Generalcin on thread problem Pin
overlord_shimra9-Jul-08 8:13
overlord_shimra9-Jul-08 8:13 
QuestionHow can one contact Wytek Szymanski, the author of this arcticle? Pin
YossiMimon2-May-08 0:06
YossiMimon2-May-08 0:06 
GeneralRe: How can one contact Wytek Szymanski, the author of this arcticle? Pin
Jessn21-Oct-10 3:06
Jessn21-Oct-10 3:06 
Questioncan anybody help me!!!! Pin
Thinn Nwe Han14-Oct-07 17:23
Thinn Nwe Han14-Oct-07 17:23 
AnswerRe: can anybody help me!!!! [modified] Pin
Jessn21-Oct-10 2:16
Jessn21-Oct-10 2:16 
Generaltwo good realizations Pin
Stanislav Panasik27-Jan-04 23:52
Stanislav Panasik27-Jan-04 23:52 
GeneralRe: two good realizations Pin
Jesse Evans24-Mar-04 10:45
Jesse Evans24-Mar-04 10:45 
GeneralRe: two good realizations Pin
Stanislav Panasik25-Mar-04 19:00
Stanislav Panasik25-Mar-04 19:00 
GeneralBuggy, not compilable and not well designed. Pin
Rolf Schaeuble27-Jan-04 21:04
Rolf Schaeuble27-Jan-04 21:04 
GeneralRe: Buggy, not compilable and not well designed. Pin
Neville Franks27-Jan-04 22:10
Neville Franks27-Jan-04 22:10 
GeneralRe: Buggy, not compilable and not well designed. Pin
Garth J Lancaster28-Jan-04 11:25
professionalGarth J Lancaster28-Jan-04 11:25 
GeneralRe: Buggy, not compilable and not well designed. Pin
Rolf Schaeuble28-Jan-04 12:14
Rolf Schaeuble28-Jan-04 12:14 
GeneralRe: Buggy, not compilable and not well designed. Pin
Garth J Lancaster28-Jan-04 15:41
professionalGarth J Lancaster28-Jan-04 15:41 
GeneralRe: Buggy, not compilable and not well designed. Pin
Todd Smith29-Jan-04 7:56
Todd Smith29-Jan-04 7:56 
GeneralRe: Buggy, not compilable and not well designed. Pin
Wytek Szymanski29-Jan-04 2:58
Wytek Szymanski29-Jan-04 2:58 
GeneralRe: Buggy, not compilable and not well designed. Pin
rj459-May-07 7:39
rj459-May-07 7:39 
This is a great article, because it illuminates how great Java and .Net do threading. What I mean is specifically is that their design is so elegant compared to anything I have seen in c++ ( so far but I'm no expert ). So I like this article, but it doesn't mean I'm not going to read others. I wouldn't advise anyone to go to code project and drop a sample into their production program, especially if you are a junior programmer. You always have to get a few diffrent sources out there and read the MSDN docs on the underlying calls.

So stop flaming people who work for *free* to post their articles. The constructive critisim part is great, and appreciated however.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.