Discussion about "Threads, Events and QObjects" article
-
After reading "Reentrancy and Thread-Safety":http://doc.qt.nokia.com/latest/threads-reentrancy.html , I think the term reentrance is not the best choice, because re-entering (in a sense of entering it twice) isn't really possible. (My problem seems to be that I'm familiar with the non-reentrance of MS-DOS.)
Classes that can be safely used by different threads at different times, I would name just safe. To be honest, I would not discuss it at all, but rather mark those that cannot be used from different threads at different times, maybe as "tread-local" or so.
Am I completely wrong here?
-
Hi Wolf,
Thread-local is normally used for members/memory. So there is the "ThreadLocalStorage":http://en.wikipedia.org/wiki/Thread-local_storage for example. "Reentrant":http://en.wikipedia.org/wiki/Reentrant_(subroutine) and "thread-safety":http://en.wikipedia.org/wiki/Thread_safety are general terms (from my understanding) which are widely used. So I would stay with the used terms. -
[quote author="Wolf P." date="1292922748"]
Classes that can be safely used by different threads at different times, I would name just safe. To be honest, I would not discuss it at all, but rather mark those that cannot be used from different threads at different times, maybe as "tread-local" or so.Am I completely wrong here?[/quote]
There are three possible cases:
- Classes/methods/objects/functions/data structures which (...whose instances) can be used at the same time from multiple threads, without the need of serializing cuncurrent accesses. That's what thread-safe means.
- Classes/methods/objects/functions/data structures which (...whose instances) cannot be used at the same time from multiple threads, therefore all accesses must be externally serialized. That's what reentrant means. Notice that
** Thread-safe implies reentrant
** Taking a reentrant class and forcibly serializing all possible accesses with a mutex makes it thread-safe - Classes/methods/objects/functions/data structures which (...whose instances) cannot be used from multiple threads at all. There isn't a specific name for this case (we usually say "not thread-safe nor reentrant"). For instance, QWidget and all of its subclasses are usable only from the main thread.
-
Ok. The term reentrant (in the given context) is now clear to me.
But please note the following example: when you call the Win32 function SendMessage (sending to another process) and get reply-blocked, your process can be re-entered by SendMessage calls from other processes. So, for me, reentrance (in general) has also something to do with recursion.
-
I added a toc to the page. (and to the "wiki syntax help":http://developer.qt.nokia.com/wiki/WikiSyntax too)
-
Unfortunately, the term "reentrancy" is not really clearly defined in computer world.
Michael Suess complains in his "blog entry:"http://www.thinkingparallel.com/2007/06/08/the-most-overused-word-in-parallel-programming-reentrancy/ about the situation. Reading the comments, it seems that there are at least two definitions of reentrancy in the context of single threading (regarding recursive function calls) and in the context of multi threading. This may confuse the people with a single threading background (DOS!) when heading over to multithreaded programming.
Anyways, the definitions are out in the wild and as long as we are in Qt context, we should use the terms defined by the Trolls to avoid further confusion. Otherwise we would need another round of BabelFishing for these kinds of things, but I doubt there's any T-Shirts to win :-)
-
[quote author="Franzk" date="1292935405"][quote author="Volker" date="1292932902"]but I doubt there's any T-Shirts to win :-)[/quote]Huh, imagine T-shirts stating something about your re-entrancy...
[/quote]What a about
"I'm a male - I'm not thread safe!"
[Edit - ok, a bit offtopic now :-) Volker]
-
Qt also requires that all objects living in a thread are deleted before the QThread object that represents the thread is destroyed; this can be easily done by creating all the objects living in that thread on the QThread::run() method’s stack.
Do you mean that
this can be easily done by deleting all the objects living in that thread on the QThread::run() method’s stack.
? -
[quote author="changsheng230" date="1293679684"]Qt also requires that all objects living in a thread are deleted before the QThread object that represents the thread is destroyed; this can be easily done by creating all the objects living in that thread on the QThread::run() method’s stack.
Do you mean that
this can be easily done by deleting all the objects living in that thread on the QThread::run() method’s stack.
?[/quote]No: I mean that if you do
@
MyThread::run()
{
Object obj1, obj2, obj3;
OtherObject foo, bar;
/* ... */
}
@All those objects will:
- be created on run()'s stack;
- be living in the "MyThread" thread;
- get automatically destroyed immediately before run() returns (thus, terminating the thread).
-
There seem to be two copies of this article now. This one: https://developer.qt.nokia.com/wiki/Threads_Events_QObjects has a revision history going back to Pepe's original post on 10 Dec through Alexandra's name change on 10 Feb. This one: https://developer.qt.nokia.com/wiki/ThreadsEventsQObjects was posted by Volker on 23 Feb under the old name. Based on a quick doc compare, I think the content of the two are identical except for the title.
@Volker: are there other changes in your 23 Feb edit that I'm not seeing? I'd like to consolidate the two back to the (new) name.
-
The two articles are identical. My "version" (that without the underscores) is only a link to the actual article. The reason is, that the old version of the link is referred in some other articles and in a blog entry.
Unfortunately it does not redirect to the actual article but pulls in its content and it does not leave a message of doing so.
-
OK, tks. That makes sense. I've wondered about inbound links as we rename articles. I have done a few searches to try and catch broken links, but I know I miss some.
-
Not sure if the documentation has ever been updated, but it's my understanding that subclassing QThread is no longer recommended. http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/
-
That is wrong, it depends, what you are doing...
Me, for example,, I often have worker threads, that do not use signal / slot, but that are waiting on wait conditions and have order queues which are filled by the client via special methods. These threads overwritre run (as the yhave special handling there) and implement synchronisation on their own.
Aslo if you have pre/post conditions in your threads event loop (like COM initialization on Windows), you have to overwrite run. So there are many scenarios where it makes sense...
-
Great article peppe. One area you didn't get into was implicitly shared objects. This is a tricky subject and one that I wrote about before:
http://www.folding-hyperspace.com/program_tip_15.htm
While I don't know if my analysis is absolutely correct, I think this is another area where the official Qt documentation needs improvement. They totally missed that QDateTime is implicitly shared and when I tried using it in threads I found the problem noted above. The same thing applies to list objects like QList. Passing these between threads in signals and slots might be a problem, but I haven't explored this yet. I simply protect all such objects with QMutex and haven't seen any problems.
Also, here is a more complete article I wrote on getting good timing in threads:
http://www.folding-hyperspace.com/program_tip_14.htm
The Qt_RealtimeIO_App example download shows several ways of doing timing and how accurate or inaccurate it can be.
A more complete list of soft realtime related articles is at:
http://www.folding-hyperspace.com/program_tips.htm
I will read your article more carefully in time and see if I can suggest any other improvements.
And I might say it is really fun to program up a big numerical program using QConcurrent and run it on an Intel i7 with 8 cores and watch it speed up x8 times. Qt rocks!