Click here to Skip to main content
11,702,130 members (65,182 online)
Click here to Skip to main content

A Generic C++ Thread Class

, 14 Nov 2001 119.6K 1.7K 20
Rate this:
Please Sign up or sign in to vote.
This article presents a class that can either be readily used as a Container for existing worker threads or can be enhanced(inherited) for OO Style programming

Preface

It has been quite some time since I have been using code from code havens like code project and codeguru. Its payback time folks. Well not with something that can be readily used by all or many. But this is my sincere start.

In this article, I have tried to bring out the lack of Object Oriented Programmability in using Worker threads and overcome it. This project was more evolutionary than revolutionary. It started with the theory from Ryan Teixeira's work on Designing a Thread Class, for which I started with a basic shape. Then came the requirements for my current project for which I had to consider little/easy portability constraints.

Enough talking lets move on.

Things I wont deal here

I assume the audience is familiar with the concept of Threads / have heard of or used a worker thread atleast. My aim is to show how quick this class can bring you closer to OO Programming.

<!------------------------------- STEP 3 ---------------------------><!-- Add the article text. Please use simple formatting (

,

etc) -->

The Class

CThread class in its declaration form looks like below. I have gone against my coding practices (which i believe is pretty much same as many programmers ) and commented the code heavily in the source files for this purpose.
class CThread
{
public:
        /*
         *    Info: Default Constructor
         */
        CThread();

        /*
         *    Info: Plug Constructor
         */
        CThread(LPTHREAD_START_ROUTINE lpExternalRoutine);

        /*
         *    Info: Default Destructor
         */
        ~CThread();

        /*
         *    Info: Starts the thread.
         */
        DWORD Start( void* arg = NULL );

        /*
         *    Info: Stops the thread.
         */
        DWORD Stop ( bool bForceKill = false );

        /*
         *    Info: Starts the thread.
         */
        DWORD GetExitCode() const;

        /*
         *    Info: Attaches a Thread Function
         */
        void Attach( LPTHREAD_START_ROUTINE lpThreadFunc );

        /*
         *    Info: Detaches the Attached Thread Function
         */
        void  Detach( void );

protected:

        /*
         *    Info: DONT override this method.
         */
        static DWORD WINAPI EntryPoint( LPVOID pArg);
        
        /*
         *    Info: Override this method.
         */
        virtual DWORD Run( LPVOID arg );

        /*
         *    Info: Constructor-like function. 
         */
        virtual void ThreadCtor();

        /*
         *    Info: Destructor-like function. 
         */
        virtual void ThreadDtor();
        
private:
        /*
         *    Info: Thread Context Inner Class
         *    
         *    Every thread object needs to be associated with a set of values.
         *    like UserData Pointer, Handle, Thread ID etc.
         *  
         *  NOTE: This class can be enhanced to varying functionalities
         *          eg.,
         *                * Members to hold StackSize
         *                * SECURITY_ATTRIBUTES member.
         */
        class CThreadContext
        {
        public:
            CThreadContext();

            /*
             *    Attributes Section
             */
        public:
            HANDLE m_hThread;    // The Thread Handle
            DWORD  m_dwTID;      // The Thread ID
            LPVOID m_pUserData;  // The user data pointer
            LPVOID m_pParent;    // The this pointer of the parent CThread object
            DWORD  m_dwExitCode; // The Exit Code of the thread
        };

        /*
         *    Attributes Section
         */
protected:
        /*
         *    Info: Members of CThread
         */
        CThreadContext            m_ThreadCtx;    // The Thread Context member
        LPTHREAD_START_ROUTINE    m_pThreadFunc;  // The Worker Thread Function 
                                                  // Pointer
};

The Methods

Method Name Description
CThread() Uses the internal default EntryPoint static function as the ThreadFunc.
CThread( LPTHREAD_START_ROUTINE pThreadFunc) The plug constructor. This is used instead of creation and a call to Attach.
~CThread() Closes the thread object and destroys the thread. Can be changed if you dont want the thread to be terminated when the object destroys.
DWORD Start( LPVOID pArg = NULL ) This method starts/spawns the thread. returns any ERROR_SUCCESS if succeeded otherwise the error value as returned by GetLastError().
DWORD Stop( bool bForceKill = false ) This method returns the ExitCode if the thread has already terminated. the parameter optionally allows it to terminate the thread forcefully.
DWORD GetExitCode() const Returns the exit code of the last thread.
void Attach( LPTHREAD_START_ROUTINE lpThreadFunc )

I Admit, I borrowed this feature after knowing COM only. It is a great concept. Here, It is used to attach any Worker Thread function this makes the generic class itself readily usable. How? we will see soon.

void Detach( void ) This method removes the object from any hooked worker function to the default EntryPoint static method.
static DWORD WINAPI EntryPoint( LPVOID pArg ) This method is the only trick you need to do to get the class contain a worker thread, others are trivial.
virtual DWORD Run( LPVOID arg ) The body method, this is the method that should contain your worker thread code. Note: the signature is similar to your worker thread and that arg is the user data.
virtual void ThreadCtor() The mimic of a constructor for the life/scope of the thread to be spawned. you can override this method and write the Thread Level construction/initialization. This method will be called before the spawn/start of the thread.
virtual void ThreadDtor() The mimic of a destructor for the life/scope of the thread spawned. you can override this method and write the Thread Level Un-initialization. This method will be called after the end of the thread.

Usage

The best way to understand any code is through an example. So thats the way we do...

Scenario 1

This more like a common scenario than un-usual. Lets say you have worker thread function "Threaded"

DWORD WINAPI Threaded( LPVOID lpData )
{
    while(1)
    {
        printf("worker threaded code");
        Sleep(1000);
    }
}

And now you would like to USE & CONTROL it ( meaning its scope, life visibility etc.. ) in OO Style. This is how you would do it.

CThread t1;

t1.Attach(Threaded); // Threaded is the name of the worker function.

t1.Start();

//        ... Do something useful 

t1.Stop();

//    Alternatively

CThread t2(Threaded);

t2.Start();

//    ...    Do something useful

t2.Stop(true); // force kill if running.

There should be a catch. Well the catch is that you lose the CTOR and DTOR mimic functions ThreadCTOR() and ThreadDTOR() functionality and you cannot access any members or methods of the encapsulated class. But still, these were not our requirments. But what if they are...

Scenario 2

The OO Way. Even if it takes a few minutes this is the better way to do it.

You derive a class, and override only the run method and thats all there is to it. Well you may add as many members/methods you need.

class CDemoThread : public CThread
{
    virtual DWORD Run( LPVOID arg )
    { 
        while(1)
        {
            printf("Threaded Object Code \n");
            Sleep(1000);
        }
    }
};

Now, how do you use this. Not much difference.

CDemoThread dmt;

dmt.Start(NULL);

// ... do something useful

dmt.Stop(true);

Things to come

I am planning to update this class with more stuff. If anyone is interested or have anything in particular, do let me know.

Conclusion

We shall have code that is now Object Oriented. The benefits of Object Oriented Programming is way too much to realize at an early stage (Not inviting any debates).

Hope you all will find it useful!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Arun N Kumar
Web Developer
India India
Arun N Kumar is working at eCredit.com India Pvt Ltd since Dec 15, 1998. He's been programming in C/C++ for 4 years and Visual C++/MFC for almost 3 years now. His background is B.Sc Computer Science from Bangalore University, INDIA.

You may also be interested in...

Comments and Discussions

 
Questionplugging my own alternative, cross-platform version Pin
RJVB19-Aug-12 2:16
memberRJVB19-Aug-12 2:16 
GeneralMy vote of 5 Pin
tasumisra20-Sep-10 20:41
membertasumisra20-Sep-10 20:41 
Questionerror > Run must return a value Pin
Morthe19-Mar-07 0:54
memberMorthe19-Mar-07 0:54 
GeneralPoor design, poorer implementation Pin
DuncanMackay11-Sep-06 12:14
memberDuncanMackay11-Sep-06 12:14 
GeneralRe: Poor design, poorer implementation Pin
aj0aj03-Dec-06 22:06
memberaj0aj03-Dec-06 22:06 
GeneralHelp... start doesn't sent the parameter to thread procedure Pin
inbha7-Aug-05 22:58
memberinbha7-Aug-05 22:58 
GeneralRe: Help... start doesn't sent the parameter to thread procedure Pin
botus1-Mar-06 1:39
memberbotus1-Mar-06 1:39 
GeneralModified version of the class. Pin
Rickg2911-Sep-04 6:04
memberRickg2911-Sep-04 6:04 
QuestionWill it be completed? Pin
Henrik L8-Jun-04 22:28
memberHenrik L8-Jun-04 22:28 
QuestionCan I use your class in my project Pin
mathmoi9-Jan-04 22:32
membermathmoi9-Jan-04 22:32 
AnswerRe: Can I use your class in my project Pin
mathmoi9-Jan-04 22:34
membermathmoi9-Jan-04 22:34 
GeneralBug: thread handle not being recycled Pin
ckhoo4-Dec-03 9:23
memberckhoo4-Dec-03 9:23 
GeneralThreading for DCOM Pin
my quest22-Jul-02 8:14
membermy quest22-Jul-02 8:14 
GeneralBlocking calls in worker thread Pin
Jacob Anawalt4-Jan-02 8:55
memberJacob Anawalt4-Jan-02 8:55 
QuestionWhat about GUI threads? Pin
jbay@nebs.com20-Nov-01 11:01
memberjbay@nebs.com20-Nov-01 11:01 
GeneralSuspend and WaitFor Pin
David Hall16-Nov-01 9:42
memberDavid Hall16-Nov-01 9:42 
GeneralRe: Suspend and WaitFor Pin
torsten_hoff16-Nov-01 12:08
membertorsten_hoff16-Nov-01 12:08 
GeneralRe: Suspend and WaitFor Pin
Arun N Kumar16-Nov-01 16:56
memberArun N Kumar16-Nov-01 16:56 
GeneralRe: Suspend and WaitFor Pin
Arun N Kumar16-Nov-01 16:55
memberArun N Kumar16-Nov-01 16:55 
Generalunneeded files in source-zip Pin
zack15-Nov-01 1:20
memberzack15-Nov-01 1:20 
GeneralRe: unneeded files in source-zip Pin
Arun N Kumar15-Nov-01 1:53
memberArun N Kumar15-Nov-01 1:53 

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 | Terms of Use | Mobile
Web04 | 2.8.150819.1 | Last Updated 15 Nov 2001
Article Copyright 2001 by Arun N Kumar
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid