[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