简体   繁体   中英

Start thread within member function using std::thread & std::bind

I have few queries with respect to below code snapshot.

1) With respect to pthread_create(), assume Thread_1 creates Thread_2. To my understanding Thread_1 can exit without join, but still Thread_2 will keep running. Where as in below example without join() I am not able to run thread and I am seeing exceptions.

2) In few examples I am seeing thread creation without thread object as below. But when I do the same, code is terminated.

std::thread(&Task::executeThread, this);

I am compiling with below command.
g++ filename.cpp -std=c++11 -lpthread

But still it terminate with exception. Is this right way of creating thread or is there any different version of C++ (In my project already they are compiling but not sure about the version).

3) In few examples of my project code, I am seeing below way of creating thread. But I am not able to execute with below example.

std::thread( std::bind(&Task::executeThread, this) );

Below is my code snapshot.

#include <iostream>
#include <thread>

class Task
{
    public:
    void executeThread(void)
    {
        for(int i = 0; i < 5; i++)
        {
           std::cout << " :: " << i << std::endl;
        }
    }

    void startThread(void);
};

void Task::startThread(void)
{
    std::cout << "\nthis: " << this << std::endl;

#if 1
    std::thread th(&Task::executeThread, this);
    th.join(); // Without this join() or while(1) loop, thread will terminate
    //while(1);
#elif 0
    std::thread(&Task::executeThread, this);  // Thread creation without thread object
#else
    std::thread( std::bind(&Task::executeThread, this) );
    while(1);
#endif
}

int main()
{
    Task* taskPtr = new Task();
    std::cout << "\ntaskPtr: " << taskPtr << std::endl;

    taskPtr->startThread();

    delete taskPtr;
    return 0;
}

Thanks & Regards

Vishnu Beema

std::thread(&Task::executeThread, this); statement creates and destroys a thread object. The destructor of std::thread invokes std::terminate when the thread wasn't joined or detached (like in your statement).

There is no good reason to use std::bind in C++11 because lambdas are better in terms of space and speed.

When building multi-threaded code you need to specify -pthread option when both compiling and linking. Linker option -lpthread is both inadequate and unnecessary.

By design, you need to join all the threads you spawned, or detach them. See eg SO question on join/detach

See also cppreference, detach

Note also important caveats if main() exits while detached threads are still running

I also 100% agree with the comment in the other answer about preferring lambdas to bind.

Finally, do not fall for the temptation to do pthread_cancel on a thread in C++. See egpthread_cancel considered harmful

  1. In C++ objects have a lifetime. This is a bit different then dealing with handles in C. In C++ if you create an object on the stack in one scope it will be destroyed if you exit that scope. There are some exception to these rule like std::move , but as a rule of thumb you own the lifetime of an object.

  2. This ties into the same answer as above. When you called std::thread(&Task::executeThread, this); you were actually invoking the thread constructor. This is the start of the thread life and the object lifetime. Notice that you created this object on the stack. If you leave the scope {.. yourcode.. } the DTor will be called. Since you have done this before std::move , join or detatch then std::terminate() is called which is raising the exception.

  3. You can create a thread that way. If you look at the linked documentation for std::thread::thread (constructor) there is an example of an object foo being created the same way. What errors are you receiving?

Relevant Documentation:

a. std::thread::~thread()

b. std::thread::thread

c. Lifetime in C++

I personally would recommend understanding the lifetime of objects in a C++. In short all objects start their lifetime when their constructor is invoked. When they are killed (as in out of scope) their destructor is called. The compiler handles this for you so if you're coming from C its a new concept.

Thank you all for your inputs. I missed thread object as part of thread creation. Because of this though compiling, I am getting exceptions. Below is my updated code. All three scenarios are working fine.

#include <iostream>
#include <thread>

class Task
{
    public:
    void executeThread(std::string command)
    {
        for(int i = 0; i < 5; i++)
        {
            std::cout << command << " :: " << i << std::endl;
        }
    }

    void startThread(void);
    std::thread th2;
    std::thread th3;
};

void Task::startThread(void)
{
    std::cout << "\nthis: " << this << std::endl;

    #if 0
        std::thread th1(&Task::executeThread, this, "Thread1");
        th1.join(); // Without join(), thread will terminate
    #elif 0
        th2 = std::thread(&Task::executeThread, this, "Thread2");
        th2.join();
    #else
        th3 = std::thread( std::bind(&Task::executeThread, this, "Thread3") );
        th3.join();
    #endif
}

int main()
{
    Task* taskPtr = new Task();
    std::cout << "\ntaskPtr: " << taskPtr << std::endl;

    taskPtr->startThread();

    delete taskPtr;
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM