Thread-safe classes in Qt
-
Hello all,
This is more of generic question to understand the basics of Qt.
What are all the classes that are thread safe and not? How do I know that? For example, is QTranslator thread safe, how do I ensure that?
Does Qt uses any static variables? And how do I know who is using what?
If any of the class is not thread safe, should I need to write a wrapper around that to use mutex? Is there any smart way of doing it?
Thanks,
Kumara -
Have you already seen this? http://doc.qt.io/qt-4.8/threads-reentrancy.html#reentrant
-
Hi,
The thread safety state (reentrant/thread safe) of each class is mentioned at the top the documentation. If nothing is written then there's no safety guaranty.
Qt has indeed some statics, as to exactly which and for what, you'll have to take a look at the sources. do you have any specific case in mind ?
As for mutex, semaphore and other protection, it all depends on your use case.
-
@Schluchti Yes, I did take a look at the documentation already. That wasn't so clear to me, that's why I wrote to get some more details from experts.
@SGaist Hi Sam! I don't exactly perfect example in my mind. Here is what poked these thoughts in my mind.
I run my Qt application in a thread and that uses QTranslator for language translation.
In one thread I do,
myTranslator->load("English.qm"); qApp->installTranslator(myTranslator);
In the other thread if I do
myTranslator->removeTranslator(myTranslator);
Can some other thread remove my translator? Is it practical. What if QTranslator uses some of static variables that hold some information about translator. To answer all these questions, I need to know if the class is really thread-safe.
I know this is not a great example, but just trying to understand if one thread can update information in other thread.
-
That's probably not the answer you are looking for, but I would always add synchronization logic in case you are unsure (or the documentation doesn't provide the necessary information). Adding some synchronization logic is almost always cheap, but prevents you from running into some nasty multithreaded issues.
I am also a big fan of grouping things logically together in one entity (thread). So for example if I need to write/read a file I create a dedicated thread that does the reading and writing. If I need to access the file from another thread, then I notify the file handling thread, which handles the action (read/write) in his own event loop (and eventually signals the result back to the thread that requested the action). In most cases you won't recognize any performance impact due to this. But keeping the logic in one thread often makes it easier to debug/extend. But that's just personal preference (and not really an answer to your question) ;)
-
@Schluchti Yes, I did take a look at the documentation already. That wasn't so clear to me, that's why I wrote to get some more details from experts.
@SGaist Hi Sam! I don't exactly perfect example in my mind. Here is what poked these thoughts in my mind.
I run my Qt application in a thread and that uses QTranslator for language translation.
In one thread I do,
myTranslator->load("English.qm"); qApp->installTranslator(myTranslator);
In the other thread if I do
myTranslator->removeTranslator(myTranslator);
Can some other thread remove my translator? Is it practical. What if QTranslator uses some of static variables that hold some information about translator. To answer all these questions, I need to know if the class is really thread-safe.
I know this is not a great example, but just trying to understand if one thread can update information in other thread.
@kumararajas QTranslator is not thread safe (else it would be mentioned in the documentation). Also I'm wondering why you want to use it in a thread different from the GUI thread? Keep this from documentation in mind:
"Note that the translator must be created before the application's widgets.".There is one very important rule in Qt: do not use UI related classes in threads other than GUI thread!
"Can some other thread remove my translator?" - not sure what you mean. Do you mean the myTranslator variable? If so then it depends whether it is shared across several threads.
-
@jsulm Ya, I know, my example did not made much sense, even for me. I was just thinking about thread safe classes in Qt and lost in a ocean.
I am bit clear now on thread safe abilities in Qt classes. Still I don't have a clear table of classes which are thread safe and which are not. But however depends on application, the class I want to use, I can go to documentation and see if that is thread safe.
Thanks Mr. Moderator ;)
-
@jsulm Ya, I know, my example did not made much sense, even for me. I was just thinking about thread safe classes in Qt and lost in a ocean.
I am bit clear now on thread safe abilities in Qt classes. Still I don't have a clear table of classes which are thread safe and which are not. But however depends on application, the class I want to use, I can go to documentation and see if that is thread safe.
Thanks Mr. Moderator ;)
None of the Qt classes are thread-safe, except where otherwise stated in the docs. In practice the number of fully thread-safe classes is very small - one can probably count them on the fingers of one hand and those are mostly the synchronization primitives (
QMutex
,QSemaphore
, etc.) + some functions here and there -QObject::connect
being a prime example. On the other hand, there is really very little need to have thread-safe classes in the library itself.Then there's the reentrant vs non-reentrant. Most of Qt's classes (utilities, containers,
QObject
, etc.) are reentrant (also noted in the docs) with the major exception of the GUI stuff, which means they don't introduce and/or use statics, and it allows you to use different instances of the same class in different threads. This is usually enough. If you need you can manually sync-up reentrant classes' instances, when working across multiple threads. If the class is not reentrant, then it must be used only from a single thread (as is the case with the GUI).If there's no mention if the class is reentrant and/or thread-safe then you should operate under the assumption that it is neither.
-
That's probably not the answer you are looking for, but I would always add synchronization logic in case you are unsure (or the documentation doesn't provide the necessary information). Adding some synchronization logic is almost always cheap, but prevents you from running into some nasty multithreaded issues.
I am also a big fan of grouping things logically together in one entity (thread). So for example if I need to write/read a file I create a dedicated thread that does the reading and writing. If I need to access the file from another thread, then I notify the file handling thread, which handles the action (read/write) in his own event loop (and eventually signals the result back to the thread that requested the action). In most cases you won't recognize any performance impact due to this. But keeping the logic in one thread often makes it easier to debug/extend. But that's just personal preference (and not really an answer to your question) ;)
@Schluchti said in Thread-safe classes in Qt:
but prevents you from running into some nasty multithreaded issues.
No it doesn't. Try adding synchronization primitives to the GUI classes and watch you program gloriously crash at random places. You can't make Qt's non-reentrant classes thread-safe by adding a few mutexes, as you don't have control over the execution and accesses of the internal's statics through the API.
-
Thank you very much for all the details. It helps me to understand the basics.