summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2012-10-15 19:10:57 -0500
committerBehdad Esfahbod <behdad@behdad.org>2012-11-07 10:59:03 -0800
commit331f00d182dd6ef4e2c7cb633b5e443cad017007 (patch)
treee4cf86a2b8372965d402596d4ec120f570668448
parentdfc1726f91d14d4af94a8959f63a492c94ee7b32 (diff)
downloadpango-331f00d182dd6ef4e2c7cb633b5e443cad017007.tar.gz
Make _pango_cairo_font_private_get_scaled_font() threadsafe
-rw-r--r--pango/pangocairo-font.c114
1 files changed, 58 insertions, 56 deletions
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index 3b649595..57b6dd1e 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;
}
/**