I am writing a OO wrapper for std::thread. A simplified version of the code is shown below. The issue with this class is that if it is destroyed immediately it can throw an error because doWork is called from the thread at the same time as the class is being destroyed (pure virtual method called).
The test case is shown at the bottom.
How can I make this class more safe? A more complicated example would be even worse if MyConThread had member variables that were being used from MyConThread::doWork.
I realize that I have a similar issue on startup where doWork can be called before the derived class is constructed.
#include <thread>
class ConThread {
public:
ConThread ()
:t_ (doWorkInternal, this)
{}
~ConThread ()
{
if (t_.joinable()) {
t_.join();//avoid a crash because std::thread will terminate the app if the thread is still running in it's destructor
}
}
std::thread& get () {return t_;};
protected:
virtual void doWork ()=0;
private:
static void doWorkInternal (ConThread* t)
{
try {
t->doWork ();
} catch (...)
{};
}
std::thread t_;
};
The issue I am running into is with the test case below:
class MyConThread: public ConThread
{
public:
long i=0;
protected:
void doWork () override
{
for (long j=0; j<1000000_ && requestedToTerminate_==false; j++)
{
++i;
}
}
};
TEST(MyConThreadTest, TestThatCanBeDestroyed)
{
MyConThread mct (); //<== crashes when being destroyed because thread calls t->doWork ()
}