QT Is a slot launched in a separate thread - c++

I have done some research on this topic . the thread at SO also caught my interest and I wanted to summarize my understanding and be corrected if I am going wrong on a certain path and also wanted to know how QueuedConnection would work.
Here is my understanding followed by the question.
Signals can be connected manually to slots primarily through two different ways first way is using direct connection and the second way is queued connection. In case of a direct connection if the slot method that is attached to the signal is in the same thread then the slot method is called sequentially (as if it was just another method) however incase the slot is in a different thread from where the signal is launched then QueuedConnection would launch it when it finds it appropriate. (Now In this case I am not sure if it would launch a new thread or how it would proceed on doing that)

Slots don't belong to any particular thread, as they are just plain functions. But objects do. If you connect a signal to a slot by QueuedConnection, the signal emission will create an event and send that into the event queue of the target. Qt will arrange that your slot will be called when internally processing that event.
As for all events, they are processed in the thread of the object's thread affinity. You can change that thread by calling moveToThread on the target object.

In multithread environement when sender and recievr object is in diffrent thread.
Qt::QueuedConnection
What is happening when emiting thread? it simply emits( internally
postevent, to reciever threads message queue) and resume emiter
thread( not blocking).
what is happening on reciever thread, after executing above
statement? The slot is invoked when control returns to the event loop
of the receiver's thread.
Qt::BlockingQueuedConnection
What is happening on emiting thread ? it emits( internally sendEvent,
to reciever message queue) and block emiter thread until receiver
slot returnes.(Blocking).
what happening on receiever thread ? The slot is invoked when control
returns to the event loop of the receiver's thread.

Roughly speaking, for QueuedConnection Qt will make a queue of received signals for the thread the slot belongs to, and will launch them one by one in order they are stored in the queue when the thread becomes available (it finishes whatever it was doing and returns to event loop).
No new thread will be launched - slot belongs to some thread, so execution will be performed in that thread.

Related

Determinate queued signals

Assume I have a Qt::QueuedConnection connection in which the signal is emitted in a different thread from the one the consumer slot is called. Now I want to close the application and in the handler destructor I would like to check either there are any remaining queued signal-slot calls (I am using this signal slot connection mechanism as a queue). Is it possible?

Is Qt's event loop thread safe or atomic? How is it synchronised when dealing with `QueuedConnection`?

Suppose 2 QThreads are running with following relation:
connect(&Object1OfThread1, &Object1::Signal,
&Object2OfThread2, &Object2::Slot, Qt::QueuedConnection);
So when an object from one thread raises a signal, the other thread's slot is invoked. As discussed in Qt signals (QueuedConnection and DirectConnection), due to Qt::QueuedConnection, the Signal() is posted/appended into the event loop of the Thread2. When it turn comes, the Slot() is invoked.
Question: Is the event loop itself thread-safe?
viz. what if Thread1 and Thread3 both post a signal simultaneously to Thread2's event loop.
The article mentioned in this comment, says that the event queue is protected by a mutex.
How Qt Signals and Slots Work - Part 3 - Queued and Inter Thread Connections
A QueuedConnection will post an event to the event loop to eventually be handled.
When posting an event (in QCoreApplication::postEvent), the event will be pushed in a per-thread queue (QThreadData::postEventList). The event queue is protected by a mutex, so there is no race conditions when threads push events to another thread's event queue.
Once the event has been added to the queue, and if the receiver is living in another thread, we notify the event dispatcher of that thread by calling QAbstractEventDispatcher::wakeUp. This will wake up the dispatcher if it was sleeping while waiting for more events. If the receiver is in the same thread, the event will be processed later, as the event loop iterates.
Qt event loop is thread safe but not atomic.
Thread safety
As long as Object2OfThread2 state is always modified by the thread associated with Thread2, there won't be any race conditions. At most one slot will be executed at any time.
Atomicity
The order of execution of slots is governed by :
usual thread preemption
The order in which the connections were made to this slot.
The other slots connected to the signal.
So I would not advise to assume a specific order of execution for a given slot.
what if Thread1 and Thread3 both post a signal simultaneously to Thread2's event loop
First, it is different signals : two threads cannot emit the same signal of the same object as this object resides in only one QObject
The signal connected first wins, assuming these signals are only connected to Object2OfThread2 even if they are "posted" simultaneously.
If for instance Thread1 signals are connected to other signals\slots, and those connections are made before Object2OfThread2, &Object2::Slot, they will be processed before being posted on Object2OfThread2 event loop. If the signals emitted simultaneously, Thread3 signal will be the first queued, so the first to execute.

How to know in which thread Qt executes slots?

I use Qt and I need to execute some code in the main thread. I realized that successfully using signals & slots.
My question is, even tho it's working atm: what defines in which thread a slot is executed as the direct result of signal emitting?
Is it inside the thread that executes the connect() function or what?
It depends how you set up your connection.
If you use Qt::DirectConnection, the slot will be executed immediately in the signaling thread, bypassing any event loop.
If you use a Qt::QueuedConnection, it will be executed in the receiving objects event loop, in the receiving objects thread.
If you don't specify the connection type, it defaults to Qt::AutoConnection, which defaults to Qt::QueuedConnection if the two QObjects have different thread affinities.
A directly connected slot always executes immediately, before the signal returns.
A slot connected via a queued connection will execute in the event loop running in its object's thread(). The slot is called from within the exec().
The default automatic connection determines which method to use every time the signal is emitted. If the target object is in the same thread, the slot will be called immediately from the signal, otherwise an event will be posted to the target object, picked up by the target thread's event loop, and executed there.
The logic is, effectively:
void mySignal(params) {
// moc-generated code below
for (all directly connected slots, all automatically connected slots in this thread):
slot(params);
for (all queued-connected slots):
QCoreApplication::postEvent(slot's object, new QMetaCallEvent(slot, params));
}
The direct connection doesn't require an event loop to work, and is like any indirect function call through a function pointer.

Blocking thread for wait queue

I have applications with 2 threads. In first (main) thread I want to generate some message and send it to second thread. Is there method to blocked thread for wait incoming message (like a queue in embended OS(FreeRTOS, TNKernel etc))?
while (true) {
waitQueue(TIMEOUT_INFINITY);
}
in waitQueue(TIMEOUT_INFINITY); current thread becomes blocked, when in main thread generates some message waitQueue releases thread.
The natural way for doing this in Qt is calling QThread::exec() in the thread (which is what the default implementation for QThread::run() do).
after that to execute a QObject instance (worker object)'s slots in that thread, you can set the instance's affinity to the new thread using QObject::moveToThread(), then when a signal connected to some slot in that instance is emitted, the slot will be invoked in the new thread.
Instantiating a QThread provides a parallel event loop, allowing QObject slots to be invoked in a secondary thread. Subclassing a QThread allows the application to initialize the new thread before starting its event loop, or to run parallel code without an event loop.
see QThread class, QObject class, Threads and QObject, along with Qt event loops.
Hope this helps. . .

How can i create several thread in a queue with Qt?

How can I create threads in a queue with Qt that execute step by step (when one thread completed another thread started)?
Please give me a code example?
Look at QThreadPool.
However, as Frank pointed out, if you execute things after each other, there is no need for threads.
There is a "finished()" signal from the QThread object. In your thread manager thread (i.e. your main qwidget or qmainwindow), you could have a queue manager class that has a slot to which this signal is connected. The slot would initialize and execute the next thread in the queue when it receives the finished signal from the currently running thread.
This would prevent blocking in your manager thread and allow you to execute these thread objects from a queue as you describe.
Make sure that each time you respond to a finished signal, you connect the next thread's finished signal to your queue manager slot. You also want to make sure that you start the thread in your "add to queue" method if there are no other threads currently running.