Search code examples
c++boostboost-threaddetach

Interrupt a detached boost::thread


I have a class with a thread running like this :

class MyClass
{
    public:
        void Start();
        void Stop();
        void Run();
    private:
        boost::thread mThread;
        bool mThreadShouldRun;
}

void MyClass::Start()
{
    mThreadShouldRun = true;
    mThread = boost::thread(&MyClass::Run, this);
}

void MyClass::Stop()
{
    mThreadShouldRun = false;
    mThread.interrupt();
}

void MyClass::Run()
{
    while(mThreadShouldRun)
    {
        //DO Something
        try {
            boost::this_thread::sleep_for(boost::chrono::seconds(15));
        } catch(boost::thread_interrupted interrupt) {
            break;
        }
    }
}

This code is doing what i'm expecting : Launching a background thread and stopping it on demand.

But according to the answer of this question join() or detach() should always be called. join() is not what i need in my case , so i go for detach() :

void MyClass::Start()
{
    mThreadShouldRun = true;
    mThread = boost::thread(&MyClass::Run, this);
    mThread.detach();
}

The thread still running as expected but mThread become Not-a-Thread and i can no longer interrupt it in the Stop() method because mThread no long reference the thread after the call to detach().

Should i really call detach() ? And if yes how to interrupt() the detached thread ?


Solution

  • Just interrupt the thread and then wait for it to return:

    #include <mutex>
    class MyClass
    {
        public:
            void Start();
            void Stop();
            void Run();
        private:
            boost::thread mThread;
            bool          mThreadShouldRun;
    }
    
    void MyClass::Start()
    {
        mThreadShouldRun = true; 
        mThread = boost::thread(&MyClass::Run, this);
    }
    
    void MyClass::Stop()
    {
        mThreadShouldRun = false;// dont really needed anymore but may be ok
        mThread.interrupt();
        mThread.join();
    }
    
    void MyClass::Run()
    {
        while(mThreadShouldRun)
        {
            //DO Something
            try {
                boost::this_thread::sleep_for(boost::chrono::seconds(15));
            } catch(boost::thread_interrupted interrupt) {
                break;
            }
        }
    }