[cairo] reference counting vs garbage collection

Bill Spitzak spitzak at d2.com
Wed Jan 5 11:44:44 PST 2005


On Wednesday 05 January 2005 11:03 am, Keith Packard wrote:
> Around 13 o'clock on Jan 5, Carl Worth wrote:
> > Regardless, it does seem easy enough to remove the conflation:
> >
> > _create		Allocate object. refcnt = 1. Connect dependent objects
> > _reference	refcnt++
> > _finish		Finalize dependent objects
> > _destroy	if (--refcnt = 0) { _finish; Free object }
>
> (I believe the term 'close' was used instead of 'finish' in the last
> message proposing this design).
>
> This will work just fine for me, but loses some of the symmetry in the
> create/destroy ref/unref model.

It is symmetric, because "unref" and "destroy" are exactly the same function. 
Perhaps one of them can be some kind of alias for the other, by using a macro 
or inline function.

I think also there can be many "finish" functions, quite dependent on the 
class of object. After calling one of them some other subset of methods will 
not work and produce unpredictable results (ie crash), only unref and destroy 
are guaranteed to still work. Because of this normal programs should not call 
the finish function, you have to really know what you are doing to call it. 
You could also do "if refcount==1 finish()" to do it slightly more safely.

Some people are complaining that "finish" should be called "close". In fact 
it can be called anything it wants, it is not a virtual function. There can 
be a whole set of different "finish" functions. For the ones taking a FILE, 
one of them can close, another can flush, another can seek back to the start, 
etc.

I do not think destroy should free data allocated by the caller. This has 
been shown many times to be a very bad idea. Thus the FILE argument that 
started this whole argument should NOT be closed by destroy. However finish 
can do this. In this example the "finish" function (called close to make it 
more clear what it does) is optional. If not called, the file is flushed by 
the destroy, but left open:

FILE* f = fopen(...);
surface = create_png_surface(f);
draw_things(surface);
close_png_surface(surface); // optional, does fclose(file)
destroy(surface);

I know this does not allow reference counting to close the output file, but I 
cannot see any realistic scenario where this is a problem. Can somebody 
explain where this would happen in a real program? It seems most uses of the 
png surface by references would be functions that should continue to work 
after the close, so there is no problem having the creator close it.




More information about the cairo mailing list