Make default-FcConfig threadsafe

This commit is contained in:
Behdad Esfahbod 2012-10-07 17:02:50 -04:00
parent e53f5da54f
commit 0552f26016
2 changed files with 40 additions and 23 deletions

View File

@ -22,6 +22,8 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* Objects MT-safe for readonly access. */
#include "fcint.h" #include "fcint.h"
#include <dirent.h> #include <dirent.h>
#include <sys/types.h> #include <sys/types.h>
@ -36,27 +38,38 @@
#define R_OK 4 #define R_OK 4
#endif #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 FcBool
FcConfigInit (void) FcConfigInit (void)
{ {
FcConfig *config; return FcConfigEnsure () ? FcTrue : FcFalse;
if (_fcConfig)
return FcTrue;
config = FcInitLoadConfigAndFonts ();
if (!config)
return FcFalse;
FcConfigSetCurrent (config);
return FcTrue;
} }
void void
FcConfigFini (void) FcConfigFini (void)
{ {
if (_fcConfig) FcConfig *cfg = fc_atomic_ptr_get (&_fcConfig);
FcConfigDestroy (_fcConfig); if (cfg && fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL))
FcConfigDestroy (cfg);
} }
@ -257,8 +270,7 @@ FcConfigDestroy (FcConfig *config)
if (FcRefDec (&config->ref) != 1) if (FcRefDec (&config->ref) != 1)
return; return;
if (config == _fcConfig) fc_atomic_ptr_cmpexch (&_fcConfig, config, NULL);
_fcConfig = 0;
FcStrSetDestroy (config->configDirs); FcStrSetDestroy (config->configDirs);
FcStrSetDestroy (config->fontDirs); FcStrSetDestroy (config->fontDirs);
@ -411,25 +423,31 @@ FcConfigBuildFonts (FcConfig *config)
FcBool FcBool
FcConfigSetCurrent (FcConfig *config) FcConfigSetCurrent (FcConfig *config)
{ {
if (config == _fcConfig) FcConfig *cfg;
retry:
cfg = fc_atomic_ptr_get (&_fcConfig);
if (config == cfg)
return FcTrue; return FcTrue;
if (!config->fonts[FcSetSystem]) if (!config->fonts[FcSetSystem])
if (!FcConfigBuildFonts (config)) if (!FcConfigBuildFonts (config))
return FcFalse; return FcFalse;
if (_fcConfig) if (!fc_atomic_ptr_cmpexch (&_fcConfig, cfg, config))
FcConfigDestroy (_fcConfig); goto retry;
_fcConfig = config;
if (cfg)
FcConfigDestroy (cfg);
return FcTrue; return FcTrue;
} }
FcConfig * FcConfig *
FcConfigGetCurrent (void) FcConfigGetCurrent (void)
{ {
if (!_fcConfig) return FcConfigEnsure ();
FcConfigInit ();
return _fcConfig;
} }
FcBool FcBool

View File

@ -119,7 +119,6 @@ FcDefaultFini (void)
if (langs && fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) { if (langs && fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) {
FcRefInit (&langs->ref, 1); FcRefInit (&langs->ref, 1);
FcStrSetDestroy (langs); FcStrSetDestroy (langs);
langs = NULL;
} }
} }
@ -212,7 +211,7 @@ FcDefaultSubstitute (FcPattern *pattern)
FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue); FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue);
FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue); FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
} }
FcSharedStrFree ((char *) v2.u.s); FcSharedStrFree ((FcChar8 *) v2.u.s);
} }
#define __fcdefault__ #define __fcdefault__
#include "fcaliastail.h" #include "fcaliastail.h"