Qt-jambi-interest Archive, October 2007
Re: Garbage collection and dispose()
Message 1 in thread
Stephan Egli wrote:
> Hi,
>
> I am reading conflicting information about when to use dispose() and when
> this is not necessary. The jambi demo code contains several dispose()
> calls, however the whitepaper claims, that this is not necessary (even
> for top level widgets). In this mailing list it once was claimed, that it is
> necessary for top level widgets.
>
> So what is the truth ? Under which circumstances is dispose()
> necessary.
Hi Stephan,
Good question ;-) That the documentation is confusing on this point is
something I'll have to forward to our doc team.
The truth is that you strictly don't need it, but in some cases it makes
things "better"... gory details to follow:
QObjects (com.trolltech.qt.core.QObject) in C++ have what we call thread
affinity, which means that they are tied to a given thread. This opens
up things like having multiple event loops running in different threads
and posting events (not only gui) back and forth between objects in them
and things like Queued Connections. On the downside there is one
limitations. A QObject can _only_ be deleted from its own thread.
GC on the other hand runs in a separate thread, so when a QObject is
collected the jvm will tell QtJambi to delete it outside its thread.
Since this is not legal, we have to do some trickery... Qt / C++ has the
concept of deleteLater() (disposeLater in Jambi) where we post an event
to the object which is then delivered in its own, deleting it in a legal
way. This solves deletion, but it does require an event loop to be
running in the objects thread.
Given that you have QApplication.exec() in the main thread, that means
_all_ your widgets will be collected properly. QObjects are only to use
outside the main thread if you are doing event posting and or queued
connections in which case you should be using an event loop and that too
should be fine. We explicitly created QSignalEmitter so that normal
(synchronous) connections could be done without the use of QObject's and
without eventloops running.
The final culprit is that there are some util classes that subclass
QObject, like QFile. When these are used in threads you may see a
warning on the form:
"QFile was deleted outside its thread, use QThread instead".
QThread is a convenience class that guarantees that you spin an
eventloop once, to clean up memory like this, but for simplicity one can
also just call dispose() which is what we do in our examples.
So to sum up. Unless you're using com.trolltech.qt.core.QObject in a
thread you never have to care, and you don't need to use QObject unless
you're doing queued connections or doing non-gui event delivery between
threads. Everything else is collected sooner or later.
> When it is desirable (for efficiency reasons) ?
What we do in dispose is to let you delete the C++ part of an object. So
for instance if you're loading an image from disk, scaling it down to an
icon and passing the icon on, you typically can benefit in performance
from disposing the image afterwards. Simply because it frees the memory
earlier and lets the OS reuse memory instead of allocating big blocks
where only parts are used.
There may also be the point that most of the people working on this are
pretty hardcore C++ guys as well so we think "I don't need this object
anymore, why should I keep it around any longer than I need to" ;-)
> Do I need to
> build up a complete widget tree, where all widgets are connected by
> parent-child relation ? Any help is appreciated...
no, you don't need to do that.
-
I hope this clarifies things,
Gunnar