On Sun, 2004-09-19 at 02:54, bulia byak wrote:
foo = create_foo(); // create a foo ... // do what we need to do with foo bar->withFoo(foo); // can take its own reference if it needs to ... // do anything else we need to do with foo unref_foo(foo); // we should let go of our reference now
It's the equivalent of the last line that was missing here.
I may misunderstand something, but, if we still need that last line, how it's better than not having a garbage collector at all? Before you needed an explicit free(), now you need an explicit unref() in the same place. If it's still not completely automatic, then what's the gain?
unref() is very diffrent from free() -- it says "destroy this object if nobody else is using it", not just "destroy this object". free() would never have been appropriate there.
That's the way reference counting has always worked. SPDocuments aren't yet managed by the garbage collector.
We will still need reference counting in places where gc-managed memory is referenced by non-gc-managed memory (this is the purpose of Inkscape::GC::Anchored), but only along that boundary. "Within the family", refcounts are no longer needed.
SPRepr is a good example of this: SPObjects, which are not gc-managed, refcount them, but SPReprs no longer need to refcount each other. That has resulted in significant simplification of the SPRepr code, which is the desired advantage.
As more classes come to be managed by the collector, less use of refcounts will be necessary, and we can even use I::G::A less[1].
It still eats memory pretty fast as you go through previews. Maybe slower than before (I haven't measured that before) but not by much. On export, there's no improvement at all (I did measure that before and after).
I think the next problem is that I screwed up and GC_invoke_finalizers() isn't being called in the idle loop like I had intended[2], so Inkscape::GC::Finalized objects never get collected.
One of the few I::G::F-derived classes is SPReprDoc, so obviously that is pretty bad.
It may be simpler to set GC_finalize_on_demand to 0 in Inkscape::GC::init (so finalizers get called immediately), and not bother with GC_invoke_finalizers().
-mental
[1] I::G::A does start with an initial reference count of 1 that you need to "release" (unref), but the requirements are much less stringent than with refcounts -- e.g. this is safe to do (and probably preferred):
using Inkscape::GC::release;
Foo *foo = release(new Foo()); foo->whatever(); ... etc
release() is a little weaker than unref() -- it just means "it's safe for the garbage collector to make a decision about this object". Here, there is no risk of the object being immediately destroyed, since the garbage collector knows you still have a pointer.
Just be sure to Inkscape::GC::anchor() the object if you stick a pointer to it in a place that isn't either a local variable or allocated using the gc-managed allocator.
The only reason I initially anchor I::G::As is that I need it to provide a drop-in replacement for the existing refcounting schemes that all start with an initial refcount of 1 -- e.g. sp_repr_ref() and sp_repr_unref() are now just wrappers for anchor() and release().
[2] I wanted to defer finalizer execution until the idle loop just to be extra conservative. It probably won't hurt if finalizers are called at other times.