Click here to Skip to main content
11,478,066 members (71,755 online)
Click here to Skip to main content

Member Threads

, 1 May 2002 74.1K 864 42
Rate this:
Please Sign up or sign in to vote.
A template function that makes creating threads that use class member functions easier.
*********** Member Threads *************

<!-- Article Starts - DO NOT ADD HTML/BODY START TAGS--> <!-- Download Links -->

<!-- Add the rest of your HTML here -->

Introduction

It is often necessary, at least for the sake of clarity, to have a worker thread member of a class. Of course this is not possible, because member functions have a hidden parameter (the "this" pointer). A very easy workaround consists in declaring a static function that receives as a parameter the "this" pointer. After a casting, the proper member function can be called.

class CDemo
{
public:
    static DWORD WINAPI ThreadStub(LPVOID Parameter)
    {
        ((CDemo*)Parameter)->Thread();
    }
    void Thread()
    {
        for(int i=0;i<100;i++)
        {
            cout<<"Worker Thread: iteration n. "<<i<<endl;
        }
    }
};


int main(int argc, char* argv[])
{
    CDemo c;
    DWORD Dummy;
    HANDLE h=CreateThread(NULL,NULL,CDemo::ThreadStub,&c,NULL,&Dummy);
    WaitForSingleObject(h,INFINITE);
    return 0;
}
I find it, at the very least, a little awkward. Moreover, very often The first thing the Worker thread does is to fire an event. The father thread will be waiting for this event to make sure that the child has been actually born.

To avoid all this hassle, I created a very simple templated function, CreateMemberThread, that does all this work for us.

Following the same sample as above, we would replace the code in the main() function like this:

#include "memberthreads.h"
class CDemo
{
//no static stub!
....
....
}
int main(int argc, char* argv[])
{
    CDemo c;
    HANDLE h=CreateMemberThread<CDemo>(&c,CDemo::Thread);
    WaitForSingleObject(h,INFINITE);
    return 0;
}
I find it nice that the CDemo class in the example must not be derived by another class, and that the syntax is very reminiscent of the original Windows API syntax. One other interesting feature, is that the name of the member function is completely arbitrary, and that more than one member thread function can be defined in a single class.

Let's go to the implementation:

The structure ThreadData<> holds a pointer to the instance of the class, a pointer to the member function, and a handle to an event to signal the start of the thread.

template <class T>
struct ThreadData
{
public:
    typedef void (T::*TFunc)();
    HANDLE hEvent;
    T* pThreadObject;
    TFunc pThreadFunc;
    static DWORD _ThreadFunc(ThreadData<T>* pThis)
    {
        //copying data, because after SetEvent is called,
        //the caller thread could restart and delete the
        //local data
        ThreadData<T> td=*pThis;
        SetEvent(td.hEvent);
        ((*(td.pThreadObject)).*(td.pThreadFunc))();
        return 0;
    }
};
The function CreateMemberThread<> allocates on the stack a ThreadData<> structure, fills it, create an event, spawns the thread and waits for the event to be fired. That's it.
template <class T>
HANDLE CreateMemberThread(T* p,void (T::*func)())
{
    ThreadData<T> td;
    td.pThreadObject=p;
    td.pThreadFunc=func;
    td.hEvent=CreateEvent(NULL,0,0,NULL);
    DWORD Dummy;   //To make win 9x Happy with the lpThreadId param
    HANDLE ThreadHandle=CreateThread(NULL,NULL,
                            (LPTHREAD_START_ROUTINE)ThreadData<T>::_ThreadFunc,
                            &td,NULL,&Dummy);
    WaitForSingleObject(td.hEvent,INFINITE);
    ::CloseHandle(td.hEvent);
    return ThreadHandle;
}

Of course, nothing new has been invented, but I think that this could be an elegant way of solving a trivial problem. No MFC is needed, no giant #includes (apart from a windows.h in your stdafx.h!) Enjoy it.

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

Luca Piccarreta
Web Developer
Italy Italy
Studied engineering in Milan, degreed
in 1998 or so, and since then he worked
in the Politecnico di Milano.
During the past three years he's been
hardly working mostly for TILAB doing
a sw Implementation of an MPEG4 Video
Codec kicking ass (IMHO) to DivX and
WMVideo.
Other interests are 3D analysis-synthesis,
VRML, and recently AAC :(

Comments and Discussions

 
GeneralQuetions about the Member Threads template Pin
-e26-Jun-06 5:06
member-e26-Jun-06 5:06 
GeneralRe: Quetions about the Member Threads template Pin
Luca Piccarreta28-Jun-06 12:26
memberLuca Piccarreta28-Jun-06 12:26 
Hi Eric,
Sorry for the late answer.

Lots of questions...
1) Suppose that CreateMemberThread returns instantly before the
thread is started...
the local variable
ThreadData td;
goes out of scope... disaster! the thread will reference it!
But if you used heap allocation on CreateMemberThread, though,
and deleted the object in the
static DWORD _ThreadFunc(ThreadData* pThis)
stub function, I suppose that everything would be fine

2) See point 1)

3) You have to call CloseHandle() after the slave thread has finished
working.
A typical call sequence is:
HANDLE h=CreateThread (or CreateMemberThread)
...
...
WaitForSingleObject(h,INFINITE);
CloseHandle(h);
Remember that thread should never be stopped (can they?) they
should be gently requested to commit suicide.

4) It is definitely possible! You should put the second parameter in
ThreadData, change the TFunc declaration, and voilà...
Should you have any problem, let me know...

Good luck.
And... you actually made me happy using this... snippet of code
Luca


GeneralDebug build fine, Release build crashes Pin
Lee Hamel12-Apr-05 7:01
memberLee Hamel12-Apr-05 7:01 
GeneralRe: Debug build fine, Release build crashes Pin
Lee Hamel13-Apr-05 13:01
memberLee Hamel13-Apr-05 13:01 
Generalgeneral static function template Pin
tuxyboy15-Nov-04 4:08
membertuxyboy15-Nov-04 4:08 
GeneralRe: general static function template Pin
Luca Piccarreta17-Dec-04 0:31
memberLuca Piccarreta17-Dec-04 0:31 
GeneralRe: general static function template Pin
tuxyboy17-Dec-04 1:01
membertuxyboy17-Dec-04 1:01 
GeneralNot XP after all Pin
Mike Osbahr6-Jun-02 9:26
memberMike Osbahr6-Jun-02 9:26 
QuestionUsing this method with Windows XP? Pin
Mike Osbahr31-May-02 11:08
memberMike Osbahr31-May-02 11:08 
AnswerRe: Using this method with Windows XP? Pin
Mike Osbahr4-Jun-02 12:05
memberMike Osbahr4-Jun-02 12:05 
GeneralWell Done! Pin
Anonymous14-May-02 1:22
memberAnonymous14-May-02 1:22 
GeneralAnother similar class Pin
Anatoly Ivasyuk2-May-02 9:14
memberAnatoly Ivasyuk2-May-02 9:14 
GeneralNOT FREEWARE Pin
Mr Angry4-Jun-02 6:16
memberMr Angry4-Jun-02 6:16 
GeneralSomething similar Pin
Todd Smith2-May-02 4:50
memberTodd Smith2-May-02 4:50 

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
Web03 | 2.8.150520.1 | Last Updated 2 May 2002
Article Copyright 2002 by Luca Piccarreta
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid