Stefano
Stefano

Reputation: 4031

use std::thread within function method

This piece of code works as expected (it prints "procedure()")

#include <iostream>
#include <thread>

class myClass{
public:
    myClass(){};
    ~myClass(){};
    void run(){std::cout << "run()"<<std::endl;};
    void procedure(){std::cout << "procedure()"<<std::endl;};
};


int main(int argc, char *argv[]){
    myClass* c = new myClass();
    std::thread c_thread(&myClass::procedure,c);
    c_thread.join();
    return 0;
}

now i do not like the fact that the caller has to know that my class launches a thread! So i would prefere that launching the thread is hidden in my constructor on the run method. So i wrote the following code:

#include <iostream>
#include <thread>
class myClass{
public:
    myClass(){};
    ~myClass(){};
    void run(){
        std::cout << "run()"<<std::endl;
        std::thread c_thread(&myClass::procedure,this);     
    };
    void procedure(){std::cout << "procedure()"<<std::endl;};
};


int main(int argc, char *argv[]){
    myClass* c = new myClass();

    c->run();
    while(true){}

    return 0;
}

this ends up in the following error:

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
run()
[New Thread 0x7ffff6fdd700 (LWP 4485)]
terminate called without an active exception

Program received signal SIGABRT, Aborted.
0x00007ffff70135f7 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.1.x86_64 libgcc-4.8.5-4.el7.x86_64 libstdc++-4.8.5-4.el7.x86_64
(gdb) bt
#0  0x00007ffff70135f7 in raise () from /lib64/libc.so.6
#1  0x00007ffff7014ce8 in abort () from /lib64/libc.so.6
#2  0x00007ffff79179d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6
#3  0x00007ffff7915946 in ?? () from /lib64/libstdc++.so.6
#4  0x00007ffff7915973 in std::terminate() () from /lib64/libstdc++.so.6
#5  0x000000000040109d in std::thread::~thread (this=0x7fffffffdeb0, __in_chrg=<optimized out>) at /usr/include/c++/4.8.2/thread:143
#6  0x00000000004011e1 in myClass::run (this=0x606010) at test2.cpp:9
#7  0x0000000000400f65 in main (argc=1, argv=0x7fffffffe008) at test2.cpp:17
(gdb) q

anyone knows the reason?

Upvotes: 0

Views: 195

Answers (2)

NathanOliver
NathanOliver

Reputation: 180415

When you call c->run(); it executes

void run(){
    std::cout << "run()"<<std::endl;
    std::thread c_thread(&myClass::procedure,this);     
};

When the function ends c_thread is destroyed. Since you never called join() or detach() on it c_thread is still joinable and this causes the destructor to throws an exception. See std::thread::~thread()

You need to make c_thread a member of myClass and in the myClass destructor you either need to call join() or detach() on it. This will allow the thread object to be destroyed without throwing an exception. If you call join() the destructor will not end until myClass::procedure ends. If you call detach() then the destructor will complete immediately but the thread will keep running until the function ends.

Upvotes: 5

Alessandro Pezzato
Alessandro Pezzato

Reputation: 8802

c_thread go out of scope whwn run() ends, so the thread is destroyed, probably before procedure() has finished.

I guess you want the std::thread instance as a member of myClass, not as a local variable. In this case, the thread is destroyed only when c go out of scope. Anyway, a thread.join() in the destructor of myClass will wait until the thread has completed.

Upvotes: 0

Related Questions