Trolltech Home | Qt-jambi-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

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