Using class member function as a thread function 
Author Message
 Using class member function as a thread function

I'm trying to find whether or not there is any way to use a
member function of a class as a thread start function.

My ultimate goal is to have a templated class which internally
calls CreateThread() inside one member function, using another
member function as the thread start routine.

I can't seem to get this to work, and even the simple case
below of a basic class does not compile.  It has a member
function called threadFunc() and another member function
called runThread() which tries to do a CreateThread() using
threadFunc().  This does not compile.  
I also tried instantiating the class and calling CreateThread()
from main() using the class's threadFunc() as the thread
start function and that does not work either.

The code is included below.  If anyone has any ideas on how
to make this work, or proof that it can never work, I'd love
to hear from you.

In the meantime, I've had to write several hard coded routines
to do the CreateThread() calls which take pointers to the
various instances of the templated classes, which makes for
lots of redundant code, and ruins the whole concept of using
templated classes in the first place...

thanks ,
jet

John E. Turi
Senior Consultant
Edgewater Technology, Inc.

Tel: 781-224-9061
Fax: 781-246-5903
http://www.*-*-*.com/

test.cpp:
----------------------------------------------------------------------------
---------------

#include <afx.h>

// global thread function, WORKS OK
DWORD WINAPI gthreadFunc(LPVOID lpVoid) { return 0; }

class CTest
{
public:
        DWORD id;

        DWORD WINAPI    threadFunc(LPVOID lpVoid) { return 0; }
        HANDLE                  runThread();
        HANDLE                  rungThread();

Quote:
};

HANDLE CTest::runThread()
{
        // member thread function does not work.
        // following line generates the compiler error
        // error C2664: 'CreateThread' : cannot convert parameter 3 from 'unsigned
long (void *)' to 'unsigned long (__stdcall *)(void *)'
        HANDLE h = CreateThread(NULL, 0, threadFunc, NULL, 0, &id);
        return h;

Quote:
}

HANDLE CTest::rungThread()
{
        // global thread function works ok
        HANDLE h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
        return h;

Quote:
}

int main()
{
        DWORD id;
        CTest c;
        HANDLE h;

        h = c.runThread();
        CloseHandle (h);

        // following line generates the compiler error
        // error C2664: 'CreateThread' : cannot convert parameter 3 from 'unsigned
long (void *)' to 'unsigned long (__stdcall *)(void *)'
        h = CreateThread(NULL, 0, c.threadFunc, NULL, 0, &id);
        CloseHandle(h);

        // global thread function works ok
        h = c.rungThread();
        CloseHandle (h);

        h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
        CloseHandle(h);

        return 0;

Quote:
}



Sun, 07 May 2000 03:00:00 GMT  
 Using class member function as a thread function

Quote:

>I'm trying to find whether or not there is any way to use a
>member function of a class as a thread start function.

[snip]

Quote:
>HANDLE CTest::runThread()
>{
> // member thread function does not work.
> // following line generates the compiler error
> // error C2664: 'CreateThread' : cannot convert parameter 3 from 'unsigned
>long (void *)' to 'unsigned long (__stdcall *)(void *)'
> HANDLE h = CreateThread(NULL, 0, threadFunc, NULL, 0, &id);
> return h;
>}

>HANDLE CTest::rungThread()
>{
> // global thread function works ok
> HANDLE h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
> return h;
>}

Solution 1: declare the member function "static". VC++ treats a static
member function as a global function for pointer conversions and linking.

Solution 2: make it an extern C and declare the vtable pointer magic
yourself (yuk!), as explained in chapter 20 of Petzolds "Programming windows
95" from Microsoft Press.

--
Dirk Bellemans, native language Dutch
D dot Bellemans at company-benelux dot "Code for Belgium"
"Code for Belgium" = be
(standard disclaimer)



Sun, 07 May 2000 03:00:00 GMT  
 Using class member function as a thread function

The basic problem is that a non-static member function has an implicit
'this' pointer. The common way of solving this is to use a static member
function.

class CTest
{
public:
        ...
        static DWORD WINAPI threadFunc(LPVOID lpVoid);
        HANDLE runThread();
protected:
        virtual DWORD threadMemberFunc();
        ...

Quote:
};

runThread() creates a new thread with threadFunc passing it the 'this'
pointer as the LPVOID param. threadFunc() uses the passed 'this' pointer to
invoke threadMemberFunc().

One book on the subject is:
Multithreading Applications in Win32?: The Complete Guide to Threads
by: Jim Beveridge, Robert Wiener
Addison-Wesley ISBN: 0-201-44234-5

Chapter 9 which discuss the issue of using threads in C++ classes happens
to be available on the web:
<http://cseng.aw.com/bookdetail.qry?ISBN=0-201-44234-5&ptype=37>

Jonathan Dodds
Software Engineer
ASA



Quote:
> I'm trying to find whether or not there is any way to use a
> member function of a class as a thread start function.

> My ultimate goal is to have a templated class which internally
> calls CreateThread() inside one member function, using another
> member function as the thread start routine.

> I can't seem to get this to work, and even the simple case
> below of a basic class does not compile.  It has a member
> function called threadFunc() and another member function
> called runThread() which tries to do a CreateThread() using
> threadFunc().  This does not compile.  
> I also tried instantiating the class and calling CreateThread()
> from main() using the class's threadFunc() as the thread
> start function and that does not work either.

> The code is included below.  If anyone has any ideas on how
> to make this work, or proof that it can never work, I'd love
> to hear from you.

> In the meantime, I've had to write several hard coded routines
> to do the CreateThread() calls which take pointers to the
> various instances of the templated classes, which makes for
> lots of redundant code, and ruins the whole concept of using
> templated classes in the first place...

> thanks ,
> jet

> John E. Turi
> Senior Consultant
> Edgewater Technology, Inc.

> Tel: 781-224-9061
> Fax: 781-246-5903
> http://www.edgewater.com

> test.cpp:

----------------------------------------------------------------------------

- Show quoted text -

Quote:
> ---------------

> #include <afx.h>

> // global thread function, WORKS OK
> DWORD WINAPI gthreadFunc(LPVOID lpVoid) { return 0; }

> class CTest
> {
> public:
>    DWORD id;

>    DWORD WINAPI    threadFunc(LPVOID lpVoid) { return 0; }
>    HANDLE                  runThread();
>    HANDLE                  rungThread();
> };

> HANDLE CTest::runThread()
> {
>    // member thread function does not work.
>    // following line generates the compiler error
>    // error C2664: 'CreateThread' : cannot convert parameter 3 from
'unsigned
> long (void *)' to 'unsigned long (__stdcall *)(void *)'
>    HANDLE h = CreateThread(NULL, 0, threadFunc, NULL, 0, &id);
>    return h;
> }

> HANDLE CTest::rungThread()
> {
>    // global thread function works ok
>    HANDLE h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
>    return h;
> }

> int main()
> {
>    DWORD id;
>    CTest c;
>    HANDLE h;

>    h = c.runThread();
>    CloseHandle (h);

>    // following line generates the compiler error
>    // error C2664: 'CreateThread' : cannot convert parameter 3 from
'unsigned
> long (void *)' to 'unsigned long (__stdcall *)(void *)'
>    h = CreateThread(NULL, 0, c.threadFunc, NULL, 0, &id);
>    CloseHandle(h);

>    // global thread function works ok
>    h = c.rungThread();
>    CloseHandle (h);

>    h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
>    CloseHandle(h);

>    return 0;
> }



Sun, 07 May 2000 03:00:00 GMT  
 Using class member function as a thread function

John,

The problem is that you cannot pass a class member function as a thread
start function, due
to addressing limitations of C++.

What you can do is make the function static. However, you cannot access
other functions
or members of the class which are not static from a static function. What
you can do, however,
is pass the address of the calling class as the parameter to the thread.
You will need to dereference  
it but this will work and ensure data integrity.

SimonO



Sun, 07 May 2000 03:00:00 GMT  
 Using class member function as a thread function

Nevermind.  I do realize that the function must be static, which means
it loses context, but I can pass in the 'this' pointer to regain my
context.
I think this will work for templated classes too.  It's tantamount to what
I was doing with a hard coded function for each type of instantiated
template that I will use, but is much cleaner.

Thanks to everyone who already answered this question (my latest search
in DejaNews paid off)

jet



Quote:
> I'm trying to find whether or not there is any way to use a
> member function of a class as a thread start function.

> My ultimate goal is to have a templated class which internally
> calls CreateThread() inside one member function, using another
> member function as the thread start routine.

> I can't seem to get this to work, and even the simple case
> below of a basic class does not compile.  It has a member
> function called threadFunc() and another member function
> called runThread() which tries to do a CreateThread() using
> threadFunc().  This does not compile.  
> I also tried instantiating the class and calling CreateThread()
> from main() using the class's threadFunc() as the thread
> start function and that does not work either.

> The code is included below.  If anyone has any ideas on how
> to make this work, or proof that it can never work, I'd love
> to hear from you.

> In the meantime, I've had to write several hard coded routines
> to do the CreateThread() calls which take pointers to the
> various instances of the templated classes, which makes for
> lots of redundant code, and ruins the whole concept of using
> templated classes in the first place...

> thanks ,
> jet

> John E. Turi
> Senior Consultant
> Edgewater Technology, Inc.

> Tel: 781-224-9061
> Fax: 781-246-5903
> http://www.edgewater.com

> test.cpp:

----------------------------------------------------------------------------

- Show quoted text -

Quote:
> ---------------

> #include <afx.h>

> // global thread function, WORKS OK
> DWORD WINAPI gthreadFunc(LPVOID lpVoid) { return 0; }

> class CTest
> {
> public:
>    DWORD id;

>    DWORD WINAPI    threadFunc(LPVOID lpVoid) { return 0; }
>    HANDLE                  runThread();
>    HANDLE                  rungThread();
> };

> HANDLE CTest::runThread()
> {
>    // member thread function does not work.
>    // following line generates the compiler error
>    // error C2664: 'CreateThread' : cannot convert parameter 3 from
'unsigned
> long (void *)' to 'unsigned long (__stdcall *)(void *)'
>    HANDLE h = CreateThread(NULL, 0, threadFunc, NULL, 0, &id);
>    return h;
> }

> HANDLE CTest::rungThread()
> {
>    // global thread function works ok
>    HANDLE h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
>    return h;
> }

> int main()
> {
>    DWORD id;
>    CTest c;
>    HANDLE h;

>    h = c.runThread();
>    CloseHandle (h);

>    // following line generates the compiler error
>    // error C2664: 'CreateThread' : cannot convert parameter 3 from
'unsigned
> long (void *)' to 'unsigned long (__stdcall *)(void *)'
>    h = CreateThread(NULL, 0, c.threadFunc, NULL, 0, &id);
>    CloseHandle(h);

>    // global thread function works ok
>    h = c.rungThread();
>    CloseHandle (h);

>    h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
>    CloseHandle(h);

>    return 0;
> }



Sun, 07 May 2000 03:00:00 GMT  
 Using class member function as a thread function

Quote:

> Nevermind.  I do realize that the function must be static, which means
> it loses context, but I can pass in the 'this' pointer to regain my
> context.
> I think this will work for templated classes too.  It's tantamount to what
> I was doing with a hard coded function for each type of instantiated
> template that I will use, but is much cleaner.

> Thanks to everyone who already answered this question (my latest search
> in DejaNews paid off)

> jet



> > I'm trying to find whether or not there is any way to use a
> > member function of a class as a thread start function.

> > My ultimate goal is to have a templated class which internally
> > calls CreateThread() inside one member function, using another
> > member function as the thread start routine.

> > I can't seem to get this to work, and even the simple case
> > below of a basic class does not compile.  It has a member
> > function called threadFunc() and another member function
> > called runThread() which tries to do a CreateThread() using
> > threadFunc().  This does not compile.
> > I also tried instantiating the class and calling CreateThread()
> > from main() using the class's threadFunc() as the thread
> > start function and that does not work either.

> > The code is included below.  If anyone has any ideas on how
> > to make this work, or proof that it can never work, I'd love
> > to hear from you.

> > In the meantime, I've had to write several hard coded routines
> > to do the CreateThread() calls which take pointers to the
> > various instances of the templated classes, which makes for
> > lots of redundant code, and ruins the whole concept of using
> > templated classes in the first place...

> > thanks ,
> > jet

> > John E. Turi
> > Senior Consultant
> > Edgewater Technology, Inc.

> > Tel: 781-224-9061
> > Fax: 781-246-5903
> > http://www.edgewater.com

> > test.cpp:

> ----------------------------------------------------------------------------

> > ---------------

> > #include <afx.h>

> > // global thread function, WORKS OK
> > DWORD WINAPI gthreadFunc(LPVOID lpVoid) { return 0; }

> > class CTest
> > {
> > public:
> >       DWORD id;

> >       DWORD WINAPI    threadFunc(LPVOID lpVoid) { return 0; }
> >       HANDLE                  runThread();
> >       HANDLE                  rungThread();
> > };

> > HANDLE CTest::runThread()
> > {
> >       // member thread function does not work.
> >       // following line generates the compiler error
> >       // error C2664: 'CreateThread' : cannot convert parameter 3 from
> 'unsigned
> > long (void *)' to 'unsigned long (__stdcall *)(void *)'
> >       HANDLE h = CreateThread(NULL, 0, threadFunc, NULL, 0, &id);
> >       return h;
> > }

> > HANDLE CTest::rungThread()
> > {
> >       // global thread function works ok
> >       HANDLE h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
> >       return h;
> > }

> > int main()
> > {
> >       DWORD id;
> >       CTest c;
> >       HANDLE h;

> >       h = c.runThread();
> >       CloseHandle (h);

> >       // following line generates the compiler error
> >       // error C2664: 'CreateThread' : cannot convert parameter 3 from
> 'unsigned
> > long (void *)' to 'unsigned long (__stdcall *)(void *)'
> >       h = CreateThread(NULL, 0, c.threadFunc, NULL, 0, &id);
> >       CloseHandle(h);

> >       // global thread function works ok
> >       h = c.rungThread();
> >       CloseHandle (h);

> >       h = CreateThread(NULL, 0, gthreadFunc, NULL, 0, &id);
> >       CloseHandle(h);

> >       return 0;
> > }

If you intend to pass this to thread function, make sure the
object resides on the heap.


Mon, 08 May 2000 03:00:00 GMT  
 Using class member function as a thread function

You can try this trick:
 union {
          DWORD WINAPI (* sproc)(LPVOID);
          DWORD WINAPI (YourClass::* mproc)();
   };
Then launch the thread from within your class object:
   CreateThread(NULL, 0, sproc, this, 0, &dwThread);
What you are doing here is faking a member class pointer and passing 'this'
as the argument to the thread routine. This works fine.

Gabriel



Wed, 10 May 2000 03:00:00 GMT  
 
 [ 7 post ] 

 Relevant Pages 

1. Using class member function as a thread function

2. Starting a thread which is a member function of a class

3. Calling class member functions from a new thread

4. Starting up a thread of a member function of a C++ class

5. Is Thread Made of Member function of class ?

6. Launching multiple threads using member functions

7. Passing C++ Class Member Function to as a C Callback Function Parameter

8. class member function as callback function

9. How to use member function of a C++ class as a callback function

10. using another class's public member functions

11. Using member function templates in template class under VC++ 5.0

12. Using Non-Static Callback Functions as member Functions VC5.0

 

 
Powered by phpBB® Forum Software