在对象构造函数中初始化boost线程

Initialize boost thread in object constructor?

本文关键字:boost 线程 初始化 对象 构造函数      更新时间:2023-10-16

我想为boost线程编写一个包装器来专门化线程模型。我的run()函数将是使用boost::thread作为聚合线程对象的同一类的成员函数。考虑:

class Thread {
public:
  Thread(...) : m_thread(&Thread::run, this) {}
private:
  void run() { ... }
  boost::thread m_thread;
};

这是潜在的危险,因为this尚未完全构建。但是,如果我能保证run()使用的对象的所有成员都在boost线程初始化之前被初始化,这实际上可以被认为是安全的吗?

我能想到的保证安全的唯一解决方法是有一个子类来保证一个对象的完整构造,这个对象可以被Thread的构造函数使用:

class Thread {
public:
  Thread(...) : m_impl(...), m_thread(&ThreadImpl::run, &m_impl) {}
private:
  class ThreadImpl {
    ThreadImpl(...) { }
    void run() { ... }
  }
  ThreadImpl m_impl;
  boost::thread m_thread;
};

是否有一个通用的方法来做到这一点?对于这样一个微不足道的问题,ThreadImpl类似乎有很多开销。

声明成员的顺序(但不是初始化列表中的顺序,因此要小心)是构造的顺序。只要构造了所有成员就足以建立一致的状态,就可以声明线程成员的持续时间。

然而,如果你不想依赖它,你可以像这样在构造函数的末尾启动你的线程:
// Constructor
MyThread() {
  // Initialize everything else...
  boost::thread t(boost::bind(&MyThread::run, this));
  m_thread.swap(t);
}

关于使用this指针的安全性,标准在12.6.2中说:

注意:因为mem初始化式是在构造函数中,this指针可用于a的表达式列表mem-initializer指向被初始化的对象。

成员函数(包括虚成员函数,10.3)可以调用正在构建的对象。

您只需要避免访问尚未构造的内容。这可以包括在初始化所有基类之前调用成员函数:

class Derived : public Base {
public:
  Derived()
    : Base(foo())  // foo() undefined because base class not initialized
  {
  }
  int foo() { return 0; }
};