Is there a safe way to have a std::thread as a member of a class? Is there a safe way to have a std::thread as a member of a class? multithreading multithreading

Is there a safe way to have a std::thread as a member of a class?


You can use a thread in combination with move semantics:

class MyClass final{private:    std::thread mythread;    void _ThreadMain();public:    MyClass()        : mythread{} // default constructor    {        // move assignment        mythread = std::thread{&MyClass::_ThreadMain, this};    }};

The move assignment operator is documented on the following page. In particular, it is noexcept and no new thread is created.


There is no better way, in general, than having a separate Start function.

Suppose MyClass is a base class for some future (unknown) class Derived. If the thread is started while (or before) the MyClass constructor runs, it always risks calling the "wrong" implementation of some virtual function overridden by Derived.

The only way to avoid this is to have the thread wait until after Derived is fully constructed, and the only way to do that is to call some other function after the Derived constructor completes to tell the thread to "go"... Which means you must have some kind of separately-invoked Go function.

You might as well just have a separately-invoked Start function instead and forego the complexity of waiting.

[Update]

Note that, for complex classes, "Two-Phase Construction" is an idiom recommended by some. Starting the thread would fit seamlessly into the "initialization" phase.


Consider separating the task from the thread management and launching.

One class creates a runner and any synchronization primitives snd the like, The other handles launching it. This allows construction of the runnable to fail before threading starts.

It also means the runnable is fully constructed prior to it being run.

Now a first pass would have the runner be a std::thread, but some stuff helping with abort and cleanup and continuations can be useful.

The run object could be a simple callable, or could add extra supportmfor the runnable to interact with it.