From 331f00d182dd6ef4e2c7cb633b5e443cad017007 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 15 Oct 2012 19:10:57 -0500 Subject: Make _pango_cairo_font_private_get_scaled_font() threadsafe --- pango/pangocairo-font.c | 114 ++++++++++++++++++++++++------------------------ 1 file 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; } /** -- cgit v1.2.1