Click here to Skip to main content
6,306,412 members and growing! (20,266 online)
Email Password   helpLost your password?
General Programming » Threads, Processes & IPC » Threads     Intermediate License: The Code Project Open License (CPOL)

A C++ Thread Class

By Wytek Szymanski

An article on wrapping the Win32 threading APIs.
VC6, VC7.1VS.NET2003, Dev
Posted:27 Jan 2004
Updated:28 Jan 2004
Views:113,190
Bookmarked:18 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
32 votes for this article.
Popularity: 3.85 Rating: 2.56 out of 5
11 votes, 34.4%
1
7 votes, 21.9%
2
3 votes, 9.4%
3
4 votes, 12.5%
4
7 votes, 21.9%
5

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


Member
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.

Occupation: Web Developer
Location: United States United States

Other popular Threads, Processes & IPC articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 15 of 15 (Total in Forum: 15) (Refresh)FirstPrevNext
Generali have to leave a mesage to you ! Pinmemberchenli05130:07 31 Mar '09  
Generalcin on thread problem Pinmemberoverlord_shimra9:13 9 Jul '08  
QuestionHow can one contact Wytek Szymanski, the author of this arcticle? PinmemberYossiMimon1:06 2 May '08  
Generalcan anybody help me!!!! PinmemberThinn Nwe Han18:23 14 Oct '07  
Generaltwo good realizations PinsussStanislav Panasik0:52 28 Jan '04  
GeneralRe: two good realizations PinmemberJesse Evans11:45 24 Mar '04  
GeneralRe: two good realizations PinsussStanislav Panasik20:00 25 Mar '04  
GeneralBuggy, not compilable and not well designed. PinmemberRolf Schaeuble22:04 27 Jan '04  
GeneralRe: Buggy, not compilable and not well designed. PinmemberNeville Franks23:10 27 Jan '04  
GeneralRe: Buggy, not compilable and not well designed. PinmemberGarth J Lancaster12:25 28 Jan '04  
GeneralRe: Buggy, not compilable and not well designed. PinmemberRolf Schaeuble13:14 28 Jan '04  
GeneralRe: Buggy, not compilable and not well designed. PinmemberGarth J Lancaster16:41 28 Jan '04  
GeneralRe: Buggy, not compilable and not well designed. PinmemberTodd Smith8:56 29 Jan '04  
GeneralRe: Buggy, not compilable and not well designed. PinmemberWytek Szymanski3:58 29 Jan '04  
GeneralRe: Buggy, not compilable and not well designed. Pinmemberrj458:39 9 May '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 28 Jan 2004
Editor: Nishant Sivakumar
Copyright 2004 by Wytek Szymanski
Everything else Copyright © CodeProject, 1999-2009
Web15 | Advertise on the Code Project