[PATCH] [cairo-atomic] Use atomic reference counting.

Chris Wilson chris at chris-wilson.co.uk
Fri Sep 21 14:22:02 PDT 2007


Replace all manipulation of object ref_counts with the equivalent atomic
operations.
---
 src/cairo-clip.c         |    6 ++--
 src/cairo-font-face.c    |   21 ++++-----------
 src/cairo-pattern.c      |    6 ++--
 src/cairo-scaled-font.c  |   62 ++++++++++++++++++++-------------------------
 src/cairo-surface.c      |    8 +++---
 src/cairo-xlib-display.c |   41 ++++++++++++++----------------
 src/cairo-xlib-screen.c  |    5 ++-
 src/cairo.c              |    6 ++--
 8 files changed, 69 insertions(+), 86 deletions(-)

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index c9ad85e..de49674 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -38,6 +38,7 @@
  */
 
 #include "cairoint.h"
+#include "cairo-atomic-private.h"
 #include "cairo-clip-private.h"
 
 static cairo_clip_path_t *
@@ -301,7 +302,7 @@ _cairo_clip_path_reference (cairo_clip_path_t *clip_path)
     if (clip_path == NULL)
 	return NULL;
 
-    clip_path->ref_count++;
+    _cairo_atomic_inc (&clip_path->ref_count);
 
     return clip_path;
 }
@@ -312,8 +313,7 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
     if (clip_path == NULL)
 	return;
 
-    clip_path->ref_count--;
-    if (clip_path->ref_count)
+    if (! _cairo_atomic_dec_and_test (&clip_path->ref_count))
 	return;
 
     _cairo_path_fixed_fini (&clip_path->path);
diff --git a/src/cairo-font-face.c b/src/cairo-font-face.c
index 3b6dab3..e935241 100644
--- a/src/cairo-font-face.c
+++ b/src/cairo-font-face.c
@@ -39,6 +39,7 @@
  */
 
 #include "cairoint.h"
+#include "cairo-atomic-private.h"
 
 /* Forward declare so we can use it as an arbitrary backend for
  * _cairo_font_face_nil.
@@ -88,15 +89,11 @@ cairo_font_face_reference (cairo_font_face_t *font_face)
     if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
 	return font_face;
 
-    CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
-
     /* We would normally assert (font_face->ref_count >0) here but we
      * can't get away with that due to the zombie case as documented
      * in _cairo_ft_font_face_destroy. */
 
-    font_face->ref_count++;
-
-    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
+    _cairo_atomic_inc (&font_face->ref_count);
 
     return font_face;
 }
@@ -116,16 +113,10 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
     if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
 	return;
 
-    CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
-
     assert (font_face->ref_count > 0);
 
-    if (--(font_face->ref_count) > 0) {
-        CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
+    if (! _cairo_atomic_dec_and_test (&font_face->ref_count))
 	return;
-    }
-
-    CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
 
     font_face->backend->destroy (font_face);
 
@@ -395,7 +386,7 @@ _cairo_toy_font_face_create (const char          *family,
     {
 	/* We increment the reference count here manually to avoid
 	   double-locking. */
-	font_face->base.ref_count++;
+	_cairo_atomic_inc (&font_face->base.ref_count);
 	_cairo_toy_font_face_hash_table_unlock ();
 	return &font_face->base;
     }
@@ -485,7 +476,7 @@ _cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
     if (unscaled_font == NULL)
 	return NULL;
 
-    unscaled_font->ref_count++;
+    _cairo_atomic_inc (&unscaled_font->ref_count);
 
     return unscaled_font;
 }
@@ -496,7 +487,7 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
     if (unscaled_font == NULL)
 	return;
 
-    if (--(unscaled_font->ref_count) > 0)
+    if (! _cairo_atomic_dec_and_test (&unscaled_font->ref_count))
 	return;
 
     unscaled_font->backend->destroy (unscaled_font);
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index b75040b..c68ba01 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -29,6 +29,7 @@
  */
 
 #include "cairoint.h"
+#include "cairo-atomic-private.h"
 
 const cairo_solid_pattern_t _cairo_pattern_nil = {
     { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
@@ -582,7 +583,7 @@ cairo_pattern_reference (cairo_pattern_t *pattern)
 
     assert (pattern->ref_count > 0);
 
-    pattern->ref_count++;
+    _cairo_atomic_inc (&pattern->ref_count);
 
     return pattern;
 }
@@ -639,8 +640,7 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
 
     assert (pattern->ref_count > 0);
 
-    pattern->ref_count--;
-    if (pattern->ref_count)
+    if (! _cairo_atomic_dec_and_test (&pattern->ref_count))
 	return;
 
     _cairo_pattern_fini (pattern);
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index cb3af9f..b53c92f 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -38,6 +38,7 @@
  */
 
 #include "cairoint.h"
+#include "cairo-atomic-private.h"
 #include "cairo-scaled-font-private.h"
 
 /*
@@ -635,7 +636,7 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
 	     * than calling into cairo_scaled_font_reference), since we
 	     * must modify the reference count while our lock is still
 	     * held. */
-	    scaled_font->ref_count++;
+	    _cairo_atomic_inc (&scaled_font->ref_count);
 	    _cairo_scaled_font_map_unlock ();
 	    return scaled_font;
 	}
@@ -689,13 +690,9 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
     if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
 	return scaled_font;
 
-    _cairo_scaled_font_map_lock ();
-    {
-	assert (scaled_font->ref_count > 0);
+    assert (scaled_font->ref_count > 0);
 
-	scaled_font->ref_count++;
-    }
-    _cairo_scaled_font_map_unlock ();
+    _cairo_atomic_inc (&scaled_font->ref_count);
 
     return scaled_font;
 }
@@ -715,38 +712,35 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
     cairo_scaled_font_map_t *font_map;
     cairo_scaled_font_t *lru = NULL;
 
-    if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
+    if (scaled_font == NULL ||
+	    scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
 	return;
 
+    assert (font_map != NULL);
+    assert (scaled_font->ref_count > 0);
+
     font_map = _cairo_scaled_font_map_lock ();
-    {
-	assert (font_map != NULL);
-
-	assert (scaled_font->ref_count > 0);
-
-	if (--(scaled_font->ref_count) == 0)
-	{
-	    /* Rather than immediately destroying this object, we put it into
-	     * the font_map->holdovers array in case it will get used again
-	     * soon. To make room for it, we do actually destroy the
-	     * least-recently-used holdover.
-	     */
-	    if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS)
-	    {
-		lru = font_map->holdovers[0];
-		assert (lru->ref_count == 0);
-
-		_cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);
-
-		font_map->num_holdovers--;
-		memmove (&font_map->holdovers[0],
-			 &font_map->holdovers[1],
-			 font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
-	    }
+    if (_cairo_atomic_dec_and_test (&scaled_font->ref_count)) {
+	/* Rather than immediately destroying this object, we put it
+	 * into the font_map->holdovers array in case it will get used
+	 * again soon. To make room for it, we do actually destroy the
+	 * least-recently-used holdover.
+	 */
+	if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) {
+	    lru = font_map->holdovers[0];
+	    assert (lru->ref_count == 0);
+
+	    _cairo_hash_table_remove (font_map->hash_table,
+				      &lru->hash_entry);
 
-	    font_map->holdovers[font_map->num_holdovers] = scaled_font;
-	    font_map->num_holdovers++;
+	    font_map->num_holdovers--;
+	    memmove (&font_map->holdovers[0],
+		     &font_map->holdovers[1],
+		     font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
 	}
+
+	font_map->holdovers[font_map->num_holdovers] = scaled_font;
+	font_map->num_holdovers++;
     }
     _cairo_scaled_font_map_unlock ();
 
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 612d8cf..c222fd5 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -38,8 +38,9 @@
 
 #include "cairoint.h"
 
-#include "cairo-surface-fallback-private.h"
+#include "cairo-atomic-private.h"
 #include "cairo-clip-private.h"
+#include "cairo-surface-fallback-private.h"
 
 #define DEFINE_NIL_SURFACE(status, name)			\
 const cairo_surface_t name = {					\
@@ -377,7 +378,7 @@ cairo_surface_reference (cairo_surface_t *surface)
 
     assert (surface->ref_count > 0);
 
-    surface->ref_count++;
+    _cairo_atomic_inc (&surface->ref_count);
 
     return surface;
 }
@@ -399,8 +400,7 @@ cairo_surface_destroy (cairo_surface_t *surface)
 
     assert (surface->ref_count > 0);
 
-    surface->ref_count--;
-    if (surface->ref_count)
+    if (! _cairo_atomic_dec_and_test (&surface->ref_count))
 	return;
 
     if (! surface->finished)
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index 5d4f339..195e3c2 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -33,6 +33,7 @@
 
 #include "cairoint.h"
 
+#include "cairo-atomic-private.h"
 #include "cairo-xlib-private.h"
 
 #include <fontconfig/fontconfig.h>
@@ -127,13 +128,8 @@ _cairo_xlib_display_reference (cairo_xlib_display_t *display)
     if (display == NULL)
 	return NULL;
 
-    /* use our mutex until we get a real atomic inc */
-    CAIRO_MUTEX_LOCK (display->mutex);
-
     assert (display->ref_count > 0);
-    display->ref_count++;
-
-    CAIRO_MUTEX_UNLOCK (display->mutex);
+    _cairo_atomic_inc (&display->ref_count);
 
     return display;
 }
@@ -144,27 +140,28 @@ _cairo_xlib_display_destroy (cairo_xlib_display_t *display)
     if (display == NULL)
 	return;
 
-    CAIRO_MUTEX_LOCK (display->mutex);
     assert (display->ref_count > 0);
-    if (--display->ref_count == 0) {
-	/* destroy all outstanding notifies */
-	while (display->workqueue != NULL) {
-	    cairo_xlib_job_t *job = display->workqueue;
-	    display->workqueue = job->next;
+    if (! _cairo_atomic_dec_and_test (&display->ref_count))
+	return;
 
-	    if (job->type == WORK && job->func.work.destroy != NULL)
-		job->func.work.destroy (job->func.work.data);
+    CAIRO_MUTEX_LOCK (display->mutex);
+    /* destroy all outstanding notifies */
+    while (display->workqueue != NULL) {
+	cairo_xlib_job_t *job = display->workqueue;
+	display->workqueue = job->next;
 
-	    _cairo_freelist_free (&display->wq_freelist, job);
-	}
-	_cairo_freelist_fini (&display->wq_freelist);
-	_cairo_freelist_fini (&display->hook_freelist);
+	if (job->type == WORK && job->func.work.destroy != NULL)
+	    job->func.work.destroy (job->func.work.data);
 
-	CAIRO_MUTEX_UNLOCK (display->mutex);
+	_cairo_freelist_free (&display->wq_freelist, job);
+    }
+    _cairo_freelist_fini (&display->wq_freelist);
+    _cairo_freelist_fini (&display->hook_freelist);
 
-	free (display);
-    } else
-	CAIRO_MUTEX_UNLOCK (display->mutex);
+    CAIRO_MUTEX_UNLOCK (display->mutex);
+    CAIRO_MUTEX_FINI (display->mutex);
+
+    free (display);
 }
 
 static int
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 88f0899..3971011 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -54,6 +54,7 @@
 
 #include "cairoint.h"
 
+#include "cairo-atomic-private.h"
 #include "cairo-xlib-private.h"
 
 #include <fontconfig/fontconfig.h>
@@ -247,7 +248,7 @@ _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
 	return NULL;
 
     assert (info->ref_count > 0);
-    info->ref_count++;
+    _cairo_atomic_inc (&info->ref_count);
 
     return info;
 }
@@ -275,7 +276,7 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
 	return;
 
     assert (info->ref_count > 0);
-    if (--info->ref_count)
+    if (! _cairo_atomic_dec_and_test (&info->ref_count))
 	return;
 
     CAIRO_MUTEX_LOCK (info->display->mutex);
diff --git a/src/cairo.c b/src/cairo.c
index ff052b5..54dcb54 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -40,6 +40,7 @@
 #include "cairo-private.h"
 
 #include "cairo-arc-private.h"
+#include "cairo-atomic-private.h"
 #include "cairo-path-private.h"
 
 #define CAIRO_TOLERANCE_MINIMUM	0.0002 /* We're limited by 16 bits of sub-pixel precision */
@@ -237,7 +238,7 @@ cairo_reference (cairo_t *cr)
 
     assert (cr->ref_count > 0);
 
-    cr->ref_count++;
+    _cairo_atomic_inc (&cr->ref_count);
 
     return cr;
 }
@@ -258,8 +259,7 @@ cairo_destroy (cairo_t *cr)
 
     assert (cr->ref_count > 0);
 
-    cr->ref_count--;
-    if (cr->ref_count)
+    if (! _cairo_atomic_dec_and_test (&cr->ref_count))
 	return;
 
     while (cr->gstate != cr->gstate_tail) {
-- 
1.4.4.2


--dWYAkE0V1FpFQHQ3--


More information about the cairo mailing list