QObject delete order in multi-threaded application
-
I found a solution for an issue but I am not sure if that solution is clean and correct.
My application processes entries of a job queue by multiple concurrent threads. The controller polls the job queue and starts threads. The worker class provides just one single method which is called for each job (concurrently, multi-threaded).
Worker* worker=new Worker(mainWindow);
Controller* controller=new Controller(worker,mainWindow);When I close the main window, then the destructors of worker and controller are automatically executed, but in the wrong order. The destructor of mainWindow deletes the worker first and then the controller. This is a problem for me, because the threads of the controller are still running and may attempt to call the workers method.
I need to destruct the controller first, which also terminates the threads. So I put the following line into the constructor of the controller class:
worker->setParent(this);
Now the worker gets deleted after the controller, which is the correct order.
But I am not sure if that is the right solution. Can someone help?
-
Without seeing more of your code it is hard to say.
What I do see is this:
You are newing up the controller and worker yourself. I am guessing that you are relying upon going out of scope some how to delete them or are you actively removing them?
I've heard that delete order is somewhat compiler dependent but generally is the reverse of the order in which you initialize... So in your constructor if you did:
window::window() : controller(nullptr), worker(nullptr) { }
I would expect the compiler to reverse that order on delete. So you could try changing the order in which you initialize.
On the use of worker->setParent I don't see a problem with doing this way as you are basically assigning ownership of the worker to the controller which is how you seem to want it to be. Again my initial concern is who/what is freeing the controller?
Someone with more experience might chime in but you also since you are using threads might look into the use of deleteLater() which can take care of removing items when when thread is done.
-
Hi,
@SysTech : deleteLater won't remove things when the thread is done, but at the next event loop iteration.
@s.frings74 If you need a specific order of deletion, then you should do it yourself to ensure it's done properly. From the looks of it, it's the destruction of your Controller that should drive the destruction of your worker.