[pango/threadsafe-failed-attempt: 1/11] Add a threadsafe hashtable and use it in pangofc-fontmap



commit bdec39afb41471e7ebc86122239741a819e4a8b3
Author: Behdad Esfahbod <behdad behdad org>
Date:   Mon Oct 15 17:58:55 2012 -0500

    Add a threadsafe hashtable and use it in pangofc-fontmap
    
    Inching our way closer to threadsafe pangofc.

 configure.in             |    2 +
 pango/Makefile.am        |    3 +-
 pango/pango-threadsafe.h |  128 ++++++++++++++++++++++++++++++++++++++++++++++
 pango/pangofc-fontmap.c  |   63 +++++++++++-----------
 tests/Makefile.am        |    5 +-
 5 files changed, 167 insertions(+), 34 deletions(-)
---
diff --git a/configure.in b/configure.in
index a0e0057..26c775e 100644
--- a/configure.in
+++ b/configure.in
@@ -469,6 +469,8 @@ AC_SUBST(GLIB_MKENUMS)
 # Add in gthread-2.0 to CFLAGS but not to LIBS so we get any
 # necesary defines for thread-safety.
 GLIB_CFLAGS=`$PKG_CONFIG --cflags $GLIB_MODULES gthread-2.0`
+GTHREAD_LIBS=`$PKG_CONFIG --libs $GLIB_MODULES gthread-2.0`
+AC_SUBST(GTHREAD_LIBS)
 
 #
 # Checks for LibThai
diff --git a/pango/Makefile.am b/pango/Makefile.am
index ab092c9..1387b78 100644
--- a/pango/Makefile.am
+++ b/pango/Makefile.am
@@ -89,8 +89,9 @@ libpango_1_0_la_SOURCES =			\
 	pango-renderer.c			\
 	pango-script.c				\
 	pango-script-lang-table.h		\
-	pango-script-private.h				\
+	pango-script-private.h			\
 	pango-tabs.c				\
+	pango-threadsafe.h			\
 	pango-utils.c				\
 	reorder-items.c				\
 	shape.c					\
diff --git a/pango/pango-threadsafe.h b/pango/pango-threadsafe.h
new file mode 100644
index 0000000..c4abd68
--- /dev/null
+++ b/pango/pango-threadsafe.h
@@ -0,0 +1,128 @@
+/* Pango
+ * pango-threadsafe.h: Thread-safe alternatives of glib datastructures
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Google author(s): Behdad Esfahbod
+ */
+
+#ifndef __PANGO_THREADSAFE_H__
+#define __PANGO_THREADSAFE_H__
+
+#include <glib.h>
+#include <pango/pango.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PHashTable {
+  GHashTable *ht;
+  GMutex mx;
+} PHashTable;
+
+
+static inline
+PHashTable* p_hash_table_new               (GHashFunc       hash_func,
+                                            GEqualFunc      key_equal_func)
+{
+  PHashTable *p = g_slice_new0 (PHashTable);
+
+  p->ht = g_hash_table_new (hash_func, key_equal_func);
+
+  return p;
+}
+
+static inline
+PHashTable* p_hash_table_new_full          (GHashFunc       hash_func,
+                                            GEqualFunc      key_equal_func,
+                                            GDestroyNotify  key_destroy_func,
+                                            GDestroyNotify  value_destroy_func)
+{
+  PHashTable *p = g_slice_new0 (PHashTable);
+
+  p->ht = g_hash_table_new_full (hash_func,
+				 key_equal_func,
+				 key_destroy_func,
+				 value_destroy_func);
+
+  return p;
+}
+
+static inline
+void        p_hash_table_destroy           (PHashTable     *hash_table)
+{
+  g_hash_table_destroy (hash_table->ht);
+  g_mutex_clear (&hash_table->mx);
+  g_slice_free (PHashTable, hash_table);
+}
+
+static inline
+void        p_hash_table_insert            (PHashTable     *hash_table,
+                                            gpointer        key,
+                                            gpointer        value)
+{
+  g_mutex_lock (&hash_table->mx);
+  g_hash_table_insert (hash_table->ht, key, value);
+  g_mutex_unlock (&hash_table->mx);
+}
+
+static inline
+void        p_hash_table_replace           (PHashTable     *hash_table,
+                                            gpointer        key,
+                                            gpointer        value)
+{
+  g_mutex_lock (&hash_table->mx);
+  g_hash_table_replace (hash_table->ht, key, value);
+  g_mutex_unlock (&hash_table->mx);
+}
+
+static inline
+gboolean    p_hash_table_remove            (PHashTable     *hash_table,
+                                            gconstpointer   key)
+{
+  gboolean ret;
+  g_mutex_lock (&hash_table->mx);
+  ret = g_hash_table_remove (hash_table->ht, key);
+  g_mutex_unlock (&hash_table->mx);
+  return ret;
+}
+
+static inline
+gpointer    p_hash_table_lookup            (PHashTable     *hash_table,
+                                            gconstpointer   key)
+{
+  gpointer ret;
+  g_mutex_lock (&hash_table->mx);
+  ret = g_hash_table_lookup (hash_table->ht, key);
+  g_mutex_unlock (&hash_table->mx);
+  return ret;
+}
+
+static inline
+void        p_hash_table_foreach           (PHashTable     *hash_table,
+                                            GHFunc          func,
+                                            gpointer        user_data)
+{
+  g_mutex_lock (&hash_table->mx);
+  g_hash_table_foreach (hash_table->ht, func, user_data);
+  g_mutex_unlock (&hash_table->mx);
+}
+
+
+G_END_DECLS
+
+#endif /* __PANGO_THREADSAFE_H__ */
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index d4a8fa9..5be2b81 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -30,6 +30,7 @@
 #include "pango-impl-utils.h"
 #include "modules.h"
 #include "pango-enum-types.h"
+#include "pango-threadsafe.h"
 
 
 /* Overview:
@@ -106,19 +107,19 @@ typedef struct _PangoFcFontset      PangoFcFontset;
 
 struct _PangoFcFontMapPrivate
 {
-  GHashTable *fontset_hash;	/* Maps PangoFcFontsetKey -> PangoFcFontset  */
+  PHashTable *fontset_hash;	/* Maps PangoFcFontsetKey -> PangoFcFontset  */
   GQueue *fontset_cache;	/* Recently used fontsets */
 
-  GHashTable *font_hash;	/* Maps PangoFcFontKey -> PangoFcFont */
+  PHashTable *font_hash;	/* Maps PangoFcFontKey -> PangoFcFont */
 
-  GHashTable *patterns_hash;	/* Maps FcPattern -> PangoFcPatterns */
+  PHashTable *patterns_hash;	/* Maps FcPattern -> PangoFcPatterns */
 
   /* pattern_hash is used to make sure we only store one copy of
    * each identical pattern. (Speeds up lookup).
    */
-  GHashTable *pattern_hash;
+  PHashTable *pattern_hash;
 
-  GHashTable *font_face_data_hash; /* Maps font file name/id -> data */
+  PHashTable *font_face_data_hash; /* Maps font file name/id -> data */
 
   /* List of all families availible */
   PangoFcFamily **families;
@@ -687,7 +688,7 @@ pango_fc_patterns_new (FcPattern *pat, PangoFcFontMap *fontmap)
   PangoFcPatterns *pats;
 
   pat = uniquify_pattern (fontmap, pat);
-  pats = g_hash_table_lookup (fontmap->priv->patterns_hash, pat);
+  pats = p_hash_table_lookup (fontmap->priv->patterns_hash, pat);
   if (pats)
     return pango_fc_patterns_ref (pats);
 
@@ -699,7 +700,7 @@ pango_fc_patterns_new (FcPattern *pat, PangoFcFontMap *fontmap)
   FcPatternReference (pat);
   pats->pattern = pat;
 
-  g_hash_table_insert (fontmap->priv->patterns_hash,
+  p_hash_table_insert (fontmap->priv->patterns_hash,
 		       pats->pattern, pats);
 
   return pats;
@@ -728,8 +729,8 @@ pango_fc_patterns_unref (PangoFcPatterns *pats)
   /* Only remove from fontmap hash if we are in it.  This is not necessarily
    * the case after a cache_clear() call. */
   if (pats->fontmap->priv->patterns_hash &&
-      pats == g_hash_table_lookup (pats->fontmap->priv->patterns_hash, pats->pattern))
-    g_hash_table_remove (pats->fontmap->priv->patterns_hash,
+      pats == p_hash_table_lookup (pats->fontmap->priv->patterns_hash, pats->pattern))
+    p_hash_table_remove (pats->fontmap->priv->patterns_hash,
 			 pats->pattern);
 
   if (pats->pattern)
@@ -1034,23 +1035,23 @@ pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
 
   priv->n_families = -1;
 
-  priv->font_hash = g_hash_table_new ((GHashFunc)pango_fc_font_key_hash,
+  priv->font_hash = p_hash_table_new ((GHashFunc)pango_fc_font_key_hash,
 				      (GEqualFunc)pango_fc_font_key_equal);
 
-  priv->fontset_hash = g_hash_table_new_full ((GHashFunc)pango_fc_fontset_key_hash,
+  priv->fontset_hash = p_hash_table_new_full ((GHashFunc)pango_fc_fontset_key_hash,
 					      (GEqualFunc)pango_fc_fontset_key_equal,
 					      NULL,
 					      (GDestroyNotify)g_object_unref);
   priv->fontset_cache = g_queue_new ();
 
-  priv->patterns_hash = g_hash_table_new (NULL, NULL);
+  priv->patterns_hash = p_hash_table_new (NULL, NULL);
 
-  priv->pattern_hash = g_hash_table_new_full ((GHashFunc) FcPatternHash,
+  priv->pattern_hash = p_hash_table_new_full ((GHashFunc) FcPatternHash,
 					      (GEqualFunc) FcPatternEqual,
 					      (GDestroyNotify) FcPatternDestroy,
 					      NULL);
 
-  priv->font_face_data_hash = g_hash_table_new_full ((GHashFunc)pango_fc_font_face_data_hash,
+  priv->font_face_data_hash = p_hash_table_new_full ((GHashFunc)pango_fc_font_face_data_hash,
 						     (GEqualFunc)pango_fc_font_face_data_equal,
 						     (GDestroyNotify)pango_fc_font_face_data_free,
 						     NULL);
@@ -1066,19 +1067,19 @@ pango_fc_font_map_fini (PangoFcFontMap *fcfontmap)
   g_queue_free (priv->fontset_cache);
   priv->fontset_cache = NULL;
 
-  g_hash_table_destroy (priv->fontset_hash);
+  p_hash_table_destroy (priv->fontset_hash);
   priv->fontset_hash = NULL;
 
-  g_hash_table_destroy (priv->patterns_hash);
+  p_hash_table_destroy (priv->patterns_hash);
   priv->patterns_hash = NULL;
 
-  g_hash_table_destroy (priv->font_hash);
+  p_hash_table_destroy (priv->font_hash);
   priv->font_hash = NULL;
 
-  g_hash_table_destroy (priv->font_face_data_hash);
+  p_hash_table_destroy (priv->font_face_data_hash);
   priv->font_face_data_hash = NULL;
 
-  g_hash_table_destroy (priv->pattern_hash);
+  p_hash_table_destroy (priv->pattern_hash);
   priv->pattern_hash = NULL;
 
   for (i = 0; i < priv->n_families; i++)
@@ -1199,7 +1200,7 @@ pango_fc_font_map_add (PangoFcFontMap *fcfontmap,
 
   key_copy = pango_fc_font_key_copy (key);
   _pango_fc_font_set_font_key (fcfont, key_copy);
-  g_hash_table_insert (priv->font_hash, key_copy, fcfont);
+  p_hash_table_insert (priv->font_hash, key_copy, fcfont);
 }
 
 /* Remove mapping from fcfont->key to fcfont */
@@ -1217,9 +1218,9 @@ _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap,
       /* Only remove from fontmap hash if we are in it.  This is not necessarily
        * the case after a cache_clear() call. */
       if (priv->font_hash &&
-	  fcfont == g_hash_table_lookup (priv->font_hash, key))
+	  fcfont == p_hash_table_lookup (priv->font_hash, key))
         {
-	  g_hash_table_remove (priv->font_hash, key);
+	  p_hash_table_remove (priv->font_hash, key);
 	}
       _pango_fc_font_set_font_key (fcfont, NULL);
       pango_fc_font_key_free (key);
@@ -1489,7 +1490,7 @@ uniquify_pattern (PangoFcFontMap *fcfontmap,
   PangoFcFontMapPrivate *priv = fcfontmap->priv;
   FcPattern *old_pattern;
 
-  old_pattern = g_hash_table_lookup (priv->pattern_hash, pattern);
+  old_pattern = p_hash_table_lookup (priv->pattern_hash, pattern);
   if (old_pattern)
     {
       return old_pattern;
@@ -1497,7 +1498,7 @@ uniquify_pattern (PangoFcFontMap *fcfontmap,
   else
     {
       FcPatternReference (pattern);
-      g_hash_table_insert (priv->pattern_hash, pattern, pattern);
+      p_hash_table_insert (priv->pattern_hash, pattern, pattern);
       return pattern;
     }
 }
@@ -1520,7 +1521,7 @@ pango_fc_font_map_new_font (PangoFcFontMap    *fcfontmap,
 
   pango_fc_font_key_init (&key, fcfontmap, fontset_key, match);
 
-  fcfont = g_hash_table_lookup (priv->font_hash, &key);
+  fcfont = p_hash_table_lookup (priv->font_hash, &key);
   if (fcfont)
     return g_object_ref (fcfont);
 
@@ -1708,7 +1709,7 @@ pango_fc_fontset_cache (PangoFcFontset *fontset,
 	{
 	  PangoFcFontset *tmp_fontset = g_queue_pop_tail (cache);
 	  tmp_fontset->cache_link = NULL;
-	  g_hash_table_remove (priv->fontset_hash, tmp_fontset->key);
+	  p_hash_table_remove (priv->fontset_hash, tmp_fontset->key);
 	}
 
       fontset->cache_link = g_list_prepend (NULL, fontset);
@@ -1730,7 +1731,7 @@ pango_fc_font_map_load_fontset (PangoFontMap                 *fontmap,
 
   pango_fc_fontset_key_init (&key, fcfontmap, context, desc, language);
 
-  fontset = g_hash_table_lookup (priv->fontset_hash, &key);
+  fontset = p_hash_table_lookup (priv->fontset_hash, &key);
 
   if (G_UNLIKELY (!fontset))
     {
@@ -1740,7 +1741,7 @@ pango_fc_font_map_load_fontset (PangoFontMap                 *fontmap,
 	return NULL;
 
       fontset = pango_fc_fontset_new (&key, patterns);
-      g_hash_table_insert (priv->fontset_hash, pango_fc_fontset_get_key (fontset), fontset);
+      p_hash_table_insert (priv->fontset_hash, pango_fc_fontset_get_key (fontset), fontset);
 
       pango_fc_patterns_unref (patterns);
     }
@@ -1788,7 +1789,7 @@ pango_fc_font_map_get_font_face_data (PangoFcFontMap *fcfontmap,
   if (FcPatternGetInteger (font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
     return NULL;
 
-  data = g_hash_table_lookup (priv->font_face_data_hash, &key);
+  data = p_hash_table_lookup (priv->font_face_data_hash, &key);
   if (G_LIKELY (data))
     return data;
 
@@ -1799,7 +1800,7 @@ pango_fc_font_map_get_font_face_data (PangoFcFontMap *fcfontmap,
   data->pattern = font_pattern;
   FcPatternReference (data->pattern);
 
-  g_hash_table_insert (priv->font_face_data_hash, data, data);
+  p_hash_table_insert (priv->font_face_data_hash, data, data);
 
   return data;
 }
@@ -1995,7 +1996,7 @@ pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap)
   if (priv->closed)
     return;
 
-  g_hash_table_foreach (priv->font_hash, (GHFunc) shutdown_font, fcfontmap);
+  p_hash_table_foreach (priv->font_hash, (GHFunc) shutdown_font, fcfontmap);
   for (i = 0; i < priv->n_families; i++)
     priv->families[i]->fontmap = NULL;
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index fa3ed12..2726bbb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -41,12 +41,12 @@ TESTS_ENVIRONMENT =                    \
    srcdir=$(srcdir)                    \
    PANGO_RC_FILE=./pangorc
 
-noinst_PROGRAMS = gen-all-unicode dump-boundaries 
+noinst_PROGRAMS = gen-all-unicode dump-boundaries
 
 check_PROGRAMS = testboundaries testboundaries_ucd testcolor testscript
 
 if HAVE_CAIRO
-check_PROGRAMS += testiter
+check_PROGRAMS += testiter test-pangocairo-threads
 endif
 if HAVE_FREETYPE
 check_PROGRAMS += test-ot-tags
@@ -64,6 +64,7 @@ testiter_LDADD = $(TEST_PANGOCAIRO_LIBS)
 testscript_LDADD = $(TEST_PANGO_LIBS)
 test_ot_tags_LDADD = $(TEST_PANGOFT2_LIBS)
 dump_boundaries_LDADD = $(TEST_PANGO_LIBS)
+test_pangocairo_threads_LDADD = $(TEST_PANGOCAIRO_LIBS) $(GTHREAD_LIBS)
 
 if HAVE_CXX
 check_PROGRAMS += cxx-test



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]