Best way to start a thread as a member of a C++ class?
I usually use a static member function of the class, and use a pointer to the class as the void * parameter. That function can then either perform thread processing, or call another non-static member function with the class reference. That function can then reference all class members without awkward syntax.
Is there a safe way to have a std::thread as a member of a class?
There is no better way, in general, than having a separate Start
function.
Suppose MyClass
is a base class for some future (unknown) class Derived
. If the thread is started while (or before) the MyClass
constructor runs, it always risks calling the "wrong" implementation of some virtual function overridden by Derived
.
The only way to avoid this is to have the thread wait until after Derived
is fully constructed, and the only way to do that is to call some other function after the Derived
constructor completes to tell the thread to "go"... Which means you must have some kind of separately-invoked Go
function.
You might as well just have a separately-invoked Start
function instead and forego the complexity of waiting.
[Update]
Note that, for complex classes, "Two-Phase Construction" is an idiom recommended by some. Starting the thread would fit seamlessly into the "initialization" phase.
How to use a thread member variable of a class c++
Assuming that the creation of this thread object will happen in
startTask(), what is the scope of this thread object? Does it live
till the Example class object gets destroyed like normal member
variables? Or its scope is the scope of that particular
method(startTask())?
The scope of the thread object is at the level of the Example object. But, the thread will not start running until you call startTask(). Do no confuse having a thread instance and having a running thread instance.
Where should I call .join() on the spawned thread if I want this
thread to live as long as the Example object? In the destructor of
Example class?
Yes, you can call it at the destructor and it is safe.
Some
material(https://thispointer.com/c11-how-to-use-stdthread-as-a-member-variable-in-class/)
online says I should create move-only class if I need to use
std::thread as member variable, why is that?
Because the std::thread is not copyable, but it is movable. So your example class cannot be copyable as well.
Is it good to have a thread object as a member variable? Reasons?
Yes, why not. I see no problem with that. You create one class with the responsibility of managing a resource, that is a 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
.
Thread as member variable of class
Since std::thread are movable but not copyable, you can do like so:
class Test {
public:
std::thread t;
Test(std::thread&& rt) : t(std::move(rt)) {}
};
int main()
{
std::vector<Test> tests;
{
std::thread t([] {
std::cout << 1;
});
tests.push_back(Test(std::move(t)));
}
for (Test& mytest : tests)
{
mytest.t.join();
}
}
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
Create thread inside class with function from same class
foo_func
is a (non-static
) member function, and it needs an instance of foo
on which to operate. This instance must be provided to the thread constructor. If you refer to the std::thread::thread reference page it explains what code is executed in the new thread. The relevant point is that which refers to f
being a pointer to member function:
- If
f
is pointer to a member function of classT
, then it is called. The return value is ignored. Effectively, the following code is executed:
(t1.*f)(t2, ..., tN)
if the type oft1
is eitherT
, reference toT
or reference to type derived fromT
.((*t1).*f)(t2, ..., tN)
otherwise.
so it is clear that the instance is required.
Change to:
for(...) some_threads.push_back(std::thread(&foo::foo_func, this));
Simple example:
#include <iostream>
#include <thread>
#include <vector>
class foo
{
public:
void make_foo_func_threads()
{
for (int i = 0; i < 5; ++i)
some_threads.push_back(std::thread(&foo::foo_func, this));
for (auto& t: some_threads) t.join();
}
private:
void foo_func() { std::cout << "Hello\n"; }
std::vector<std::thread> some_threads;
};
int main()
{
foo f;
f.make_foo_func_threads();
}
Related Topics
G++ Error:/Usr/Lib/Rpm/Redhat/Redhat-Hardened-Cc1: No Such File or Directory
Integrate Type Name in Static_Assert Output
How to Use C Source Files in a C++ Project
Getter and Setter, Pointers or References, and Good Syntax to Use in C++
Llvm Get Constant Integer Back from Value*
Is Std::Vector<T> a 'User-Defined Type'
Compile Time Template Instantiation Check
Race-Condition in Pthread_Once()
Const Pointer Assign to a Pointer
C++11 Constexpr Flatten List of Std::Array into Array
Is It Always the Case That Sizeof(T) >= Alignof(T) for All Object Types T
Using Zeromq Together with Boost::Asio
Real-Time Pitch Detection Using Fft
How to Use Cmake_Export_Compile_Commands