Commit 64af9e19 authored by Behdad Esfahbod's avatar Behdad Esfahbod

Make refcounts, patterns, charsets, strings, and FcLang thread-safe

parent 814871b2
......@@ -63,7 +63,7 @@ static inline void HBMemoryBarrier (void) {
}
#endif
typedef long fc_atomic_int_t;
typedef int fc_atomic_int_t;
#define fc_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
#define fc_atomic_ptr_get(P) (HBMemoryBarrier (), (void *) *(P))
......@@ -74,7 +74,7 @@ typedef long fc_atomic_int_t;
#include <libkern/OSAtomic.h>
typedef int32_t fc_atomic_int_t;
typedef int fc_atomic_int_t;
#define fc_atomic_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
#define fc_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P))
......@@ -111,13 +111,13 @@ typedef int fc_atomic_int_t;
#endif
/* reference count */
#define FC_REF_CONSTANT ((fc_atomic_int_t) -1)
#define FC_REF_CONSTANT_INIT {FC_REF_CONSTANT}
#define FC_REF_CONSTANT_VALUE ((fc_atomic_int_t) -1)
#define FC_REF_CONSTANT {FC_REF_CONSTANT_VALUE}
typedef struct _FcRef { fc_atomic_int_t count; } FcRef;
static inline void FcRefInit (FcRef *r, int v) { r->count = v; }
static inline int FcRefInc (FcRef *r) { return fc_atomic_int_add (r->count, +1); }
static inline int FcRefDec (FcRef *r) { return fc_atomic_int_add (r->count, -1); }
static inline void FcRefFinish (FcRef *r) { r->count = FC_REF_CONSTANT; }
static inline FcBool FcRefIsConst (FcRef *r) { return r->count == FC_REF_CONSTANT; }
static inline void FcRefInit (FcRef *r, int v) { r->count = v; }
static inline int FcRefInc (FcRef *r) { return fc_atomic_int_add (r->count, +1); }
static inline int FcRefDec (FcRef *r) { return fc_atomic_int_add (r->count, -1); }
static inline void FcRefSetConst (FcRef *r) { r->count = FC_REF_CONSTANT_VALUE; }
static inline FcBool FcRefIsConst (const FcRef *r) { return r->count == FC_REF_CONSTANT_VALUE; }
#endif /* _FCATOMIC_H_ */
......@@ -94,7 +94,7 @@ FcConfigCreate (void)
config->expr_pool = NULL;
config->ref = 1;
FcRefInit (&config->ref, 1);
return config;
......@@ -221,7 +221,7 @@ FcConfigReference (FcConfig *config)
return 0;
}
config->ref++;
FcRefInc (&config->ref);
return config;
}
......@@ -232,7 +232,7 @@ FcConfigDestroy (FcConfig *config)
FcSetName set;
FcExprPage *page;
if (--config->ref > 0)
if (FcRefDec (&config->ref) != 1)
return;
if (config == _fcConfig)
......@@ -662,7 +662,7 @@ typedef struct _FcSubState {
} FcSubState;
static FcValue
FcConfigPromote (FcValue v, FcValue u)
FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
{
if (v.type == FcTypeInteger)
{
......@@ -674,9 +674,9 @@ FcConfigPromote (FcValue v, FcValue u)
v.u.m = &FcIdentityMatrix;
v.type = FcTypeMatrix;
}
else if (v.type == FcTypeString && u.type == FcTypeLangSet)
else if (buf && v.type == FcTypeString && u.type == FcTypeLangSet)
{
v.u.l = FcLangSetPromote (v.u.s);
v.u.l = FcLangSetPromote (v.u.s, buf);
v.type = FcTypeLangSet;
}
return v;
......@@ -692,9 +692,10 @@ FcConfigCompareValue (const FcValue *left_o,
FcBool ret = FcFalse;
FcOp op = FC_OP_GET_OP (op_);
int flags = FC_OP_GET_FLAGS (op_);
FcValuePromotionBuffer buf1, buf2;
left = FcConfigPromote (left, right);
right = FcConfigPromote (right, left);
left = FcConfigPromote (left, right, &buf1);
right = FcConfigPromote (right, left, &buf2);
if (left.type == right.type)
{
switch (left.type) {
......@@ -893,10 +894,10 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e)
FcMatrix m;
FcValue xx, xy, yx, yy;
v.type = FcTypeMatrix;
xx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xx), v);
xy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xy), v);
yx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yx), v);
yy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yy), v);
xx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xx), v, NULL);
xy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xy), v, NULL);
yx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yx), v, NULL);
yy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yy), v, NULL);
if (xx.type == FcTypeDouble && xy.type == FcTypeDouble &&
yx.type == FcTypeDouble && yy.type == FcTypeDouble)
{
......@@ -987,8 +988,8 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e)
case FcOpDivide:
vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right);
vl = FcConfigPromote (vl, vr);
vr = FcConfigPromote (vr, vl);
vl = FcConfigPromote (vl, vr, NULL);
vr = FcConfigPromote (vr, vl, NULL);
if (vl.type == vr.type)
{
switch ((int) vl.type) {
......
......@@ -35,7 +35,7 @@ FcCharSetCreate (void)
fcs = (FcCharSet *) malloc (sizeof (FcCharSet));
if (!fcs)
return 0;
fcs->ref = 1;
FcRefInit (&fcs->ref, 1);
fcs->num = 0;
fcs->leaves_offset = 0;
fcs->numbers_offset = 0;
......@@ -55,12 +55,12 @@ FcCharSetDestroy (FcCharSet *fcs)
if (fcs)
{
if (fcs->ref == FC_REF_CONSTANT)
if (FcRefIsConst (&fcs->ref))
{
FcCacheObjectDereference (fcs);
return;
}
if (--fcs->ref > 0)
if (FcRefDec (&fcs->ref) != 1)
return;
for (i = 0; i < fcs->num; i++)
free (FcCharSetLeaf (fcs, i));
......@@ -237,7 +237,7 @@ FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
FcCharLeaf *leaf;
FcChar32 *b;
if (fcs == NULL || fcs->ref == FC_REF_CONSTANT)
if (fcs == NULL || FcRefIsConst (&fcs->ref))
return FcFalse;
leaf = FcCharSetFindLeafCreate (fcs, ucs4);
if (!leaf)
......@@ -253,7 +253,7 @@ FcCharSetDelChar (FcCharSet *fcs, FcChar32 ucs4)
FcCharLeaf *leaf;
FcChar32 *b;
if (fcs == NULL || fcs->ref == FC_REF_CONSTANT)
if (fcs == NULL || FcRefIsConst (&fcs->ref))
return FcFalse;
leaf = FcCharSetFindLeaf (fcs, ucs4);
if (!leaf)
......@@ -329,8 +329,8 @@ FcCharSetCopy (FcCharSet *src)
{
if (src)
{
if (src->ref != FC_REF_CONSTANT)
src->ref++;
if (!FcRefIsConst (&src->ref))
FcRefInc (&src->ref);
else
FcCacheObjectReference (src);
}
......@@ -488,7 +488,7 @@ FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed)
if (!a || !b)
return FcFalse;
if (a->ref == FC_REF_CONSTANT) {
if (FcRefIsConst (&a->ref)) {
if (changed)
*changed = FcFalse;
return FcFalse;
......@@ -1204,7 +1204,7 @@ FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs)
freezer->charsets_allocated++;
ent->set.ref = FC_REF_CONSTANT;
FcRefSetConst (&ent->set.ref);
ent->set.num = fcs->num;
if (fcs->num)
{
......@@ -1338,7 +1338,7 @@ FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
FcChar16 *numbers;
int i;
if (cs->ref != FC_REF_CONSTANT)
if (!FcRefIsConst (&cs->ref))
{
if (!serialize->cs_freezer)
{
......@@ -1377,7 +1377,7 @@ FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
FcCharLeaf *leaf, *leaf_serialized;
int i;
if (cs->ref != FC_REF_CONSTANT && serialize->cs_freezer)
if (!FcRefIsConst (&cs->ref) && serialize->cs_freezer)
{
cs = FcCharSetFindFrozen (serialize->cs_freezer, cs);
if (!cs)
......@@ -1388,7 +1388,7 @@ FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
if (!cs_serialized)
return NULL;
cs_serialized->ref = FC_REF_CONSTANT;
FcRefSetConst (&cs_serialized->ref);
cs_serialized->num = cs->num;
if (cs->num)
......
......@@ -170,7 +170,7 @@ FcDefaultSubstitute (FcPattern *pattern)
FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue);
FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
}
FcSharedStrFree (v2.u.s);
FcSharedStrFree ((char *) v2.u.s);
}
#define __fcdefault__
#include "fcaliastail.h"
......
......@@ -35,6 +35,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <stddef.h>
......@@ -108,6 +109,8 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
#define FcPrivate
#endif
FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int));
typedef enum _FcValueBinding {
FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
} FcValueBinding;
......@@ -188,7 +191,7 @@ struct _FcPattern {
int num;
int size;
intptr_t elts_offset;
int ref;
FcRef ref;
};
#define FcPatternElts(p) FcOffsetMember(p,elts_offset,FcPatternElt)
......@@ -296,7 +299,7 @@ typedef struct _FcCharLeaf {
} FcCharLeaf;
struct _FcCharSet {
int ref; /* reference count */
FcRef ref; /* reference count */
int num; /* size of leaves and numbers arrays */
intptr_t leaves_offset;
intptr_t numbers_offset;
......@@ -309,7 +312,7 @@ struct _FcCharSet {
#define FcCharSetNumbers(c) FcOffsetMember(c,numbers_offset,FcChar16)
struct _FcStrSet {
int ref; /* reference count */
FcRef ref; /* reference count */
int num;
int size;
FcChar8 **strs;
......@@ -497,7 +500,7 @@ struct _FcConfig {
time_t rescanTime; /* last time information was scanned */
int rescanInterval; /* interval between scans */
int ref; /* reference count */
FcRef ref; /* reference count */
FcExprPage *expr_pool; /* pool of FcExpr's */
};
......@@ -525,6 +528,17 @@ struct _FcStatFS {
FcBool is_mtime_broken;
};
typedef struct _FcValuePromotionBuffer FcValuePromotionBuffer;
struct _FcValuePromotionBuffer {
union {
double d;
int i;
long l;
char c[256]; /* Enlarge as needed */
} u;
};
/* fcblanks.c */
/* fccache.c */
......@@ -798,7 +812,7 @@ FcPrivate FcLangResult
FcLangCompare (const FcChar8 *s1, const FcChar8 *s2);
FcPrivate FcLangSet *
FcLangSetPromote (const FcChar8 *lang);
FcLangSetPromote (const FcChar8 *lang, FcValuePromotionBuffer *buf);
FcPrivate FcLangSet *
FcNameParseLangSet (const FcChar8 *string);
......@@ -952,7 +966,7 @@ FcPrivate const FcChar8 *
FcSharedStr (const FcChar8 *name);
FcPrivate FcBool
FcSharedStrFree (const FcChar8 *name);
FcSharedStrFree (FcChar8 *name);
FcPrivate FcChar32
FcStringHash (const FcChar8 *s);
......
......@@ -22,10 +22,11 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <string.h>
#include "fcint.h"
#include "fcftint.h"
/* Objects MT-safe for readonly access. */
typedef struct {
const FcChar8 lang[8];
const FcCharSet charset;
......@@ -702,34 +703,38 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
/*
* Used in computing values -- mustn't allocate any storage
* XXX Not thread-safe
*/
FcLangSet *
FcLangSetPromote (const FcChar8 *lang)
FcLangSetPromote (const FcChar8 *lang, FcValuePromotionBuffer *vbuf)
{
static FcLangSet ls;
static FcStrSet strs;
static FcChar8 *str;
int id;
memset (ls.map, '\0', sizeof (ls.map));
ls.map_size = NUM_LANG_SET_MAP;
ls.extra = 0;
int id;
typedef struct {
FcLangSet ls;
FcStrSet strs;
FcChar8 *str;
} FcLangSetPromotionBuffer;
FcLangSetPromotionBuffer *buf = (FcLangSetPromotionBuffer *) vbuf;
FC_ASSERT_STATIC (sizeof (FcLangSetPromotionBuffer) <= sizeof (FcValuePromotionBuffer));
memset (buf->ls.map, '\0', sizeof (buf->ls.map));
buf->ls.map_size = NUM_LANG_SET_MAP;
buf->ls.extra = 0;
id = FcLangSetIndex (lang);
if (id > 0)
{
FcLangSetBitSet (&ls, id);
FcLangSetBitSet (&buf->ls, id);
}
else
{
ls.extra = &strs;
strs.num = 1;
strs.size = 1;
strs.strs = &str;
strs.ref = 1;
str = (FcChar8 *) lang;
buf->ls.extra = &buf->strs;
buf->strs.num = 1;
buf->strs.size = 1;
buf->strs.strs = &buf->str;
FcRefInit (&buf->strs.ref, 1);
buf->str = (FcChar8 *) lang;
}
return &ls;
return &buf->ls;
}
FcChar32
......
......@@ -23,10 +23,6 @@
*/
#include "fcint.h"
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
static double
FcCompareNumber (FcValue *value1, FcValue *value2)
......
......@@ -36,6 +36,8 @@
#include <config.h>
#endif
#define FC_STMT_START do
#define FC_STMT_END while (0)
/* mutex */
......
......@@ -22,9 +22,8 @@
#include "fcint.h"
#include "fcftint.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* Objects MT-safe for readonly access. */
FcPattern *
FcPatternCreate (void)
......@@ -37,7 +36,7 @@ FcPatternCreate (void)
p->num = 0;
p->size = 0;
p->elts_offset = FcPtrToOffset (p, NULL);
p->ref = 1;
FcRefInit (&p->ref, 1);
return p;
}
......@@ -362,13 +361,13 @@ FcPatternDestroy (FcPattern *p)
if (!p)
return;
if (p->ref == FC_REF_CONSTANT)
if (FcRefIsConst (&p->ref))
{
FcCacheObjectDereference (p);
return;
}
if (--p->ref > 0)
if (FcRefDec (&p->ref) != 1)
return;
elts = FcPatternElts (p);
......@@ -546,7 +545,7 @@ FcPatternObjectListAdd (FcPattern *p,
FcPatternElt *e;
FcValueListPtr l, *prev;
if (p->ref == FC_REF_CONSTANT)
if (FcRefIsConst (&p->ref))
goto bail0;
/*
......@@ -598,7 +597,7 @@ FcPatternObjectAddWithBinding (FcPattern *p,
FcPatternElt *e;
FcValueListPtr new, *prev;
if (p->ref == FC_REF_CONSTANT)
if (FcRefIsConst (&p->ref))
goto bail0;
new = FcValueListCreate ();
......@@ -1060,8 +1059,8 @@ bail0:
void
FcPatternReference (FcPattern *p)
{
if (p->ref != FC_REF_CONSTANT)
p->ref++;
if (!FcRefIsConst (&p->ref))
FcRefInc (&p->ref);
else
FcCacheObjectReference (p);
}
......@@ -1153,7 +1152,7 @@ bail0:
* significant by any means. */
FcBool
FcSharedStrFree (const FcChar8 *name)
FcSharedStrFree (FcChar8 *name)
{
free (name);
return FcTrue;
......@@ -1162,7 +1161,7 @@ FcSharedStrFree (const FcChar8 *name)
const FcChar8 *
FcSharedStr (const FcChar8 *name)
{
return strdup (name);
return strdup ((const char *) name);
}
FcBool
......@@ -1195,7 +1194,7 @@ FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
return NULL;
*pat_serialized = *pat;
pat_serialized->size = pat->num;
pat_serialized->ref = FC_REF_CONSTANT;
FcRefSetConst (&pat_serialized->ref);
elts_serialized = FcSerializePtr (serialize, elts);
if (!elts_serialized)
......
......@@ -33,6 +33,8 @@
#include <windows.h>
#endif
/* Objects MT-safe for readonly access. */
FcChar8 *
FcStrCopy (const FcChar8 *s)
{
......@@ -1078,7 +1080,7 @@ FcStrSetCreate (void)
FcStrSet *set = malloc (sizeof (FcStrSet));
if (!set)
return 0;
set->ref = 1;
FcRefInit (&set->ref, 1);
set->num = 0;
set->size = 0;
set->strs = 0;
......@@ -1230,16 +1232,16 @@ FcStrSetDel (FcStrSet *set, const FcChar8 *s)
void
FcStrSetDestroy (FcStrSet *set)
{
if (--set->ref == 0)
{
int i;
int i;
for (i = 0; i < set->num; i++)
FcStrFree (set->strs[i]);
if (set->strs)
free (set->strs);
free (set);
}
if (FcRefDec (&set->ref) != 1)
return;
for (i = 0; i < set->num; i++)
FcStrFree (set->strs[i]);
if (set->strs)
free (set->strs);
free (set);
}
FcStrList *
......@@ -1251,7 +1253,7 @@ FcStrListCreate (FcStrSet *set)
if (!list)
return 0;
list->set = set;
set->ref++;
FcRefInc (&set->ref);
list->n = 0;
return list;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment