summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2005-09-13 12:28:00 +0000
committerCarl Worth <cworth@cworth.org>2005-09-13 12:28:00 +0000
commit36f4bb98371a3a81ccc6ccf6f3295b9e48e8c8c9 (patch)
tree8875c42aa2887c2e745be34c478d2b5fb16d80f6
parent33820b04759582334fb725962aa3fff8bdd44584 (diff)
Expand locking to encapsulate any modification to the reference count of a scaled font, rather than just modifcations of the scaled_font_map, since scaled fonts are shared between threads.
-rw-r--r--ChangeLog8
-rw-r--r--src/cairo-font.c85
2 files changed, 56 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index fb23c3594..d22770a41 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2005-09-13 Carl Worth <cworth@cworth.org>
+ * src/cairo-scaled-font.c: (cairo_scaled_font_reference),
+ (cairo_scaled_font_destroy): Expand locking to encapsulate any
+ modification to the reference count of a scaled font, rather than
+ just modifcations of the scaled_font_map, since scaled fonts are
+ shared between threads.
+
+2005-09-13 Carl Worth <cworth@cworth.org>
+
* test/cairo-test.h: Add documentation for cairo_test functions.
* test/cairo-test.c: (cairo_test_init), (cairo_test_expecting):
diff --git a/src/cairo-font.c b/src/cairo-font.c
index b228f2850..e46ba5e72 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -762,6 +762,8 @@ UNWIND:
cairo_scaled_font_t *
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
{
+ cairo_scaled_font_map_t *font_map;
+
if (scaled_font == NULL)
return NULL;
@@ -772,16 +774,19 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
* we are using ref_count == 0 as a legitimate case for the
* holdovers array. See below. */
- /* If the original reference count is 0, then this font must have
- * been found in font_map->holdovers, (which means this caching is
- * actually working). So now we remove it from the holdovers
- * array. */
- if (scaled_font->ref_count == 0) {
- cairo_scaled_font_map_t *font_map;
- int i;
+ /* cairo_scaled_font_t objects are cached and shared between
+ * threads. This works because these objects are immutable. Except
+ * that the reference count is mutable, so we have to do locking
+ * around any modification of the reference count. */
+ font_map = _cairo_scaled_font_map_lock ();
+ {
+ /* If the original reference count is 0, then this font must have
+ * been found in font_map->holdovers, (which means this caching is
+ * actually working). So now we remove it from the holdovers
+ * array. */
+ if (scaled_font->ref_count == 0) {
+ int i;
- font_map = _cairo_scaled_font_map_lock ();
- {
for (i = 0; i < font_map->num_holdovers; i++)
if (font_map->holdovers[i] == scaled_font)
break;
@@ -792,10 +797,11 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
&font_map->holdovers[i+1],
(font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
}
- _cairo_scaled_font_map_unlock ();
- }
- scaled_font->ref_count++;
+ scaled_font->ref_count++;
+
+ }
+ _cairo_scaled_font_map_unlock ();
return scaled_font;
}
@@ -819,38 +825,43 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
if (scaled_font->ref_count == (unsigned int)-1)
return;
- assert (scaled_font->ref_count > 0);
-
- if (--(scaled_font->ref_count) > 0)
- return;
-
+ /* cairo_scaled_font_t objects are cached and shared between
+ * threads. This works because these objects are immutable. Except
+ * that the reference count is mutable, so we have to do locking
+ * around any modification of the reference count. */
font_map = _cairo_scaled_font_map_lock ();
- assert (font_map != NULL);
{
- /* 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) {
- cairo_scaled_font_t *lru;
+ assert (font_map != NULL);
+
+ assert (scaled_font->ref_count > 0);
- lru = font_map->holdovers[0];
- assert (lru->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) {
+ cairo_scaled_font_t *lru;
+
+ lru = font_map->holdovers[0];
+ assert (lru->ref_count == 0);
- _cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);
+ _cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);
- _cairo_scaled_font_fini (lru);
- free (lru);
+ _cairo_scaled_font_fini (lru);
+ free (lru);
- font_map->num_holdovers--;
- memmove (&font_map->holdovers[0],
- &font_map->holdovers[1],
- font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
- }
+ 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++;
+ font_map->holdovers[font_map->num_holdovers] = scaled_font;
+ font_map->num_holdovers++;
+ }
}
_cairo_scaled_font_map_unlock ();
}