[cairo] reference counting vs garbage collection
Olivier Andrieu
oliv__a at users.sourceforge.net
Sun Jan 2 15:48:11 PST 2005
> Keith Packard [Sun, 02 Jan 2005]:
>
> In my nickle binding, I'm creating garbage collected objects that
> wrap cairo surfaces and contexts. This allows me to automatically
> destroy surfaces which are no longer in use.
>
> Cairo doesn't make this easy for some kinds of surfaces though; for
> png and ps surfaces, there is a 'FILE' object which is referenced
> by these surfaces and which must be fclose'd when the surface is
> finally destroyed.
The problem is that such surfaces use two kinds of resources: the
memory (with reference counts) and the FILE*. Garbage collectors
automatically manage memory but not other kind of resources.
There could be two functions I think: _destroy (which should rather be
named _unref) to manage the memory and _close to indicate that the
file resource is not to be used anymore. That's more or less how GTK+
work for instance and it works very well with language bindings. When
_close() is called, cairo would flush file-based surfaces, and set a
flag to indicate nothing should be done on this surface
anymore. _unref() decreases the refcount and when it reaches zero, it
calls _close() and then frees the memory.
That helps separate the management of these two resources. Languages
with GC automate the memory management and the other one is left in
the hands of the programmer.
> Of course, each cairo_t object associated with the surface (either
> as target or pattern) holds a reference to it, so the surface isn't
> really destroyed until the cairo_t objects are also destroyed.
>
> The problem here is that I have no idea which call to
> cairo_surface_destroy actually cleans up the cairo internal state,
> flushing the remaining output to the file and dropping the
> reference to the FILE object.
Why yes, it's the last one ;)
> So, if the surface is finalized before the cairo_t and I fclose the
> file at that point, when the cairo_t gets finalized and the png
> library attempts to write the file, I get a nice segfault.
>
> I don't really know what would work best in this situation; either
> some kind of callback (yuck) when the surface is actually
why `yuck' ? It's a perfectly fine solution (again that's how GTK does
it, with signals).
> destroyed, or some way of knowing whether a call to
> cairo_surface_destroy has actually destroyed the surface might
> work. That would require some care on my part as things like
> cairo_destroy also call cairo_surface_destroy, but I think that
> could work.
>
> What have other garbage collected bindings done in this situation?
When I raised this problem on IRC a couple of months ago, you
suggested to do a :
cairo_set_target_surface (cr, NULL);
That drops the refcount on the underlying surface and so it helps in
knowing when the last ref is dropped. But it's far from perfect. I'm
glad that you're acknowledging there's a problem here :)
--
Olivier
More information about the cairo
mailing list