diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2012-10-15 21:41:59 -0500 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2012-11-07 10:59:04 -0800 |
commit | ae7dbbce8cbcc3801147d4130a63e0bdf482737f (patch) | |
tree | c51f5e505839dc76998b6feace91df291b9620ac | |
parent | 1b705389d7c15f461ebf0460e2b08f982c482667 (diff) | |
download | pango-ae7dbbce8cbcc3801147d4130a63e0bdf482737f.tar.gz |
Some more real hashtable threadsafety in pangofc
-rw-r--r-- | pango/pango-threadsafe.h | 17 | ||||
-rw-r--r-- | 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 @@ -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; } |