From ae7dbbce8cbcc3801147d4130a63e0bdf482737f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 15 Oct 2012 21:41:59 -0500 Subject: Some more real hashtable threadsafety in pangofc --- pango/pango-threadsafe.h | 17 +++++++++++++++++ pango/pangofc-fontmap.c | 29 ++++++++++++++++------------- 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 @@ -84,6 +84,23 @@ void p_hash_table_insert (PHashTable *hash_table, g_mutex_unlock (&hash_table->mx); } +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, 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; } -- cgit v1.2.1