[pango/threadsafe-failed-attempt: 3/11] Make _pango_cairo_font_private_get_scaled_font() threadsafe



commit 331f00d182dd6ef4e2c7cb633b5e443cad017007
Author: Behdad Esfahbod <behdad behdad org>
Date:   Mon Oct 15 19:10:57 2012 -0500

    Make _pango_cairo_font_private_get_scaled_font() threadsafe

 pango/pangocairo-font.c |  126 ++++++++++++++++++++++++-----------------------
 1 files changed, 64 insertions(+), 62 deletions(-)
---
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index 3b64959..57b6dd1 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -62,76 +62,78 @@ _pango_cairo_font_private_scaled_font_data_destroy (PangoCairoFontPrivateScaledF
 cairo_scaled_font_t *
 _pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv)
 {
-  cairo_font_face_t *font_face;
-
-  if (G_LIKELY (cf_priv->scaled_font))
-    return cf_priv->scaled_font;
-
-  /* need to create it */
-
-  if (G_UNLIKELY (cf_priv->data == NULL))
+  cairo_scaled_font_t *scaled_font;
+  PangoCairoFontPrivateScaledFontData *data;
+retry:
+  scaled_font = g_atomic_pointer_get (&cf_priv->scaled_font);
+
+  /* The case of scaled_font == NULL && data == NULL happens when we tried to
+   * create it, and failed before. */
+  if (G_UNLIKELY (!scaled_font) &&
+      ((data = g_atomic_pointer_get (&cf_priv->data)) != NULL))
     {
-      /* we have tried to create and failed before */
-      return NULL;
-    }
-
-  font_face = (* PANGO_CAIRO_FONT_GET_IFACE (cf_priv->cfont)->create_font_face) (cf_priv->cfont);
-  if (G_UNLIKELY (font_face == NULL))
-    goto done;
-
-  cf_priv->scaled_font = cairo_scaled_font_create (font_face,
-						   &cf_priv->data->font_matrix,
-						   &cf_priv->data->ctm,
-						   cf_priv->data->options);
-
-  cairo_font_face_destroy (font_face);
+      cairo_font_face_t *font_face;
+      font_face = (* PANGO_CAIRO_FONT_GET_IFACE (cf_priv->cfont)->create_font_face) (cf_priv->cfont);
+      if (G_LIKELY (font_face))
+        {
+	  scaled_font = cairo_scaled_font_create (font_face,
+						  &cf_priv->data->font_matrix,
+						  &cf_priv->data->ctm,
+						  cf_priv->data->options);
+	  cairo_font_face_destroy (font_face);
+	}
 
-done:
+      if (!g_atomic_pointer_compare_and_exchange (&cf_priv->scaled_font, NULL, scaled_font))
+        {
+	  cairo_scaled_font_destroy (scaled_font);
+	  goto retry;
+	}
 
-  if (G_UNLIKELY (cf_priv->scaled_font == NULL || cairo_scaled_font_status (cf_priv->scaled_font) != CAIRO_STATUS_SUCCESS))
-    {
-      cairo_scaled_font_t *scaled_font = cf_priv->scaled_font;
-      PangoFont *font = PANGO_FONT (cf_priv->cfont);
-      static GQuark warned_quark = 0; /* MT-safe */
-      if (!warned_quark)
-	warned_quark = g_quark_from_static_string ("pangocairo-scaledfont-warned");
+      if (g_atomic_pointer_compare_and_exchange (&cf_priv->data, data, NULL))
+	_pango_cairo_font_private_scaled_font_data_destroy (data);
 
-      if (!g_object_get_qdata (G_OBJECT (font), warned_quark))
+      if (G_UNLIKELY (!scaled_font || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
 	{
-	  PangoFontDescription *desc;
-	  char *s;
+	  cairo_scaled_font_t *scaled_font = cf_priv->scaled_font;
+	  PangoFont *font = PANGO_FONT (cf_priv->cfont);
+	  static GQuark warned_quark = 0; /* MT-safe */
+	  if (!warned_quark)
+	    warned_quark = g_quark_from_static_string ("pangocairo-scaledfont-warned");
 
-	  desc = pango_font_describe (font);
-	  s = pango_font_description_to_string (desc);
-	  pango_font_description_free (desc);
+	  if (!g_object_get_qdata (G_OBJECT (font), warned_quark))
+	    {
+	      PangoFontDescription *desc;
+	      char *s;
 
-	  g_warning ("failed to create cairo %s, expect ugly output. the offending font is '%s'",
-		     font_face ? "scaled font" : "font face",
-		     s);
+	      desc = pango_font_describe (font);
+	      s = pango_font_description_to_string (desc);
+	      pango_font_description_free (desc);
 
-	  if (!font_face)
-		g_warning ("font_face is NULL");
-	  else
-		g_warning ("font_face status is: %s",
-			   cairo_status_to_string (cairo_font_face_status (font_face)));
+	      g_warning ("failed to create cairo %s, expect ugly output. the offending font is '%s'",
+			 font_face ? "scaled font" : "font face",
+			 s);
 
-	  if (!scaled_font)
-		g_warning ("scaled_font is NULL");
-	  else
-		g_warning ("scaled_font status is: %s",
-			   cairo_status_to_string (cairo_scaled_font_status (scaled_font)));
+	      if (!font_face)
+		    g_warning ("font_face is NULL");
+	      else
+		    g_warning ("font_face status is: %s",
+			       cairo_status_to_string (cairo_font_face_status (font_face)));
 
-	  g_free (s);
+	      if (!scaled_font)
+		    g_warning ("scaled_font is NULL");
+	      else
+		    g_warning ("scaled_font status is: %s",
+			       cairo_status_to_string (cairo_scaled_font_status (scaled_font)));
 
-	  g_object_set_qdata_full (G_OBJECT (font), warned_quark,
-				   GINT_TO_POINTER (1), NULL);
+	      g_free (s);
+
+	      g_object_set_qdata_full (G_OBJECT (font), warned_quark,
+				       GINT_TO_POINTER (1), NULL);
+	    }
 	}
     }
 
-  _pango_cairo_font_private_scaled_font_data_destroy (cf_priv->data);
-  cf_priv->data = NULL;
-
-  return cf_priv->scaled_font;
+  return scaled_font;
 }
 
 /**



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