[pango/win32-threadsafe: 2/2] PangoWin32: Make font discovery thread-safe



commit 527107096cccaf696c9076dd4373bef8ef541220
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Mon Jul 22 17:07:36 2019 +0800

    PangoWin32: Make font discovery thread-safe
    
    Make font discovery using GDI/Unicscribe on Windows thread-safe, by:
    
    -Making the alias HashTable a part of the _PangoWin32FontMap struct, so
     that we only need to initialize this once when we initialize the
     PangoFontMap on Win32.  Make sure that we fill in that hash table with
     the fonts items we ask from the system once and only once as we
     initialize the PangoWin32FontMap.
    
    -Make the access to the common HDC in pangowin32.c where Alex mentioned
     that could be thread-unsafe done through pango_win32_get_dc().
    
    At this point the test-pangocairo-threads will pass in Meson, tested for
    20 successive rounds using 'meson test test-pangocairo-threads'.  Note
    that we still get the
    "Pango-WARNING **:hh:mm:ss.sss: All font fallbacks failed!!!", but at
    least we are doing much better on PangoWin32 in terms of thread-safety.

 pango/pangowin32-fontmap.c | 33 ++++++++++++++++-----------------
 pango/pangowin32-private.h |  3 +++
 pango/pangowin32.c         |  8 ++++----
 3 files changed, 23 insertions(+), 21 deletions(-)
---
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index dfdfbdc0..961dfcfd 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -604,36 +604,30 @@ read_windows_fallbacks (GHashTable *ht_aliases)
 #endif
 
 
-static GHashTable *
-load_aliases (void)
+static gboolean
+load_aliases (GHashTable *ht_aliases)
 {
-  GHashTable *ht_aliases = g_hash_table_new_full ((GHashFunc)alias_hash,
-                                                  (GEqualFunc)alias_equal,
-                                                  (GDestroyNotify)alias_free,
-                                                  NULL);
 
 #ifdef HAVE_CAIRO_WIN32
   read_windows_fallbacks (ht_aliases);
   read_builtin_aliases (ht_aliases);
 #endif
 
-  return ht_aliases;
+  return TRUE;
 }
 
 static void
-lookup_aliases (const char   *fontname,
+lookup_aliases (GHashTable   *aliases_ht,
+                const char   *fontname,
                 char       ***families,
                 int          *n_families)
 {
-  static GHashTable *aliases_ht = NULL; /* MT-safe */
-
   struct PangoAlias alias_key;
   struct PangoAlias *alias;
+  static gsize aliases_inited = 0;
 
-  if (g_once_init_enter (&aliases_ht))
-    {
-      g_once_init_leave (&aliases_ht, load_aliases ());
-    }
+  if (g_once_init_enter (&aliases_inited))
+    g_once_init_leave (&aliases_inited, load_aliases (aliases_ht));
 
   alias_key.alias = g_ascii_strdown (fontname, -1);
   alias = g_hash_table_lookup (aliases_ht, &alias_key);
@@ -659,7 +653,7 @@ create_standard_family (PangoWin32FontMap *win32fontmap,
   int n_aliases;
   char **aliases;
 
-  lookup_aliases (standard_family_name, &aliases, &n_aliases);
+  lookup_aliases (win32fontmap->aliases, standard_family_name, &aliases, &n_aliases);
   for (i = 0; i < n_aliases; i++)
     {
       PangoWin32Family *existing_family = g_hash_table_lookup (win32fontmap->families, aliases[i]);
@@ -726,6 +720,10 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
 
   win32fontmap->font_cache = pango_win32_font_cache_new ();
   win32fontmap->freed_fonts = g_queue_new ();
+  win32fontmap->aliases = g_hash_table_new_full ((GHashFunc)alias_hash,
+                                                 (GEqualFunc)alias_equal,
+                                                 (GDestroyNotify)alias_free,
+                                                 NULL);
 
   memset (&logfont, 0, sizeof (logfont));
   logfont.lfCharSet = DEFAULT_CHARSET;
@@ -757,8 +755,9 @@ pango_win32_font_map_fontset_add_fonts (PangoFontMap          *fontmap,
   char **aliases;
   int n_aliases;
   int j;
+  PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
 
-  lookup_aliases (family, &aliases, &n_aliases);
+  lookup_aliases (win32fontmap->aliases, family, &aliases, &n_aliases);
 
   if (n_aliases)
   {
@@ -841,8 +840,8 @@ pango_win32_font_map_finalize (GObject *object)
 
   pango_win32_font_cache_free (win32fontmap->font_cache);
 
+  g_hash_table_destroy (win32fontmap->aliases);
   g_hash_table_destroy (win32fontmap->fonts);
-
   g_hash_table_destroy (win32fontmap->families);
 
   G_OBJECT_CLASS (_pango_win32_font_map_parent_class)->finalize (object);
diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h
index 65f9de05..65a4b43b 100644
--- a/pango/pangowin32-private.h
+++ b/pango/pangowin32-private.h
@@ -107,6 +107,9 @@ struct _PangoWin32FontMap
    */
   GHashTable *fonts;
 
+  /* keeps track of the alias pairs that we might have */
+  GHashTable *aliases;
+
   double resolution;           /* (points / pixel) * PANGO_SCALE */
 };
 
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index 86c698d1..e6b00341 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -462,15 +462,15 @@ pango_win32_font_get_glyph_extents (PangoFont      *font,
 
   if (!info)
     {
+      HDC hdc = pango_win32_get_dc ();
+
       info = g_new0 (PangoWin32GlyphInfo, 1);
 
       memset (&gm, 0, sizeof (gm));
 
       hfont = _pango_win32_font_get_hfont (font);
-      SelectObject (_pango_win32_hdc, hfont);
-      /* FIXME: (Alex) This constant reuse of _pango_win32_hdc is
-        not thread-safe */
-      res = GetGlyphOutlineA (_pango_win32_hdc,
+      SelectObject (hdc, hfont);
+      res = GetGlyphOutlineA (hdc,
                              glyph_index,
                              GGO_METRICS | GGO_GLYPH_INDEX,
                              &gm,


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