[cairo] API Shakeup: Consistent error handling for all objects

Carl Worth cworth at cworth.org
Wed Feb 23 13:56:28 PST 2005


(I knew I'd remember a topic or too just as soon as I said I was
done).

Owen already mentioned this once in passing, but I wanted to start an
API Shakeup thread on the topic.

I propose making all objects in cairo use an error handling scheme
similar to cairo_t. That is, rather than each function returning
cairo_status_t, most functions are void and error state is stored in
the object itself, (and can be queried). An object in an error state
is inert, and functions can be safely called on it with no side
effects.

Additionally, I propose to extend the current scheme so that all create
functions are also guaranteed to "work". That is, in the case of
out-of-memory, the functions will return a pointer to a static
in-error object.

This scheme has advantages to both users of cairo, and for the
implementation of cairo itself. Functions that currently look have
nasty patterns like:

	status = STATUS_SUCCESS;

	status = foo0 (...);
	if (status != STATUS_SUCCESS)
		goto BAIL0;

	status = foo1 (...);
	if (status != STATUS_SUCCESS)
		goto BAIL1;

	/* ... */

	BAIL1:
	cleanup_foo1 (...);

	BAIL0:
	cleanup_foo0 (...);

	return status;

will now get to look much nicer:

	foo0 (...);
	foo1 (...);

	/* ... */

	cleanup_foo1 (...);
	cleanup_foo0 (...);

	return;

And actual checks for status can be pushed to interface boundaries
within the cairo implementation, (and wherever most convenient within
application code).

I haven't implemented all of this, so I'm not sure it won't fall apart
at some point, but I am optimistic it will work quite well.

There are some classes of operations which do not fit well with this
model. For instance, calling cairo_surface_set_user_data on an inert
surface, and assuming you'll get a destroy notify at some point in the
future will not work, (since the inert object cannot save the
data). Immediately calling the destroy notifier might actually work,
but doesn't seem a good idea. It will probably be best to just make
set_user_data be one of the few functions that can fail.

-Carl

PS. As I went to implement the placeholder objects for the
out-of-memory case, I considered naming them "nil", as in
cairo_surface_nil. As I did so, I thought I might do a quick check of
the use of "nil" in other languages. On of the first results I found
was a March 2000, Smalltalk Chronicles article by Nevin Pratt:

	A Generalized Null Object Pattern
	http://www.smalltalkchronicles.net/edition2-1/null_object_pattern.htm

which introduces what he calls the "message-eating nil" of
Objective-C, and his implementation of a similar pattern in
Smalltalk. Interestingly, the results are quite similar to what we're
proposing here. And, amusingly enough, since Smalltalk already had a
nil, he named his new thing "null", (where I chose "nil" since C
already has NULL).

	


	
		
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050223/f4b64e2b/attachment.pgp


More information about the cairo mailing list