干净地退出 class 的 Boost 线程成员

Cleanly exit Boost thread member of class

我有一个 class 有一个 boost::thread 成员变量。我在该线程中有一个私有成员函数 运行(请参见下面的代码)。

class Human
{
  public:
    Human()
        : m_thinkThread(&Human::think, this)
    { }

    ~Human()
    {
        m_thinkThread.interrupt();
        m_thinkThread.join();
    }

  private:
    void think()
    {
        // do some thinking...
    }

    boost::thread m_thinkThread;
};
  1. 我是否需要 interruptjoin 调用以及自定义析构函数?或者默认的析构函数会负责干净地退出吗?如果我只需要默认析构函数,那么它“在幕后”做了什么以确保线程干净地退出?
  2. 如果我这样做,需要 interruptjoin 调用,那么我当前的设置有一个错误,因为 join() 可以 throw,这将是一个未捕获的析构函数中的异常。我将如何处理这种情况?

谢谢

Do I need the interrupt and join calls and therefore the custom destructor? Or will the default destructor take care of exiting cleanly? If the default destructor is all I need, then what does it do "under the hood" to ensure the thread is exited cleanly?

是的。在较新的标准版本中有 std::jthread,即 auto-join。

If I do however, need the interrupt and join calls, then my current setup has a bug because join() can throw, which will be an uncaught exception in a destructor. How would I handle this case?

如果我没记错的话,还有一个 join_nothrow 操作。如果我记得一个实现细节,请考虑使用线程保护器。

这似乎是在 Anthony Williams 的 "Concurrency In Action" (chapter 2.1.3) 之后添加到 Boost Thread 中的,后者似乎从未收到过文档。

struct Human
{
    Human() : m_thinkThread(&Human::think, this) {}

  private:
    void think() const;

    boost::thread m_thinkThread;
    boost::thread_guard<boost::interrupt_and_join_if_joinable> m_guard{m_thinkThread};
};

Live On Coliru

void Human::think() const {
    while (true) {
        boost::this_thread::sleep_for(boost::chrono::milliseconds(1500));
        std::cout << "Thinking..." << std::endl;
    }
}

int main() {
    Human plight;
    boost::this_thread::sleep_for(boost::chrono::seconds(10));
}

版画

Thinking...
Thinking...
Thinking...
Thinking...
Thinking...
Thinking...

然后在 10 秒后完全关闭。

注意事项

有一些版本的 boost 在嵌套可中断线程的情况下使用 thread-guards 会出现未处理的异常:请参阅 https://github.com/boostorg/thread/issues/366