[Kde-bindings] playground/bindings/kimono

Arno Rehn arno at arnorehn.de
Tue Mar 6 18:31:12 UTC 2007


Am Dienstag, 6. März 2007 schrieb Richard Dale:
> On Tuesday 06 March 2007, Arno Rehn wrote:
> > Am Dienstag, 6. März 2007 schrieb Richard Dale:
> > > On Tuesday 06 March 2007, Arno Rehn wrote:
> > > > Am Montag, 5. März 2007 schrieb Richard Dale:
> > > > > So the 'internalPointer' has a different value even when the
> > > > > underlying instance is the same. That's because
> > > > > QAbstractItemModel.CreateIndex() allocates a new GCHandle every
> > > > > time, which will have different values. The reason it works in
> > > > > QtRuby is because the internalPointer is a Ruby VALUE that is  the
> > > > > same for every createIndex call.
> > > >
> > > > Ah tanks. I added a Dictionary where all the GCHandles for
> > > > QModelIndex'es are stored. This GCHandle is looked up for the
> > > > specific QModelIndex and then passed to the C++ helper function.
> > > > Selecting child items is no problem anymore. Up to now I thought
> > > > GCHandle.Alloc() returns always the same value, but apparently it
> > > > doesn't.
> > >
> > > I thought about have a WeakReference as a key, but I don't think that
> > > works because wrapping an instance in a GCHandle will probably create a
> > > strong reference (you wouldn't want an instance to be GC'd while you
> > > were referencing it in C code).
> >
> > Yes, that's right, but than we just need to change the WeakReference to a
> > normal, 'strong' reference.
> >
> > > So I think you need to have the actual object as a key, and a struct as
> > > a value with two fields; a reference count and a GCHandle. When you add
> > > a new GCHandle, set the ref count to 1 and increment every time the
> > > handle is reused in another QModelIndex. Then in the QModelIndex
> > > destructor, retrieve the entry for the wrapped object and decrement the
> > > ref count. If the ref count is then zero, delete the entry.
> >
> > That won't work, I think, because the destructor is only called
> > automatically, when the object is GC'd. And as long as there is a strong
> > reference, the object won't be GC'd, so the destrcutor is never called.
> > Hence, the only case in which a destructor is called is when you have
> > something like
> > using (QModelIndex index = CreateIndex(...)) {
> >       // code
> > }
>
> No, there won't be a reference to the QModelIndex in the dictionary to
> prevent it being GC'd, only to the thing inside the 'internalPointer' (ie
> TreeItem or similar).
But there will be a reference inside the GCHandle, you yourself said
'wrapping an instance in a GCHandle will probably create a strong reference 
(you wouldn't want an instance to be GC'd while you were referencing it in C 
code).'
That would mean by creating a GCHandle to be stored in somewhere, we 
automatically create a strong reference to the object and thus prevent it 
from being GC'd. Without the GC calling the destructor of the object, we 
can't decrement anything. MSDN says the following to the GCHandleTypes:

Normal (default):
[...] You can use this type to track an object and prevent its collection by 
the garbage collector. [...]

Weak:
This handle type is used to track an object, but allow it to be collected. 
[...]

That means, we could create a GCHandle with GCHandleType.Weak but there would 
be a danger of the object being GC'd while it is in use by C code (even 
though the probability of this is very small, I think).
If we use GCHandleType.Weak, we can keep the code as it is at the moment, 
since nothing would prevent the GC from collecting the QModelIndex and if the 
weakRef is Zero ( = the object was collected) the entry is deleted.

I hope we don't talk cross-purposes.

> > After that the instance is gone, and then it wouldn't make sense anymore
> > to decrement some counter, because the instance was deleted anyway.
> >
> > I think the current way is OK, because we can easily check if the
> > instance is still alive (e.g. in the above example with using(...) {...}
> > it may have been deleted) and if not, we can just delete the entry in the
> > Dictionary. The WeakReference is just as good as a strong reference for
> > this kind of doings and provides us with IsAlive a useful property.
>
> The key WeakReference will always be alive because the value has a GCHandle
> wrapping the key.
Oops, ok, that's right.


-- 
Arno Rehn
arno at arnorehn.de



More information about the Kde-bindings mailing list