Click here to Skip to main content
Click here to Skip to main content

A C++ Thread Class

, 28 Jan 2004
Rate this:
Please Sign up or sign in to vote.
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

// 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

// 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:

// 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)

About the Author

Wytek Szymanski
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 Pinmembervxfade9-Aug-10 7:48 
Generali have to leave a mesage to you ! Pinmemberchenli051330-Mar-09 23:07 
Generalcin on thread problem Pinmemberoverlord_shimra9-Jul-08 8:13 
QuestionHow can one contact Wytek Szymanski, the author of this arcticle? PinmemberYossiMimon2-May-08 0:06 
GeneralRe: How can one contact Wytek Szymanski, the author of this arcticle? PinmemberJessn21-Oct-10 3:06 
Questioncan anybody help me!!!! PinmemberThinn Nwe Han14-Oct-07 17:23 
AnswerRe: can anybody help me!!!! [modified] PinmemberJessn21-Oct-10 2:16 
Generaltwo good realizations PinsussStanislav Panasik27-Jan-04 23:52 
GeneralRe: two good realizations PinmemberJesse Evans24-Mar-04 10:45 
GeneralRe: two good realizations PinsussStanislav Panasik25-Mar-04 19:00 
GeneralBuggy, not compilable and not well designed. PinmemberRolf Schaeuble27-Jan-04 21:04 
GeneralRe: Buggy, not compilable and not well designed. PinmemberNeville Franks27-Jan-04 22:10 
GeneralRe: Buggy, not compilable and not well designed. PinmemberGarth J Lancaster28-Jan-04 11:25 
GeneralRe: Buggy, not compilable and not well designed. PinmemberRolf Schaeuble28-Jan-04 12:14 
GeneralRe: Buggy, not compilable and not well designed. PinmemberGarth J Lancaster28-Jan-04 15:41 
GeneralRe: Buggy, not compilable and not well designed. PinmemberTodd Smith29-Jan-04 7:56 
GeneralRe: Buggy, not compilable and not well designed. PinmemberWytek Szymanski29-Jan-04 2:58 
GeneralRe: Buggy, not compilable and not well designed. Pinmemberrj459-May-07 7:39 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 29 Jan 2004
Article Copyright 2004 by Wytek Szymanski
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid