[cairo-commit] src/cairo.c src/cairo-debug.c src/cairoint.h src/cairo-mutex-list-private.h
Chris Wilson
ickle at kemper.freedesktop.org
Sat Jun 12 02:47:20 PDT 2010
src/cairo-debug.c | 2 +
src/cairo-mutex-list-private.h | 1
src/cairo.c | 76 +++++++++++++++++++++++++++++++++++------
src/cairoint.h | 3 +
4 files changed, 71 insertions(+), 11 deletions(-)
New commits:
commit 9b7cc7641b691a3b9e3d5edd51053c9a095d9c5a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Jun 12 10:41:09 2010 +0100
cairo: Create error objects for cairo_t
Perform an early check for error status and prevent creation of a full
object. This means that we do not pass down error objects to the
initialisation routines and so can survive without paranoia inside the
library. It also has brings consistency that like the other
constructors, no object is created in error and we can skip the
cairo_destroy() if we choose (and we don't waste one of the precious
zero-alloc context slots.
Fixes crash in test/a8-mask introduced by 1a544361e845.
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 05ca16e..712ce93 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -81,6 +81,8 @@ cairo_debug_reset_static_data (void)
_cairo_drm_device_reset_static_data ();
#endif
+ _cairo_reset_static_data ();
+
CAIRO_MUTEX_FINALIZE ();
}
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index 29ffd04..5827667 100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -40,6 +40,7 @@ CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
CAIRO_MUTEX_DECLARE (_cairo_image_solid_cache_mutex)
+CAIRO_MUTEX_DECLARE (_cairo_error_mutex)
CAIRO_MUTEX_DECLARE (_cairo_toy_font_face_mutex)
CAIRO_MUTEX_DECLARE (_cairo_intern_string_mutex)
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
diff --git a/src/cairo.c b/src/cairo.c
index b2a3a7b..9d28aee 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -221,6 +221,61 @@ _context_put (cairo_t *cr)
#define _context_put(cr) free (cr)
#endif
+/* XXX This should disappear in favour of a common pool of error objects. */
+static cairo_t *_cairo_nil__objects[CAIRO_STATUS_LAST_STATUS + 1];
+
+static cairo_t *
+_cairo_create_in_error (cairo_status_t status)
+{
+ cairo_t *cr;
+
+ assert (status != CAIRO_STATUS_SUCCESS);
+
+ /* special case OOM in order to avoid another allocation */
+ switch ((int) status) {
+ case CAIRO_STATUS_NO_MEMORY:
+ return (cairo_t *) &_cairo_nil;
+ case CAIRO_STATUS_NULL_POINTER:
+ return (cairo_t *) &_cairo_nil__null_pointer;
+ }
+
+ CAIRO_MUTEX_LOCK (_cairo_error_mutex);
+ cr = _cairo_nil__objects[status];
+ if (cr == NULL) {
+ cr = malloc (sizeof (cairo_t));
+ if (unlikely (cr == NULL)) {
+ CAIRO_MUTEX_UNLOCK (_cairo_error_mutex);
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_t *) &_cairo_nil;
+ }
+
+ *cr = _cairo_nil;
+ cr->status = status;
+ _cairo_nil__objects[status] = cr;
+ }
+ CAIRO_MUTEX_UNLOCK (_cairo_error_mutex);
+
+ return cr;
+}
+
+void
+_cairo_reset_static_data (void)
+{
+ int status;
+
+ CAIRO_MUTEX_LOCK (_cairo_error_mutex);
+ for (status = CAIRO_STATUS_SUCCESS;
+ status <= CAIRO_STATUS_LAST_STATUS;
+ status++)
+ {
+ if (_cairo_nil__objects[status] != NULL) {
+ free (_cairo_nil__objects[status]);
+ _cairo_nil__objects[status] = NULL;
+ }
+ }
+ CAIRO_MUTEX_UNLOCK (_cairo_error_mutex);
+}
+
/**
* cairo_create:
* @target: target surface for the context
@@ -250,17 +305,14 @@ cairo_create (cairo_surface_t *target)
cairo_t *cr;
cairo_status_t status;
- /* special case OOM in order to avoid another allocation */
- if (target == NULL)
- return (cairo_t *) &_cairo_nil__null_pointer;
- if (target->status == CAIRO_STATUS_NO_MEMORY)
- return (cairo_t *) &_cairo_nil;
+ if (unlikely (target == NULL))
+ return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
+ if (unlikely (target->status))
+ return _cairo_create_in_error (target->status);
cr = _context_get ();
- if (unlikely (cr == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return (cairo_t *) &_cairo_nil;
- }
+ if (unlikely (cr == NULL))
+ return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
CAIRO_REFERENCE_COUNT_INIT (&cr->ref_count, 1);
@@ -274,8 +326,10 @@ cairo_create (cairo_surface_t *target)
cr->gstate_tail[1].next = NULL;
status = _cairo_gstate_init (cr->gstate, target);
- if (unlikely (status))
- _cairo_set_error (cr, status);
+ if (unlikely (status)) {
+ _context_put (cr);
+ cr = _cairo_create_in_error (status);
+ }
return cr;
}
diff --git a/src/cairoint.h b/src/cairoint.h
index 014f0ba..b3deee9 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -389,6 +389,9 @@ struct _cairo_font_face {
};
cairo_private void
+_cairo_reset_static_data (void);
+
+cairo_private void
_cairo_toy_font_face_reset_static_data (void);
cairo_private void
More information about the cairo-commit
mailing list