Passing Member Functions to Std::Thread

Start thread with member function

#include <thread>
#include <iostream>

class bar {
public:
void foo() {
std::cout << "hello from member function" << std::endl;
}
};

int main()
{
std::thread t(&bar::foo, bar());
t.join();
}

EDIT:
Accounting your edit, you have to do it like this:

  std::thread spawn() {
return std::thread(&blub::test, this);
}

UPDATE: I want to explain some more points, some of them have also been discussed in the comments.

The syntax described above is defined in terms of the INVOKE definition (§20.8.2.1):

Define INVOKE (f, t1, t2, ..., tN) as follows:

  • (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of
    type T or a reference to an object of a type derived from T;
  • ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous
    item;
  • t1.*f when N == 1 and f is a pointer to member data of a class T and t 1 is an object of type T or a

    reference to an object of type T or a reference to an object of a

    type derived from T;
  • (*t1).*f when N == 1 and f is a pointer to member data of a class T and t 1 is not one of the types described in the previous item;
  • f(t1, t2, ..., tN) in all other cases.

Another general fact which I want to point out is that by default the thread constructor will copy all arguments passed to it. The reason for this is that the arguments may need to outlive the calling thread, copying the arguments guarantees that. Instead, if you want to really pass a reference, you can use a std::reference_wrapper created by std::ref.

std::thread (foo, std::ref(arg1));

By doing this, you are promising that you will take care of guaranteeing that the arguments will still exist when the thread operates on them.


Note that all the things mentioned above can also be applied to std::async and std::bind.

In C++, How a std::thread can call a member function without creating an object?

how td_1 and td_2 called the member function operator() of class H without an object of class H?

td_1 and td_2 does create objects of type H. Those objects are temporaries. Next, those supplied function object(which are temporaries in this case) are moved/copied into the storage belonging to the newly created thread of execution and invoked from there.

You can confirm this by adding a default constructor and move constructor inside class H as shown below:

#include<iostream>
#include<thread>

class H {
public:
void operator()(){
printf("This is H(), I take no argument\n");
}

void operator()(int x){
printf("This is H(), I received %d \n",x);
}
//default constructor
H()
{
std::cout<<"default constructor called"<<std::endl;
}
//move constructor
H(H&&)
{
std::cout<<"move constructor called"<<std::endl;
}

};

int main(){

int param = 0xD;

std::thread td_1 = std::thread(H());
std::thread td_2 = std::thread(H(),param);

td_1.join();
td_2.join();


return 0;
}

The output of the above program is:

default constructor called
move constructor called
move constructor called
default constructor called
move constructor called
move constructor called
This is H(), I take no argument
This is H(), I received 13

Passing member functions to std::thread

class A
{
void FunctA();
void FunctB();

void run()
{
std::thread t(&A::FunctA, this);
std::thread r(&A::FunctB, this);
}
};

Pointers to member functions are different from pointers to functions, syntax of calling them is different, as well, and requires instance of class. You can just pass pointer to instance as second argument of std::thread constructor.

How to pass member function of class to thread?

why do we need to pass the reference to the object in this case?

A member function, apart from the "normal" arguments, also takes a pointer to the object (this). This one is implicitly provided when you call with the normal syntax:

x.apply_greeting("goodbye"); //secretly calls apply_greeting(&x,"goodbye"). (not valid code!)

So when you have a pointer to a member function which you have when you write &SayHello::greeting, you need to provide the pointer to the object as well. Otherwise - how would it know about its member variables?

Pointer to member functions are messy, you can circumvent by using a lambda:

std::thread t([&x](){ x.greeting("goodbye!"); } );

Passing class's member function to std::thread

You should specify the scope

&Timer::ThreadFunc

Starting a member function with arguments in a separate thread

Just add the arguments to the thread's constructor:

QString a("test");
std::thread thr(&MyClass::doStuff, this, a);

As your function accepts a reference you should use std::ref() like this:

MyClass::doStuff(QString& str) { /* ... */ }

// ...

QString a("test");
std::thread thr(&MyClass::doStuff, this, std::ref(a)); // wrap references

c++ passing std::function with custom object as argument in threading

Your problem is that you are capturing lastline and dict by-value and then passing them to the func which expect non-const references. You probably need to capture like this instead:

std::thread([func, interval, filename, &lastline, &dict] {
...
});

However you should be especially careful when capturing by-reference to make sure that those object are still alive when they are used in lambda, especially given that you are calling it in a separate thread. This also creates a possibility of a data race, so if you are going to access lastline and dict from several threads you need to make sure to use proper synchronization mechanisms such as std::mutex.

Passing any class member function with any number of arguments to a function outside the class

If you want to call a member function you'll need to pass the object to std::thread too:

void manager() {
//...
runFunctionInThread(f1, this);
runFunctionInThread(f2, this, 2);
runFunctionInThread(f3, this, 3, 3);
}

Note:
I noticed that you detach your threads. You then need to manually make sure that they have ended before your program does or you are in for surprises at program exit if they are still running.

It's often easier to keep the running threads in a container (like a std::list<std::thread>) and join() them later. In C++20 you could even make it std::list<std::jthread> to have them automatically joined when the container is destroyed.



Related Topics



Leave a reply



Submit