I am working on a project in which I am using threads. The threads are launched with std::async and I ran into some things with member variables in a class that I do not understand. In the code below there are four different implementations of the thread launching function "start_thread_n". The four different functions give somewhat different results when executed and the output I get when running them is shown in the comment before each of the functions. The difference between the functions is in the call std::async(std::launch::async, &ThreadTest::run, &h) and specifically the param "h". What I would like to get is what start_thread_3 delivers (and _4). The difference in behaviour is what the variable m_a contains at different places in the execution of the code, as can be seen in the print outs to the screen (in the comments before each function).
Can you hint on why I get the different results? I run on Linux with C++14.
Many thanks
#include <future>
#include <thread>
#include <vector>
#include <signal.h>
sig_atomic_t g_stop(false);
std::vector<std::future<void>> my_futures;
std::future<void> g_thread;
class ThreadTest
{
public:
ThreadTest();
void run();
private:
unsigned m_a;
};
ThreadTest::ThreadTest()
{
m_a = 1;
std::cout << m_a << std::endl;
}
void ThreadTest::run()
{
std::cout << "Thread started" << std::endl;
while (not g_stop) {
std::cout << "." << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << std::endl;
std::cout << m_a << std::endl;
std::cout << "Thread stopped" << std::endl;
}
void start_thread_1();
void start_thread_2();
void start_thread_3();
ThreadTest start_thread_4();
void stop_threads();
int main()
{
start_thread_1();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
g_stop = true;
stop_threads();
}
/*
* > ./thread_test
* 1
* Thread started
* ..........
* 0
* Thread stopped
*/
void start_thread_1()
{
ThreadTest h;
g_thread = std::async(std::launch::async, &ThreadTest::run, &h);
my_futures.push_back(std::move(g_thread));
}
/*
* > ./thread_test
* Thread started
* ..........
* fish: “./thread_test” terminated by signal SIGSEGV (Address boundary error)
*/
void start_thread_2()
{
std::shared_ptr<ThreadTest> h;
g_thread = std::async(std::launch::async, &ThreadTest::run, h);
my_futures.push_back(std::move(g_thread));
}
/*
* > ./thread_test
* 1
* Thread started
* ..........
* 1
* Thread stopped
*/
void start_thread_3()
{
ThreadTest h;
g_thread = std::async(std::launch::async, &ThreadTest::run, h);
my_futures.push_back(std::move(g_thread));
}
/*
* > ./thread_test
* 1
* Thread started
* ..........
* 1
* Thread stopped
*/
ThreadTest start_thread_4()
{
ThreadTest h;
g_thread = std::async(std::launch::async, &ThreadTest::run, h);
my_futures.push_back(std::move(g_thread));
return h;
}
void stop_threads()
{
size_t m = my_futures.size();
for(size_t n = 0; n < m; n++) {
auto e = std::move(my_futures.back());
e.get();
my_futures.pop_back();
}
}```