I'm using some QThread in my application.
My objects "live" in different threads (their owner threads as Qt means it are different) and use signal/slots with queued connections to communicate.
Now, I have this problem :
Object "A" lives in QThread "A"
Object "B" lives in QThread "B"
Gui lives in the "main thread"
then :
Object "A" calls a method B::foo on "B" instance, from its own thread "A"
the ressources shared by this B::foo method are protected using a mutex, no problem here to execute B::foo from the thread "A"
inside the B::foo method, object "B" emit the signal barSignal
And I have some questions about his configuration :
Is it safe to emit a signal of object "B" from a thread which is not the "B" owner's QThread ?
Is it safe to use Qt::AutoConnection to receive this signal in a GUI object who lives in the "Qt main thread" ?
Is it safe to use a Qt::AutoConnection to receive this signal in a object "C" who lives in it's own QThread "C" ?
My test tends to say "yes" to everything.
By reading the Qt emit code, it seems to be ok.
But it didn't find anything in the Qt documentation about "emitting signal from a thread which is not the emitter's owner thread".
It's safe to emit signals from other threads, if you use auto or queued connections. Auto is deduced to be queued in situations where the signal is emitted in a thread in which the receiving QObject do not have affinity. Direct connections are not thread safe.
There is a "Signals and Slots Across Threads" section in the documentation that deals with emitting signals to objects in different threads.
Queued Connection - The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
also
The connection type can be specified by passing an additional argument to connect(). Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.
QObject::connect() itself is thread-safe.
Related
There is a multi-threaded application on QT5. Threads emits signals to each other. For example, the button click signal in the GUI comes in three separate threads, and each thread performs its own function. Is there an easy way to connect all signals to some object, let's call it SignalHub? And this SignalHub will receive all signals from all threads or objects, and any thread or object can be subscribed to the desired signal? Something similar to DBus, but only for several threads within a single QT application? Each thread or object should not receive its own signal. The purpose of this is to reduce the amount of code (there are several threads in the application, and each has multiple signals and slots). And it would be ideal to connect the necessary signals to (and from) the SignalHub only in new object's constructor or new thread's constructor.
Signals are thread-safe. So are connect() and disconnect(). Meaning: you can literally declare any object you want to be your "signal hub" and just connect the slots across threads as you desire. To what threads the objects involved belong doesn't matter. No problems.
To avoid receiving signals an object sent itself, you can simply do something along those lines:
void MyObject::someSlot() {
if(sender() == this) return;
}
http://doc.qt.io/qt-5/threads-qobject.html#per-thread-event-loop
https://wiki.qt.io/Threads_Events_QObjects#Per-thread_event_loop
These two links talk about event loop. Please explain the "meaning" of the term "event loop" w.r.t threads in Qt?
An event loop is usually a loop that is run by the main thread to receive events that either originate from the system (e.g. GUI interaction, network events, timers, ...) or from other Qt components (e.g. QCoreApplication::postEvent(), ...). The event loop waits for new events to arrive in the event queue, then takes them out of the queue and sends them to their destination QObject where they are handled by an overridden QObject::event(QEvent*) (e.g. A QPushButton would handle a mouse press event by emitting pressed(), ...).
Per-thread event loops are a generalization of the concept above. This makes it possible to handle events in worker threads by introducing the concept of a QObject's thread affinity. Thread affinity is the thread in which a particular QObject should have its events handled (the thread from which QObject::event gets called for this QObject). In the big picture, this can be used to run asynchronous code in worker threads (since GUI code should be run only in the main thread). For example, you can run many asynchronous sockets and have QTimers to disconnect these sockets after some specified time of inactivity all in a single worker thread. Per-thread event loops are also essential for cross-thread signal-slot connections, since this kind of signal emissions is translated into QMetaCallEvents under the hood (to be delivered to its destination QObject).
I am confused on one point with notify method. "notify() : It wakes up one single thread that called wait() on the same object." So lets say two thread called wait for the same object. So when I call notify which thread will be notified?
You can't know which one will be notified. Spec says:
public final void notify()
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.
How can i Send signal from one worker thread to another worker thread? First thread will be waiting for the signal from second thread after getting signal first thread will execute his jobs.. how can i implement this?
By "send a signal" I guess you don't mean send a (Windows) message. Too complicated implementation for something really simple. Your (2nd) worker thread should create a message-loop and check for a (custom) message? Quite an overkill. Although worker threads can of course create message-loops, this is very uncommon.
Better use synchronization, and the proper object type for this is an "Event" (a simple object that can be in either signaled or non-signaled state). The 2nd thread should wait on this, and the 1st one must set it to the signaled state to notify the 2nd to do its job (this amounts to "sending the signal").
I have made a Gui thread and a QTcpSocket thread in Qt.I want to access data
from QTcpSocket thread to Gui thread.How to solve it?
Do i need to declare some global variable and how?
The easiest way is to communicate via signal-slot connections. There is one QObject in each thread. The sending object has a signal, which is connected to the slot of the receiving object in the other thread.
In this setup, you make sure that the objects on both ends of the connections are configured to live in the correct threads. You might need to call QObject::moveToThread(). QObject also has a property where you can get the current thread (for debugging purposes in this case).
Then just establish the signal-slot connection as usual. Since both objects are in different threads, when the signal is triggered, a slot invocation event will be placed in the event loop of the receiving flag. This is explained in the Qt documentation, look for Qt::QueuedConnection.
The QTcpSocket is created from the gui thread.
So at that point the gui thread has a pointer to the socket object.
It then creates a connection between a slot in the gui and a signal in the socket.
In the socket object whenever you get data you simply emit a signal containing the data, which will be picked up by the gui thread.
You can pass any Qt type eg QString, QByteArray (or a raw pointer), through a signal/slot very efficiently. The details if signals between threads are also handled automatically.