summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2012-10-15 17:58:55 -0500
committerBehdad Esfahbod <behdad@behdad.org>2012-11-07 10:59:03 -0800
commitbdec39afb41471e7ebc86122239741a819e4a8b3 (patch)
treef3a23dc7324718232cc7512d8531b0610623c26b
parent8c1752d5e58616ca3013bd7bf5941d8025f0d975 (diff)
downloadpango-bdec39afb41471e7ebc86122239741a819e4a8b3.tar.gz
Add a threadsafe hashtable and use it in pangofc-fontmap
Inching our way closer to threadsafe pangofc.
-rw-r--r--configure.in2
-rw-r--r--pango/Makefile.am3
-rw-r--r--pango/pango-threadsafe.h128
-rw-r--r--pango/pangofc-fontmap.c63
-rw-r--r--tests/Makefile.am5
5 files changed, 167 insertions, 34 deletions
diff --git a/configure.in b/configure.in
index a0e00578..26c775e6 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 ab092c92..1387b786 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 00000000..c4abd683
--- /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 d4a8fa96..5be2b815 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 fa3ed125..2726bbba 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