From 0552f26016865b8a76819cf342fa0cf13afdc5e8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 7 Oct 2012 17:02:50 -0400 Subject: [PATCH] Make default-FcConfig threadsafe --- src/fccfg.c | 60 ++++++++++++++++++++++++++++++++----------------- src/fcdefault.c | 3 +-- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/fccfg.c b/src/fccfg.c index 1ac7c43..3245ede 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -22,6 +22,8 @@ * PERFORMANCE OF THIS SOFTWARE. */ +/* Objects MT-safe for readonly access. */ + #include "fcint.h" #include #include @@ -36,27 +38,38 @@ #define R_OK 4 #endif -static FcConfig *_fcConfig; +static FcConfig *_fcConfig; /* MT-safe */ + +static FcConfig * +FcConfigEnsure (void) +{ + FcConfig *config; +retry: + config = fc_atomic_ptr_get (&_fcConfig); + if (!config) + { + config = FcInitLoadConfigAndFonts (); + + if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) { + FcConfigDestroy (config); + goto retry; + } + } + return config; +} FcBool FcConfigInit (void) { - FcConfig *config; - - if (_fcConfig) - return FcTrue; - config = FcInitLoadConfigAndFonts (); - if (!config) - return FcFalse; - FcConfigSetCurrent (config); - return FcTrue; + return FcConfigEnsure () ? FcTrue : FcFalse; } void FcConfigFini (void) { - if (_fcConfig) - FcConfigDestroy (_fcConfig); + FcConfig *cfg = fc_atomic_ptr_get (&_fcConfig); + if (cfg && fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL)) + FcConfigDestroy (cfg); } @@ -257,8 +270,7 @@ FcConfigDestroy (FcConfig *config) if (FcRefDec (&config->ref) != 1) return; - if (config == _fcConfig) - _fcConfig = 0; + fc_atomic_ptr_cmpexch (&_fcConfig, config, NULL); FcStrSetDestroy (config->configDirs); FcStrSetDestroy (config->fontDirs); @@ -411,25 +423,31 @@ FcConfigBuildFonts (FcConfig *config) FcBool FcConfigSetCurrent (FcConfig *config) { - if (config == _fcConfig) + FcConfig *cfg; + +retry: + cfg = fc_atomic_ptr_get (&_fcConfig); + + if (config == cfg) return FcTrue; if (!config->fonts[FcSetSystem]) if (!FcConfigBuildFonts (config)) return FcFalse; - if (_fcConfig) - FcConfigDestroy (_fcConfig); - _fcConfig = config; + if (!fc_atomic_ptr_cmpexch (&_fcConfig, cfg, config)) + goto retry; + + if (cfg) + FcConfigDestroy (cfg); + return FcTrue; } FcConfig * FcConfigGetCurrent (void) { - if (!_fcConfig) - FcConfigInit (); - return _fcConfig; + return FcConfigEnsure (); } FcBool diff --git a/src/fcdefault.c b/src/fcdefault.c index 2f13659..0069db2 100644 --- a/src/fcdefault.c +++ b/src/fcdefault.c @@ -119,7 +119,6 @@ FcDefaultFini (void) if (langs && fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) { FcRefInit (&langs->ref, 1); FcStrSetDestroy (langs); - langs = NULL; } } @@ -212,7 +211,7 @@ FcDefaultSubstitute (FcPattern *pattern) FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue); FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue); } - FcSharedStrFree ((char *) v2.u.s); + FcSharedStrFree ((FcChar8 *) v2.u.s); } #define __fcdefault__ #include "fcaliastail.h"