Search code examples
c++multithreadingboostboost-thread

terminating a running boost thread


I currently have a boost thread as such

class foo
{
  private:
  boost::shared_ptr<boost::thread> t;
  public:
  foo()
  {
    t = boost::make_shared<boost::thread>(&foo::SomeMethod,this);
  }
  void SomeMethod()
  {
    while(true)
    {
       .... //Does some work
    boost::this_thread::sleep(boost::posix_time::milliseconds(5000)); //sleep for 5 seconds
    }
  }

  void stopThread()
  {
    //Elegant and instant way of stopping thread t
  }
}

I have read from this post that you have to define interruption points however I am not sure if I understand how that would fit in my scenario. I am looking for a safe elegant way that will ensure that thread t is terminated


Solution

  • You can't ever safely terminate a thread, you just need to tell it from the outside that it should stop. If you interrupt a thread, you don't know where you interrupted it and you could leave the system in an unknown state.

    Instead of looping forever, you can check a variable (make sure it's thread safe though!) inside the thread's loop to see if the thread should exit. What I do in work threads is I have them wait on a condition variable, and then when there's work they wake up and do work, but when they're awake they also check the "shutdown" flag to see if they should exit.

    A snippet of my code:

    //-----------------------------------------------------------------------------
    void Manager::ThreadMain() {
        unique_lock<mutex> lock( m_work_mutex, std::defer_lock );
        while( true ) {
            lock.lock();
            while( m_work_queue.empty() && !m_shutdown ) {
                m_work_signal.wait( lock );
            }
    
            if( !m_work_queue.empty() ) {
    
                // (process work...)
                continue;
            }
    
            // quit if no work left and shutdown flag set.
            if( m_shutdown ) return;
        }
    }
    

    You could maybe get away with something like:

    std::atomic<bool> stop_thread = false;
    
    void SomeMethod()
    {
      while( !stop_thread )
      {
        .... //Does some work
        boost::this_thread::sleep(boost::posix_time::milliseconds(5000)); //sleep for 5 seconds
      }
    }
    
    void stopThread()
    {
      stop_thread = true;
    
      // join thread (wait for it to stop.)
      t->join();
    }
    

    And let me tell you, sometimes it isn't easy to make something safely exit. A few weeks ago I had a big struggle with threaded console input. I ended up having to handle raw windows console events and translating them into keystrokes myself, just so I could simultaneously intercept my custom shutdown event.