Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

run threads of class member function in c++

As the title says. The following is my code skeleton.

class CLASS
{
public:
    void A();
private:
    DWORD WINAPI B(LPVOID);
};

void CLASS::A()
{
    DWORD (WINAPI CLASS::*thread)(LPVOID) = &CLASS::B;
    ...
    CreateThread(NULL, 0, thread, &arg, 0, NULL);
    ...
}

the function B needs CLASS's member variables.
But I've got an error code when I compiled this.
It's " can't convert argument 3 from 'DWORD (__stdcall CLASS::* )(LPVOID)' to 'LPTHREAD_START_ROUTINE' " or something like that.
I don't know if it is the same in the english environment.

can anybody help please?

like image 360
superscalar Avatar asked Jan 12 '11 08:01

superscalar


People also ask

How will you launch a thread using function pointer and function object?

To start a thread we simply need to create a new thread object and pass the executing code to be called (i.e, a callable object) into the constructor of the object. Once the object is created a new thread is launched which will execute the code specified in callable. After defining callable, pass it to the constructor.

How is class member function accessed?

Accessing data members and member functions: The data members and member functions of class can be accessed using the dot('. ') operator with the object. For example if the name of object is obj and you want to access the member function with the name printName() then you will have to write obj. printName() .

What is a class member function?

A member function of a class is a function that has its definition or its prototype within the class definition like any other variable. It operates on any object of the class of which it is a member, and has access to all the members of a class for that object.


1 Answers

Seriously, use std::thread:

class CLASS
{
public:
    void A();
private:
    void B(your args go here);
};

void CLASS::A()
{
    std::thread t(&CLASS::B, this, your args go here);
    // when done
    t.join();
    // or
    t.detach();
}

Explanation

Your code doesn't compile because CreateThread is a C API, expecting a non-member C function as a callback. In order to call a non-static member function of a C++ class, the caller needs to know about this pointer and how to correctly use it. Since WinAPI clearly doesn't have this and doesn't expect a member function pointer, this cannot possibly work. Your compiler catches this and reports it as a type mismatch error.

This is where the lpParameter of CreateThread comes into play. It allows you to pass this through that parameter. However it doesn't change the fact that CreateThread doesn't know how to call C++ member functions. Therefore it's your responsibility to wrap it in a static function that will do the member function call:

class CLASS
{
public:
    void A();
private:
    DWORD B();
    static DWORD s_B(LPVOID);
};

DWORD CLASS::s_B(LPVOID that) {
    return ((CLASS*)that)->B();
}

void CLASS::A() {
    CreateThread(NULL, 0, s_B, this, 0, NULL);
}

This is what @Nawaz does in their answer, except in a slightly more general way.

Even though this approach works, it clearly has downsides:

  • It's verbose.
  • It's non portable.
  • You need to pass your original args through different means (e.g. through a member of your class).

std::thread already does all that for you.

like image 75
Yakov Galka Avatar answered Oct 01 '22 01:10

Yakov Galka