YotKay
YotKay

Reputation: 1207

Thread as member variable

I want to have a thread kept as member variable of a class. I want to start the thread inside 'start' method, and stop the thread inside 'stop' method. I also want to be sure that the thread joins, whether or not the 'stop' method is called.

I designed the following code, using shared_ptr with custom deleter used to both join the thread and delete the pointer to thread, but I am not 100% sure if it is fully correct.

Please comment on this. Is everything OK here? Or maybe there is a better approach how to do this (e.g. use unique_ptr or desing other RAII class)?

#include <thread>
#include <iostream>
#include <memory>
using namespace std::chrono_literals;

void fun() { std::cout << "inside thread\n"; std::this_thread::sleep_for(1s); }

class A
{
public:
    A() : pT(nullptr) {}

    void start()
    {
        std::cout << "starting...\n";
        pT.reset(new std::thread(fun), [](auto p) {
            if (p->joinable()) 
            { 
                std::cout << "joining thread\n";
                p->join(); 
            }
            std::cout << "deleting thread\n"; 
            delete p;
       });
    }

    void stop()
    {
        std::cout << "stopping...\n";
        pT.reset();
    }

private:
    std::shared_ptr<std::thread> pT;
};
int main()
{
    A a;
    a.start();
    std::this_thread::sleep_for(2s);
    a.stop();

    return 0;
}

The output is correct:

starting...
inside thread
stopping...
joining thread
deleting thread

Upvotes: 3

Views: 3878

Answers (1)

Jorge Omar Medra
Jorge Omar Medra

Reputation: 988

In my case i like to have the control of what are create and when it is destroyed. So, my proposal is:

You can add the thread pointer as a member of your class and check if it was finish as i show you in this example:

class A{

   std::thread *pThread = nullptr; \\ Thread Pointer
   //...
public:
   A();
   ~A();
   void start();
   void stop();
}

And used it as:

void start()
{
    if(pThread == nullptr) 
    {
       pThread = new thread(fun); //Create the thread and store its reference
    }
}

~A()
{
    if (pThread != nullptr)
    {
        if(pThread->joinable()) \\Wait until the thread has been finished
            pThread->join();
        delete pThread; \\IMPORTANT, release the memory. 
    }
}

In this sample i use the thread to synchronized the destruction of Class, it will not be destroyed until the thread has been finished.

Note: If you want to use a method of some class as the function which runs the thread, you can use std::bind.

Also you can use smart pointer as unique_ptr instead of std::thread, as i made in this sample. In this case the memory will be release when the class get to be destroyed, so be sure the thread is finished before delete this pointer o leave the context (Class).

Upvotes: 3

Related Questions