Make FcGetDefaultLang and FcGetDefaultLangs thread-safe
This commit is contained in:
parent
64af9e1917
commit
b97ab0c949
|
@ -25,6 +25,8 @@
|
||||||
#include "fcint.h"
|
#include "fcint.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/* MT-safe */
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
FcObject field;
|
FcObject field;
|
||||||
FcBool value;
|
FcBool value;
|
||||||
|
@ -32,7 +34,6 @@ static const struct {
|
||||||
{ FC_HINTING_OBJECT, FcTrue }, /* !FT_LOAD_NO_HINTING */
|
{ FC_HINTING_OBJECT, FcTrue }, /* !FT_LOAD_NO_HINTING */
|
||||||
{ FC_VERTICAL_LAYOUT_OBJECT, FcFalse }, /* FC_LOAD_VERTICAL_LAYOUT */
|
{ FC_VERTICAL_LAYOUT_OBJECT, FcFalse }, /* FC_LOAD_VERTICAL_LAYOUT */
|
||||||
{ FC_AUTOHINT_OBJECT, FcFalse }, /* FC_LOAD_FORCE_AUTOHINT */
|
{ FC_AUTOHINT_OBJECT, FcFalse }, /* FC_LOAD_FORCE_AUTOHINT */
|
||||||
/* XXX: FC_GLOBAL_ADVANCE is deprecated */
|
|
||||||
{ FC_GLOBAL_ADVANCE_OBJECT, FcTrue }, /* !FC_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
|
{ FC_GLOBAL_ADVANCE_OBJECT, FcTrue }, /* !FC_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
|
||||||
{ FC_EMBEDDED_BITMAP_OBJECT, FcTrue }, /* !FC_LOAD_NO_BITMAP */
|
{ FC_EMBEDDED_BITMAP_OBJECT, FcTrue }, /* !FC_LOAD_NO_BITMAP */
|
||||||
{ FC_DECORATIVE_OBJECT, FcFalse },
|
{ FC_DECORATIVE_OBJECT, FcFalse },
|
||||||
|
@ -40,12 +41,20 @@ static const struct {
|
||||||
|
|
||||||
#define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
|
#define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
|
||||||
|
|
||||||
|
FcStrSet *default_langs;
|
||||||
|
|
||||||
FcStrSet *
|
FcStrSet *
|
||||||
FcGetDefaultLangs (void)
|
FcGetDefaultLangs (void)
|
||||||
{
|
{
|
||||||
FcStrSet *result = FcStrSetCreate ();
|
FcStrSet *result;
|
||||||
|
retry:
|
||||||
|
result = (FcStrSet *) fc_atomic_ptr_get (&default_langs);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
char *langs;
|
char *langs;
|
||||||
|
|
||||||
|
result = FcStrSetCreate ();
|
||||||
|
|
||||||
langs = getenv ("FC_LANG");
|
langs = getenv ("FC_LANG");
|
||||||
if (!langs || !langs[0])
|
if (!langs || !langs[0])
|
||||||
langs = getenv ("LC_ALL");
|
langs = getenv ("LC_ALL");
|
||||||
|
@ -61,24 +70,52 @@ FcGetDefaultLangs (void)
|
||||||
else
|
else
|
||||||
FcStrSetAdd (result, (const FcChar8 *) "en");
|
FcStrSetAdd (result, (const FcChar8 *) "en");
|
||||||
|
|
||||||
|
FcRefSetConst (&result->ref);
|
||||||
|
if (!fc_atomic_ptr_cmpexch (&default_langs, NULL, result)) {
|
||||||
|
FcRefInit (&result->ref, 1);
|
||||||
|
FcStrSetDestroy (result);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FcChar8 *default_lang; /* MT-safe */
|
||||||
|
|
||||||
FcChar8 *
|
FcChar8 *
|
||||||
FcGetDefaultLang (void)
|
FcGetDefaultLang (void)
|
||||||
{
|
{
|
||||||
static FcChar8 lang_local[128] = {0};
|
FcChar8 *lang;
|
||||||
FcStrSet *langs;
|
retry:
|
||||||
|
lang = fc_atomic_ptr_get (&default_lang);
|
||||||
if (!lang_local[0])
|
if (!lang)
|
||||||
{
|
{
|
||||||
langs = FcGetDefaultLangs ();
|
FcStrSet *langs = FcGetDefaultLangs ();
|
||||||
strncpy ((char *)lang_local, (const char *)langs->strs[0], 127);
|
lang = (FcChar8 *) strdup ((const char *) langs->strs[0]);
|
||||||
lang_local[127] = 0;
|
|
||||||
FcStrSetDestroy (langs);
|
FcStrSetDestroy (langs);
|
||||||
|
|
||||||
|
if (!fc_atomic_ptr_cmpexch (&default_lang, NULL, lang)) {
|
||||||
|
free (lang);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lang_local;
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FcDefaultFini (void)
|
||||||
|
{
|
||||||
|
if (default_lang) {
|
||||||
|
free (default_lang);
|
||||||
|
default_lang = NULL;
|
||||||
|
}
|
||||||
|
if (default_langs) {
|
||||||
|
FcRefInit (&default_langs->ref, 1);
|
||||||
|
FcStrSetDestroy (default_langs);
|
||||||
|
default_langs = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -156,6 +156,7 @@ FcFini (void)
|
||||||
FcConfigDestroy (_fcConfig);
|
FcConfigDestroy (_fcConfig);
|
||||||
|
|
||||||
FcCacheFini ();
|
FcCacheFini ();
|
||||||
|
FcDefaultFini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -761,6 +761,9 @@ FcInitDebug (void);
|
||||||
FcPrivate FcChar8 *
|
FcPrivate FcChar8 *
|
||||||
FcGetDefaultLang (void);
|
FcGetDefaultLang (void);
|
||||||
|
|
||||||
|
FcPrivate void
|
||||||
|
FcDefaultFini (void);
|
||||||
|
|
||||||
/* fcdir.c */
|
/* fcdir.c */
|
||||||
|
|
||||||
FcPrivate FcBool
|
FcPrivate FcBool
|
||||||
|
|
|
@ -1234,6 +1234,10 @@ FcStrSetDestroy (FcStrSet *set)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* We rely on this in FcGetDefaultLangs for caching. */
|
||||||
|
if (FcRefIsConst (&set->ref))
|
||||||
|
return;
|
||||||
|
|
||||||
if (FcRefDec (&set->ref) != 1)
|
if (FcRefDec (&set->ref) != 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue