2

I want to write a wrapper for boost thread to specialize a threading model. My run() function is going to be a member function of the same class that is using boost::thread as the aggregate thread object. Consider:

class Thread {
public:
  Thread(...) : m_thread(&Thread::run, this) {}

private:
  void run() { ... }
  boost::thread m_thread;
};

This is potentially dangerous because this is not yet fully constructed. However, if I can guarantee that all members of the object used by run() are initialized prior-to initialization of the boost thread, could this actually be considered safe?

The only workaround I can think of that guarantees safety is to have a subclass that guarantees full construction of an object that can be used by the constructor of 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;
};

Is there a common way to do this? The ThreadImpl class seems like a lot of overhead for such a trivial issue.

Community
  • 1
  • 1
jwalk
  • 1,120
  • 11
  • 27

1 Answers1

2

The order that members are declared (not the order in the initializer list, though, so be careful) is the order of construction. You should be fine if you declare the thread member last as long as having all members constructed is sufficient to establish a consistent state.

However, if you don't want to rely on that, you can start your thread at the end of the constructor with something like this:

// Constructor
MyThread() {
  // Initialize everything else...

  boost::thread t(boost::bind(&MyThread::run, this));
  m_thread.swap(t);
}

Regarding the safety of using the this pointer, the standard says in 12.6.2:

Note: because the mem-initializer are evaluated in the scope of the constructor, the this pointer can be used in the expression-list of a mem-initializer to refer to the object being initialized.

and

Member functions (including virtual member functions, 10.3) can be called for an object under construction.

You just have to avoid accessing what has not yet been constructed. That can include calling member functions before all base classes have been initialized:

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

  int foo() { return 0; }
};
rhashimoto
  • 15,650
  • 2
  • 52
  • 80
  • Is there any documentation providing rules for safety regarding usage of "this" pointer to an object that hasn't been fully constructed? One of the answers in the link I referenced to stated "if you ever accidentally call a function on this you invoke UB". But then my usage would be unsafe. – jwalk Apr 01 '13 at 23:04
  • Updated answer to discuss safety of partially constructed object. – rhashimoto Apr 02 '13 at 00:30
  • Although this gives a better understanding, I really wish there were better documentation on this aspect of partially constructed objects. It seems though the points you referred to are stated, they are not very well explained in the standard. – jwalk Apr 02 '13 at 05:19