Make default-FcConfig threadsafe
authorBehdad Esfahbod <behdad@behdad.org>
Sun, 7 Oct 2012 21:02:50 +0000 (17:02 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 2 Jan 2013 07:01:29 +0000 (01:01 -0600)
src/fccfg.c
src/fcdefault.c

index 1ac7c43..3245ede 100644 (file)
@@ -22,6 +22,8 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/* Objects MT-safe for readonly access. */
+
 #include "fcint.h"
 #include <dirent.h>
 #include <sys/types.h>
 #define R_OK 4
 #endif
 
-static FcConfig    *_fcConfig;
+static FcConfig    *_fcConfig; /* MT-safe */
 
-FcBool
-FcConfigInit (void)
+static FcConfig *
+FcConfigEnsure (void)
 {
     FcConfig   *config;
-
-    if (_fcConfig)
-       return FcTrue;
-    config = FcInitLoadConfigAndFonts ();
+retry:
+    config = fc_atomic_ptr_get (&_fcConfig);
     if (!config)
-       return FcFalse;
-    FcConfigSetCurrent (config);
-    return FcTrue;
+    {
+       config = FcInitLoadConfigAndFonts ();
+
+       if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) {
+           FcConfigDestroy (config);
+           goto retry;
+       }
+    }
+    return config;
+}
+
+FcBool
+FcConfigInit (void)
+{
+  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
index 2f13659..0069db2 100644 (file)
@@ -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"