I've done my due diligence but can't find an answer to this one:
How does the Qt signal/slot mechanism interact with non-Qt threads?
In particular, is it safe to emit a signal from a non-Qt (e.g. TBB) thread, to be caught by a slot in my main event loop? Supposing I connect it with a queued connection explicitly? (My feeling is that specifying that the connection is queued would be mandatory; is this correct?)
(As a side question, I have been assuming that in general, the Qt synchronization classes, e.g. QMutex
, work across non-Qt threads. Is this correct?)
(As a clarifying remark, the thing that I'm worried about is that the queued connection mechanism will not use guards, e.g. mutexes, to add the metacall to the main thread event queue if it does not detect that the signal is being emitted from a different Qt thread.)
(Final addition: I can believe that because the Qt mechanisms are implemented in terms of platform-specific primitives, that in practice all of the things that I am trying to do will just work gracefully, but I'm also wondering if Qt provides any guarantees that these things will work.)
It is generally unsafe to provide slots in your QThread subclass, unless you protect the member variables with a mutex. On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.
There are several ways to connect signal and slots. The first is to use function pointers: connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed); There are several advantages to using QObject::connect() with function pointers.
emit is just syntactic sugar. If you look at the pre-processed output of function that emits a signal, you'll see emit is just gone. The "magic" happens in the generated code for the signal emitting function, which you can look at by inspecting the C++ code generated by moc.
In C++, public means those members that are accessible from anywhere where the object is visible, private means that members are accessible only from within other members of the same class or from their friends. But in Qt, the difference in private slots and public slots seem not to exist.
The documentation states:
Note: Qt's threading classes are implemented with native threading APIs; e.g., Win32 and pthreads. Therefore, they can be used with threads of the same native API.
So yes, Qt's mutexes will work with other threads (as long as they also use the same native API).
The difference between Qt threads and other threads is that other threads will never have Qt's event loop running, so won't be able to receive and handle any signals. However, if you'll run the event loop (exec
) inside such a thread everything should work fine.
The signal related functions, mainly processEvents
and postEvent
are said to be thread safe:
Note: This function is thread-safe.
If the objects have the thread affinity set correctly (using the moveToThread
method) you don't need to set the connection type explicitly, the default AutoConnection
works as follows:
(default) If the signal is emitted in the thread which the receiving object has affinity then the behavior is the same as the Direct Connection. Otherwise, the behavior is the same as the Queued Connection.
This answer suggests that non-Qt threads should also be correctly identifiable by Qt's methods - currentThread
should return a QThread
instance even for a non-Qt thread, as it's only a wrapper over native threads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With