summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2012-10-15 21:41:59 -0500
committerBehdad Esfahbod <behdad@behdad.org>2012-11-07 10:59:04 -0800
commitae7dbbce8cbcc3801147d4130a63e0bdf482737f (patch)
treec51f5e505839dc76998b6feace91df291b9620ac
parent1b705389d7c15f461ebf0460e2b08f982c482667 (diff)
downloadpango-ae7dbbce8cbcc3801147d4130a63e0bdf482737f.tar.gz
Some more real hashtable threadsafety in pangofc
-rw-r--r--pango/pango-threadsafe.h17
-rw-r--r--pango/pangofc-fontmap.c29
2 files changed, 33 insertions, 13 deletions
diff --git a/pango/pango-threadsafe.h b/pango/pango-threadsafe.h
index cf8b4258..57e823d1 100644
--- a/pango/pango-threadsafe.h
+++ b/pango/pango-threadsafe.h
@@ -85,6 +85,23 @@ void p_hash_table_insert (PHashTable *hash_table,
}
static inline
+gboolean p_hash_table_insert_if_null (PHashTable *hash_table,
+ gpointer key,
+ gpointer value)
+{
+ gboolean ret;
+ g_mutex_lock (&hash_table->mx);
+ if (g_hash_table_lookup (hash_table->ht, key))
+ ret = FALSE;
+ else {
+ g_hash_table_insert (hash_table->ht, key, value);
+ ret = TRUE;
+ }
+ g_mutex_unlock (&hash_table->mx);
+ return ret;
+}
+
+static inline
void p_hash_table_replace (PHashTable *hash_table,
gpointer key,
gpointer value)
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 2e031a82..22d9f0c5 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -701,8 +701,8 @@ pango_fc_patterns_new (FcPattern *pat, PangoFcFontMap *fontmap)
FcPatternReference (pat);
pats->pattern = pat;
- p_hash_table_insert (fontmap->priv->patterns_hash,
- pats->pattern, pats);
+ p_hash_table_insert_if_null (fontmap->priv->patterns_hash,
+ pats->pattern, pats);
return pats;
}
@@ -712,7 +712,7 @@ pango_fc_patterns_ref (PangoFcPatterns *pats)
{
g_return_val_if_fail (pats->ref_count > 0, NULL);
- pats->ref_count++;
+ g_atomic_int_inc (&pats->ref_count);
return pats;
}
@@ -722,9 +722,7 @@ pango_fc_patterns_unref (PangoFcPatterns *pats)
{
g_return_if_fail (pats->ref_count > 0);
- pats->ref_count--;
-
- if (pats->ref_count)
+ if (!g_atomic_int_dec_and_test (&pats->ref_count))
return;
/* Only remove from fontmap hash if we are in it. This is not necessarily
@@ -1218,8 +1216,8 @@ pango_fc_font_map_add (PangoFcFontMap *fcfontmap,
key_copy = pango_fc_font_key_copy (key);
_pango_fc_font_set_font_key (fcfont, key_copy);
- /* XXXXXXXXXXX racy here? */
- p_hash_table_insert (priv->font_hash, key_copy, fcfont);
+ if (!p_hash_table_insert_if_null (priv->font_hash, key_copy, fcfont))
+ pango_fc_font_key_free (key_copy);
}
/* Remove mapping from fcfont->key to fcfont */
@@ -1509,7 +1507,6 @@ uniquify_pattern (PangoFcFontMap *fcfontmap,
PangoFcFontMapPrivate *priv = fcfontmap->priv;
FcPattern *old_pattern;
- /* XXXXXX racy here? */
old_pattern = p_hash_table_lookup (priv->pattern_hash, pattern);
if (old_pattern)
{
@@ -1518,7 +1515,8 @@ uniquify_pattern (PangoFcFontMap *fcfontmap,
else
{
FcPatternReference (pattern);
- p_hash_table_insert (priv->pattern_hash, pattern, pattern);
+ if (!p_hash_table_insert_if_null (priv->pattern_hash, pattern, pattern))
+ FcPatternDestroy (pattern);
return pattern;
}
}
@@ -1766,7 +1764,8 @@ pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
return NULL;
fontset = pango_fc_fontset_new (&key, patterns);
- p_hash_table_insert (priv->fontset_hash, pango_fc_fontset_get_key (fontset), g_object_ref (fontset));
+ if (!p_hash_table_insert_if_null (priv->fontset_hash, pango_fc_fontset_get_key (fontset), g_object_ref (fontset)))
+ g_object_unref (fontset);
pango_fc_patterns_unref (patterns);
}
@@ -1814,7 +1813,7 @@ pango_fc_font_map_get_font_face_data (PangoFcFontMap *fcfontmap,
if (FcPatternGetInteger (font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
return NULL;
- /* XXXXXXXXXX racy here */
+retry:
data = p_hash_table_lookup (priv->font_face_data_hash, &key);
if (G_LIKELY (data))
return data;
@@ -1826,7 +1825,11 @@ pango_fc_font_map_get_font_face_data (PangoFcFontMap *fcfontmap,
data->pattern = font_pattern;
FcPatternReference (data->pattern);
- p_hash_table_insert (priv->font_face_data_hash, data, data);
+ if (!p_hash_table_insert_if_null (priv->font_face_data_hash, data, data))
+ {
+ pango_fc_font_face_data_free (data);
+ goto retry;
+ }
return data;
}