moveToThread(qApp->thread()) and signal-slot - qt

If I understand correctly, slots will always occur in the main thread.
So what is the difference between using the signal-slot system and moveToThread(qApp->thread())?

Your understanding is incorrect.
Each thread has its own event queue, so when a signal is emitted, if the connection is queued (not direct), it will be added to the event queue matching the thread affinity of the object.
For example: -
Let's assume that we have 2 objects; object1 running on the main thread and object2, which has been moved to a new thread.
connect(object1, &SomeObject::signal1, object2, &SomeOtherObject::signal2);
When object1 emits signal1, an event is posted to the new thread; the thread to which object2 was moved.
When the new thread processes its event loop and the event for signal1 it will execute object2's slot, signal2. This is not on the main thread.

Each QObject tree can be assigned to a specified thread. moveToThread means move tree of objects (for given root object) to that thread.
That doesn't mean that that all code of the QObject is assigned to that thread. It means that any slot invoked by queued connection (not direct connection) will be invoked in given thread. Read carefully documentation of QObject::connect and Qt::ConnectionType.
Except for Qt::DirectConnection, all connections use the owning thread of the receiving object to deliver the signal. All arguments are packed and sent to the receiver's event queue. When the receiving thread's event loop gains control it will unpack the arguments and invoke the slot.
Note that I wrote above about a tree of objects. You can't move an object to a different thread if it has a parent. And you can't reparent an object to one that belongs in a different thread.
By default objects are assigned to thread which created them (if they do not have a parent). So it doesn't have to be main thread.

Thread a,b,c;
a created b, b created c;
connect(a, &QThread::finished, a, &QObject::deleteLater);
connect(b, &QThread::finished, b, &QObject::deleteLater);
connect(c, &QThread::finished, c, &QObject::deleteLater);
I do some experiment, found that if b had finished faster than c, c would not be deleted; But can do that:
b->moveObject(a); //then b would be deleted again.

Related

When to use deleteLater

Assuming I have the following snippet, is it safe to call deleteLater in qto's destructor for other QT objects it might administer?
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyQTObject qto;
qto.show();
return a.exec();
}
Because I've analyzed similar code like this with a leak detector and all the objects for which deleteLater was called, weren't deallocated correctly unless I replaced the call with a normal delete.
If I've understood this correctly, deleteLater only registers a deletion event in the QT message queue. Can this be the problem that qto's destructor is called at the end of main's scope whereas the QT message loop already ends with the return from a.exec? Thus the deletion event will never be processed, in fact not even pushed into a message queue since there is none?
This post is rather aged, but I would like to add the answer I would have liked to come across when I was asking this myself.
deleteLater() can be very useful in combination with asynchronous operations. It especially shines, I think, with the more recent possibility to connect signals to lambda functions.
Suppose you have some longComputation() that you want to execute asynchronously (not in the sense of multithreading, in the sense of scheduling execution in the event loop). You can do like this:
void MyClass::deferLongComputation()
{
QTimer* timer = new QTimer();
connect(timer,
&QTimer::timeout,
[this, timer](){this->longComputiation(); timer->deleteLater();});
timer->setSingleShot(true);
timer->start();
}
where deleteLater() takes care of safely disposing of the QTimer once its duty has been carried out and avoid the memory leak that one would have otherwise.
The same pattern can be used in multithreading with QFutureWatcher.
As I understand it, deleteLater is most often used when you require an object to be deleted from within the call to a slot. If delete is used in this case and the object is referenced when returning from the slot, a reference to uninitialised memory occurs.
Therefore, deleteLater requests that object to be deleted by placing a message on the event loop, which is processed at some point, on returning from the slot and it is safe to be deleted.
I expect that using deleteLater in the destructor means there's a likely chance that the object goes out of scope, calls deleteLater on its managed objects, but quits before the event loop has a chance to delete the objects, as exiting from QApplication::exec() will terminate the event loop.
The question is old, but I'll leave this for the future generation)
The reply which was marked as an answer is correct but oddly formulated.
Actually your question contains a right answer:
message loop already ends with the return from a.exec? Thus the
deletion event will never be processed, in fact not even pushed into a
message queue since there is none.
This is exactly what is happening. Everything deleteLater() does is just posting a deletion event into the outter event loop. When event gets proccessed - object gets deleted. But if there are not outter event loop and no event loop is encountered later in the execution flow - event will never get posted, thus object is never deleted.
If you call deleteLater() in the object's destructor and put an object on the stack - deleteLater() is called when the object goes out of scope. In your example "going out of scope" is happening when closing brace of main() function is encountered. However, by that time, a.exec() (which represents the main event loop of Qt App) has already returned --> no event loop any more --> deleteLater() was called, but it's nowhere to post a deletion event --> objects were supposed to be "deletedLater" never get deleted...
Regarding the part "when to use deleteLater()":
Kuba Ober answered:
Generally speaking, there is a narrow set of circumstances where
deleteLater should be used. Most likely you simply shouldn't be using
it...
Don't listen to it, it is absolutely incorrect as the whole answer. What you should do and what should not you better decide after reading this article. Although, it is mainly about Qt threads, the article also tells about ascynchronous programming (and, as Emerald Weapon mentioned, it is exactly what deleteLater() was created for).
Also, smart pointers and QObject parent ownership have nothing to do with scheduling for the deletion with deleteLater(). These both techniques are actually using a simple delete operation under the hood. And as the article shows and as Emerald Weapon's answer demonstrated: delete does not solve the problems deleteLater() does. So if you need to delete object you use delete, if you need to schedule it for the deletion you use deleteLater().
BTW, if you want to use smart pointer with deleteLater() you can specify the deleter:
// Shared Pointer
QSharedPointer<MyObject> obj =
QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
// Scoped Pointer
QScopedPointer<MyObject, QScopedPointerDeleteLater> customPointer(new MyObject);
And at last, It is an NOT an error to use deleteLater() in the destructor of QObject, for non-child objects.
You are correct that the deleteLater() command is only executed by an event loop.
From the Qt documentation for QObject:
Schedules this object for deletion.
The object will be deleted when control returns to the event
loop. If the event loop is not running when this function is
called (e.g. deleteLater() is called on an object before
QCoreApplication::exec()), the object will be deleted once the
event loop is started. If deleteLater() is called after the main event loop
has stopped, the object will not be deleted.
Since Qt 4.8, if deleteLater() is called on an object that lives in a
thread with no running event loop, the object will be destroyed when the
thread finishes.
Note that entering and leaving a new event loop (e.g., by opening a modal
dialog) will \e not perform the deferred deletion; for the object to be
deleted, the control must return to the event loop from which
deleteLater() was called.
Note: It is safe to call this function more than once; when the
first deferred deletion event is delivered, any pending events for the
object are removed from the event queue.
If you want all child QObjects to be deleted when qto is deleted, make sure they are created with qto as a the parent.
Generally speaking, there is a narrow set of circumstances where deleteLater should be used. Most likely you simply shouldn't be using it.
It is an error to use it in the destructor of QObject, for non-child objects. As you've found QObjects may well be destructed without an event loop present. There are no deleteLater calls in object destructors the qtbase Qt module, for example.
One has to be careful here: for example, ~QTcpServer() invokes close() invoking d->socketEngine->deleteLater(), but the socket engine is already a child of the server and will be deleted by ~QObject() anyway.
For all I know, MyQTObject should be doing one of the following:
using a smart pointer like QScopedPointer or std::unique_ptr,
have the objects as regular (non-pointer) members,
use raw pointers and have the objects be children of it.

QThread and QML Locking Up

I have a class, audio_engine_interface, and in main.cpp, I add it to the QML thing.
viewer.rootContext()->setContextProperty("engine", engine);
In audio_engine_interface, I have a audio_engine class, which is computationally intensive—it needs to run on its own thread.
void audio_engine_interface::play()
{
QThread thread;
thread.start();
engine->moveToThread(&thread);
engine->play(); // Will use 100% of CPU
}
However, when I do this, the whole QML thread locks up, meaning I can't pause (pretty important). Am I missing something?
EDIT:
This thread won't mess up anything or access objects from other places. However, it does have a pause function that will need to be called at some point. For what it's worth, the engine is doing pitch shifting.
This is a problem: -
Qthread thread;
Creating a QThread object like this is creating it on the stack. When the function ends, the object will go out of scope and delete the QThread object.
You need to dynamically allocate the object on the heap: -
QThread* thread = new QThread;
Then remember to delete the thread, or set it to delete itself: -
//Qt 5 connect syntax
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
You should also be aware of thread affinity (the thread which an object is running on). I suggest reading this article on how to use QThread properly.
You have so many problems.
when you move to thread your object must not have a parent
your thread object is local variable so it will day immediately when udio_engine_interface::play() end execution
you are invoking you engine->play(); method directly and this means that it will be executed in current thread.
moveToThread means that slots invked by signals connected using default 5th parameter (Qt::AutoConnection) will be queued in event loop of given thread.
The easiest way to fix it is use QtConcurrent:
void audio_engine_interface::play()
{
QtConcurrent::run(engine, &EngineClass::play);
}
Depending what your engine does you should make it thread safe (use mutex locks an so on), without details it is hard to tell, what exactly you should do.

QTimer timeout signal not invoking slot when run on a different thread

I have a subclass of QObject referred to as myObject, which has a QTimer data member allocated on the heap in the constructor. myObject also has a slot which is connected to the QTimer timeout() signal in the constructor. I refer to the pointer of myObject as myObject_ptr.
I want to run myObject on a different thread from the main thread. Following the relatively new recommendations, I DO NOT subclass QThread. In the main thread, I use myObject as follows:
QThread *thread = new QThread(this);
myObject_ptr->moveToThread(thread);
connect(myObject_ptr, SIGNAL(destroyed(), thread, SLOT(quit())); //thread not needed if no object
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); //to avoid memory leak
connect(thread, SIGNAL(terminated()), thread, SLOT(deleteLater())); //to avoid memory leak
thread->start();
The main thread invokes a function of myObject_ptr which in turn starts the QTimer data member. When it times out, nothing happens, but I expect the slot of myObject to which the timer's timeout() signal is connected to be invoked. What is the problem? How do you make this work. It works flawlessly if myObject is run on the same thread where it was created i.e. main thread.
From all the readings I've done, I think the new thread I am creating might not be processing events because it doesn't have it's own event loop. I also read documentation/articles contrary to that, saying that when the thread starts, the run() function calls exec() and you have an event loop.
Could someone help me please?
I could probably get it to work correctly if I subclass QThread, but based on current recommendations, I would prefer to avoid doing that.
Thank you in advance.
I solved my problem!! In the constructor of MyObject, the timer is allocated on the heap as follows:
timer_ptr = new QTimer(this);
but to work correctly, it should be:
timer_ptr = new QTimer(0);
and in the destructor, delete the object manually:
timer_ptr->deleteLater();
I guess when they say can't move an object with a parent to a thread, they really do mean ALL objects, including data members of the object actually being moved to the new thread.
Happy coding.

QObject.moveToThread(thread) if thread is a child of that object

I wanted to create QObject (object) with the child QThread (thread) with that object as parent (for keeping thread alive while object is alive) and make object.moveToThread(thread) but signal to start the thread isn't working in this case.
Simply:
object owns thread
object moves to thread
signal starting thread isn't working
What's going on?
[Edit]: Throwing away my initial answer due to the comments
Maybe do it like the following:
Create the Object
Create the Thread, but don't assign a parent to it
Connect the Thread's finished() signal to its deleteLater() slot as usual
Connect the Object's deleted() signal to the thread's stop() slot
Then, when you delete the Object, it will emit deleted() which will stop the thread. The thread will emit finished() which will call its deleteLater() slot.

Will disconnecting all signal-slot connections during the execution of a slot prevent all subsequent slots from being called?

Say I have a Qt application where I have something like this:
connect(A, SIGNAL(a()), B, SLOT(b1()));
connect(A, SIGNAL(a()), B, SLOT(b2()));
...
void B::b1() {
A->disconnect();
}
If a() is emitted, will the slot B::b2() still be called after disconnecting all slots from A in B::b1(), since they both respond to the same signal? Assume that both objects live in the same thread, so we have a direct connection.
I know that the disconnect() disconnects all signal connections from A, but I am not sure if the emit just schedules both the b1 and b2 slots to be called and then calls them, so that a change to the connections has no effect until the two slots (and therefore the emit) return. So it could be implemented like:
emit:
make temprorary copy of signal's slot table
foreach element in temporary slot table: call
disconnect:
clear signal's slot table
Otherwise you could run into datastructure integrity problems.
A quick experiment shows that the second slot is not called.
However, I'm not sure if this is something that Qt promises.
Qt does document that certain checks are made during the iteration of connected receivers, but it's but that's pretty loose and non-specific (and I haven't come across anything better in my short search); from http://doc.qt.io/qt-5/signalsandslots.html:
This is the overhead required to locate the connection object, to safely iterate over all connections (i.e. checking that subsequent receivers have not been destroyed during the emission)
So they loosely document that certain checks are made while a signal is emitted, such as whether a receiver has been destroyed. I think checking whether the connection has been disconnected seems like a similar kind of situation, but it would be nice if that were explicitly documented.
Since it sounds like this will be a problem for you (you want all the signals to get through, right?), you may be able to work around this problem by ensuring that the signal to slot b1() is connected last. Qt does promise that slots will be called by a signal in connection order, so if you arrange for the slot that does the disconnect to be the last one, all the other slots will be seen.
I don't know how easy this might be to arrange, but it also seems kind of strange that an object would disconnect everything from inside another object's slot function (so there's probably some other refactoring that can solve this problem as well).
If none of that is acceptable, it wouldn't be too hard to come up with a proxy object for A's signals that has the behavior you need. There would be a single:
connect(A, SIGNAL(a()), proxy_obj, SLOT(proxy_slot()));
to connect A's signal to the proxy, then B can connect to the proxy's signal (which the proxy would be emit when the proxy's slot got called):
connect(proxy_obj, SIGNAL(a()), B, SLOT(b1()));
connect(proxy_obj, SIGNAL(a()), B, SLOT(b2()));
Since A's disconnect will not affect the connections that the proxy has to B, the proxy will ensure that all of B's slots get called when signal A->a() is emitted.
class A_proxy : public QObject
{
Q_OBJECT
public slots:
void proxy_slot() {
emit a();
}
signals:
void a();
};
disconnect reference page answers your question.
It depends on how you call it, and the way you call it (without any parameter), it will disconnect all signals on object A, therefore the slot B:b2 will not be called after disconnect.

Resources