I am trying to implement polymorphism, where the derived class implements a method that is run in a separate thread:
#include <memory>
#include <thread>
#include <chrono>
class Base
{
public:
std::thread m_jobThread;
~Base() { if (m_jobThread.joinable()) m_jobThread.join(); }
virtual void doJob() = 0;
void doJobInBackground() { m_jobThread = std::thread(&Base::doJob, this); }
};
class Drived : public Base
{
public:
Drived() = default;
virtual void doJob() final { std::this_thread::sleep_for(std::chrono::seconds(1)); }
};
int main(int argc, char const *argv[])
{
Drived d;
d.doJobInBackground();
return 0;
}
How do I achieve this safely without getting a pure virtual method called exception?
I want to be able to destroy the derived objects, potentially while the job is happening and have the destructor of the base class deal with managing the thread. but since the vtable of the derived class gets destroyed before the destructor of the base class is run, I get a pure virtual method exception.
I thought of adding a stop method in the destructor of the derived class that makes sure the thread is joined. But that defeats the purpose of my polymorphic design, where I want the derived class to ONLY be responsible for defining the doJob method and not for directly or indirectly handling the resources of the base class such as the thread...
Any ideas if this is possible? Do I need to change my design?
As pointed out by Sam Varshavchik in his comment above, the reason why you trigger a pure virtual function call here is that the destructor of d is run before your second thread has even started executing. You only synchronize in the Base destructor. By the time the Base destructor runs, however, the Derived part of the object has already been destroyed. The dynamic type of the object at this point is just Base, because that's all that's still alive and, thus, the virtual function call dispatches to the base version, which is pure. Strictly speaking, you actually have undefined behavior here because the object being destroyed in one thread while another may be calling a method on it violates [basic.life]/7.2. The lifetime of your object ends when the destructor call starts [basic.life]/1.3, the method call in the second thread does not inter-thread happen before the destructor call in the first thread…
Just
#include <thread>
#include <chrono>
class Base
{
std::thread m_jobThread;
public:
void join() { if (m_jobThread.joinable()) m_jobThread.join(); }
virtual void doJob() = 0;
void doJobInBackground() { join(); m_jobThread = std::thread(&Base::doJob, this); }
};
class Derived : public Base
{
public:
virtual void doJob() final { std::this_thread::sleep_for(std::chrono::seconds(1)); }
};
int main(int argc, char const* argv[])
{
Derived d;
d.doJobInBackground();
d.join();
return 0;
}
works fine…
Related
So I have this class kind of class:
class Base
{
public:
Base() { task_ = std::thread(&DexHandlerBase::running_task, this); }
virtual ~Base(){ /*send signal to task_ to stop then */ task_.join();}
protected:
virtual int some_check(int) = 0;
private:
void running_task() { some_check(123); }
std::thread task_;
}
class Derived
{
protected:
int some_check(int) override; //here I use my_data
private:
std::string my_data = "test";
}
An exception spawn up sometimes when the program close.
My guess is that the default Destructor of derived is called, Derived default destructor run and then my_data get destructed. Then the Base class destructor is called and it signal the thread that its going to be destroyed and wait. But the thread is running a task that is a call to a virtual function , this function use my_data that no longer exist.
So there is a dependency from the Base class to the Derived class data. I dont want to move data up, and the function has to be virtual. Shall I override the destructor in each derived class so it closes the thread or is there a better design for this ?
I had similar problems when trying to run async operations in Base classes. Most likely after the destructor of Derived is called, the task_ tries to call virtual int some_check(int) = 0; which is pure virtual, so it is illegal, because Derived doesn't exist anymore. You should make sure that your Derrived::~Derived() stops the asyc operation by /*send signal to task_ to stop then */. E.g. implement protected Base::stopTask() and call it in Derived DTor.
I have a problem with virtual methods in C++ on a multithreading context (Linux).
This next example points out my problem:
class Base {
};
class Concrete1: public Base { //define pure virtual function
virtual void func() = 0;
};
class Concrete2: public Concrete1 { //override of virtual func
void func() {}
void run(){
//....
pthread_create(&handle, NULL, Concrete2::thread, static_cast<void*>(this));
}
static void* thread(void arg*){
Concrete2 *ptr = static_cast<Concrete2*>(arg);
//Concrete1 *ptr = static_cast<Concrete2*>(arg); // same error
while(1){
//....
ptr->func()
}
}
};
int main(){
Concrete2 obj;
obj.run();
pthread_exit(NULL);
return 0;
}
When the line ptr->func() is executed, the following error appears:
pure virtual method called terminate called without an active exception
Can someone tell me why the pure virtual method is being called instead of the overrided method?
Concrete2 is created on the stack and is destroyed as soon as run is called.
The spawned thread does not keep obj alive.
Your thread function is trying to dereference a destroyed object, aka a dangling pointer, which constitutes undefined behavior.
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
class Base {
protected:
pthread_t receiverThreadID;
Base() {
pthread_create(&receiverThreadID,NULL,threadFunction,this);
}
~Base() {
}
virtual void handleEvent() = 0;
static void* threadFunction(void* arg) {
while(true) {
// This threads receives UDP via recvfrom(). The messages can come in randomly. I use sleep() to simulate a blocking wait
sleep(1);
((Base*)arg)->handleEvent();
}
return 0;
}
};
class Derived : public Base {
virtual void handleEvent() {
// Do something
printf("hello\n");
}
public:
Derived() {}
~Derived() {}
};
int main() {
Derived derived;
sleep(10);
}
You are not supposed to call a pure virtual function from the constructor of a class, but is it ok to create a thread in the constructor, that in turn calls a pure virtual function? Is there any risk for a race condition? I did not get any runtime errors with the code above.
If it is not ok to code like I've done, how should you solve it?
This can blow up if the threadFunction() calls handleEvent() before the constructor of Derived is done.
Why not place the pthread_create call in another function - say, start() - and call it once the object is constructed?
class Base {
protected:
pthread_t receiverThreadID;
Base() {}
~Base() {}
void start() {
pthread_create(&receiverThreadID,NULL,threadFunction,this);
}
...
};
If you call it in a thread or directly doesn't matter, you should not call the pure virtual function before Derived is fully constructed - and this happens after the construction of Base.
Your sleep is what makes this code running, but not safe.
If you want a safe version, i see 2 options:
Use mutexes or similar mechanisms to prevent the thread from calling the function before the constructor is done.
(And thats probably the better option): Start your thread in a function called after the constructor. You might want to utilize a factory-function here to make sure it is always called.
It is wrong to call virtual function when the constructor is not completely executed.
As other suggested, please make sure to have another function that used this virtual function. And call this function once object is created.
eg.
class Base{
static void *create_thread(void * arg){
pthread_create(&receiverThreadID,NULL,threadFunction,this);
}
};
// client call something like this.
Base * b = new Derived();
b->create_thread();
Hope this should solve the problem.
I have a class hierarchy which inherits QObject.
I need to perform some operations after construction (when the object is fully constructed) and before destruction (when the object is still complete).
The construction part is no problem, since I can control the construction of an object, making private its constructor and just making public the creator function which already can perform all the required operations.
The problem comes with the destructor. I have done more or less the same: hiding the destructor and providing a destroyer function which performs all the operations and then destroys the object.
Here is where the problem begins:my class hierarchy is used as part of the QJSEngine scripting module, which takes ownership of all the objects, and when it is time, it destroys them using the QObject's destructor, thus, bypassing my destroyer function. It is of no help declaring my destructors private, since the QJSEngine can always execute the QObject's destructor (and by the way, also can any piece of code which casts my pointers to QObject).
I require to perform this operations before calling the destructor, since I use some virtual functions, so I need to execute this BEFORE beginning the destruction process, so the virtual functions calls will not fail.
Is there a way to achieve this?
I attach a basic code snipped showing my problem:
class IBase: public QObject {
public:
template<typename T>
static IBase * create() {
IBase * obj=new T;
obj->afterConstruction();
return obj;
}
void destroy() {
this->beforeDestruction();
delete this;
}
protected:
IBase(): fBeforeDestruction(false){}
virtual ~IBase(){
//Try to perform operations, but it is too late....
if (!fBeforeDestruction)
doBeforeDestruction();
}
virtual void doAfterConstruction(){}
virtual void doBeforeDestruction(){}
private:
bool fBeforeDestruction;
void afterConstruction() {
doAfterConstruction();
}
void beforeDestruction(){
fBeforeDestruction=true;
doBeforeDestruction();
}
};
class TSubclass: public IBase {
protected:
TSubclass(){}
virtual ~TSubclass(){}
virtual void doAfterConstruction(){
qDebug()<<"AfterConstruction";
}
virtual void doBeforeDestruction(){
qDebug()<<"BeforeDestruction";
}
private:
friend class IBase;
};
int main(int argc, char *argv[])
{
//QObject *obj=new TSubclass() //Compile time error! Nice!
QObject *obj=IBase::create<TSubclass>();
delete obj;//Wrong! BeforeDestruction is NEVER shown!!! <---- How to change this behaviour?
IBase * obj2=IBase::create<TSubclass>();
//delete obj2; //Compile time error! Nice!
obj2->destroy(); //Nice!
}
EDIT:
After some comments, I have to add to the question that I want to do several operations before the destructor for two reasons:
Virtual calls: The virtual calls are not allowed inside the destructor, since they will not call the overriden functions, but only the functions in the current destroying class.
Dynamic casts downcasting: Some of the things to do involve donwcasting via dynamic_cast. dynamic_cast downcasting inside the destructors always fails.
EDIT 2:
The answer of Ezee works as I needed. Here is my complete code snippet, showing the code, with also a dynamic_cast:
template <typename T>
class TAfterConstructionBeforeDestruction: public T {
public:
~TAfterConstructionBeforeDestruction() {
this->beforeDestruction();
}
protected:
using T::T;
};
class IBase: public QObject {
public:
//Now it can be public, just as the one in QObject!
virtual ~IBase(){}
template<typename T>
static IBase * create() {
//Create a
IBase * obj=new TAfterConstructionBeforeDestruction<T>;
obj->afterConstruction();
return obj;
}
protected:
IBase(){}
virtual void afterConstruction(){}
virtual void beforeDestruction(){}
};
class TSubclass: public IBase {
public:
virtual ~TSubclass(){}
protected:
TSubclass(){}
virtual void afterConstruction(){
qDebug()<<"AfterConstruction";
}
virtual void beforeDestruction();
private:
friend class IBase;
};
class TSubclass2: public TSubclass {
public:
virtual ~TSubclass2(){}
protected:
TSubclass2(){}
virtual void beforeDestruction(){
qDebug()<<"BeforeDestruction from Subclass2";
TSubclass::beforeDestruction();
}
};
void TSubclass::beforeDestruction() {
qDebug()<<"BeforeDestruction";
TSubclass2 * sub=dynamic_cast<TSubclass2*>(this);
if (sub) {
qDebug()<<"We are actually a TSubclass2!";
}
}
int main(int argc, char *argv[])
{
//QObject *obj=new TSubclass() //Compile time error! Nice!
QObject *obj=IBase::create<TSubclass>();
delete obj;//Now it works fine!
IBase * obj2=IBase::create<TSubclass2>();
delete obj2; //It is still succeeding to dynamic_cast to TSubclass2 without any problem!
}
First of all, I must say that calling virtual methods from a constructor or a destructor is a very bad practice.
Call doAfterConstruction() from the constructor of the mose derived descendant of IBase.
Call doBeforeDestruction() from the destructor of the mose derived descendant of IBase.
You can do the same using signals/slots:
Declare a signal beforeDestroyed() in IBase (add Q_OBJECT macro also).
In the constructor of IBase connect this signal to a slot doBeforeDestruction (make it a slot).
In the destructor of the mose derived descendant of IBase emit the signal: emit beforeDestroyed().
If you have a lot of descendants you may want to avoid doing the same thing in every constructor/destructor. In this case you can use a template also:
template <class T>
class FirstAndLastCall : public T
{
public:
FirstAndLastCall ()
{
doAfterConstruction();
}
~FirstAndLastCall
{
doBeforeDestruction();
}
}
Usage:
IBase* obj2 = new FirstAndLastCall<TSubclass>();
class base
{
public:
virtual void start();
virtual void stop();
void doSomething() { start(); .... stop(); }
}
class derived : public base
{
public:
void start();
void stop();
}
But when I call doSomething() in the derived class it is using it's own definition of Start() and Stop() - not the derived ones.
I don't want to rewrite doSomething() in the derived class because it would be identical to the base one. What am I doing wrong?
Sorry if that wasn't clear.
The behaviour of Start() and Stop() in the derived class is different (it's a different machine) - but I want to use the original base class doSomething() because that hasn't changed. It just has to start() and stop() using the new derived class code.
The code you've posted should work the way you want. Calling doSomething on an instance of derived will call the overridden start and stop functions defined in derived.
There's an exception to that, though. If you call doSomething in the constructor or destructor of base (whether directly or indirectly), then the versions of start and stop that get called will be the ones defined in base. That's because in those circumstances, you don't actually have a valid derived instance yet. It's either not fully constructed or partially destructed, so the language prevents you from calling methods that would use the partial object.
If you're not calling it from a base constructor or destructor, then there is more to the problem than what's shown here.
Update
Based on your comment below that you are trying to make doSomething() call the Derived class's version of start() and stop(), my updated answer to your question is as follows:
There is nothing wrong with the way that you defined Base and Derived. You are probably experiencing what is called "code slicing", where you are calling "doSomething()" on an object whose declared type is "Base", instead of "Base*" or "Base&", which will result in the object being converted to type Base.
Bad example:
Derived derived;
Base base = derived;
base.doSomething(); // This is Base's version of doSomething()
Good example:
Base* base = new Derived; // NOTE: declared type is "Base*"
base->doSomething(); // This will call Derived version
delete base;
Side-note: you should use a scoped_ptr, shared_ptr, unique_ptr, or some other smart pointer class instead of using a pointer directly as in my example; however, to not obscure the issue, I have opted to use a raw pointer in this example. For more information about "slicing", see:
What is the slicing problem in C++? - StackOverflow
Slicing in C++
Original solution
You could do something like this:
class Base {
public:
Base() {}
virtual ~Base() {}
virtual void start() {
startInternal();
}
virtual void stop() {
stopInternal();
}
void doSomething() {
startInternal();
// ...
stopInternal();
}
private:
void startInternal() {
// ...
}
void stopInternal() {
// ...
}
};
class Derived : public Base {
public:
Derived() {}
virtual ~Derived() {}
virtual void start() {
// ...
}
virtual void stop() {
// ...
}
};
If you do this, then doSomething() will use the internal version of start/stop which isn't overridden. You will find this pattern a lot, when a constructor/destructor needs to share logic with a virtual method.
Also, not related to the issue at hand, don't forget that you should always create a virtual destructor whenever you create a class that has virtual methods.