summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2012-10-07 14:41:38 -0400
committerBehdad Esfahbod <behdad@behdad.org>2013-01-02 00:51:00 -0600
commit64af9e1917114c789ad74dd28b3248f8c0525f45 (patch)
tree31023c299c7cdd6bfc9632e1ae103c8fbf839499 /src
parent814871b2aaa3a22ef711ca4656507fb69c952156 (diff)
Make refcounts, patterns, charsets, strings, and FcLang thread-safe
Diffstat (limited to 'src')
-rw-r--r--src/fcatomic.h18
-rw-r--r--src/fccfg.c29
-rw-r--r--src/fccharset.c24
-rw-r--r--src/fcdefault.c2
-rw-r--r--src/fcint.h26
-rw-r--r--src/fclang.c43
-rw-r--r--src/fcmatch.c4
-rw-r--r--src/fcmutex.h2
-rw-r--r--src/fcpat.c25
-rw-r--r--src/fcstr.c24
10 files changed, 108 insertions, 89 deletions
diff --git a/src/fcatomic.h b/src/fcatomic.h
index 7479a3dd..c066d122 100644
--- a/src/fcatomic.h
+++ b/src/fcatomic.h
@@ -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_ */
diff --git a/src/fccfg.c b/src/fccfg.c
index ef5f4ff2..dd34f5ac 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -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) {
diff --git a/src/fccharset.c b/src/fccharset.c
index df98eb25..c9f928cd 100644
--- a/src/fccharset.c
+++ b/src/fccharset.c
@@ -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)
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 8ad1b1e9..d9778576 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -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"
diff --git a/src/fcint.h b/src/fcint.h
index d881a777..ab4a7e1a 100644
--- a/src/fcint.h
+++ b/src/fcint.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);
diff --git a/src/fclang.c b/src/fclang.c
index d1fadf51..8e9b094b 100644
--- a/src/fclang.c
+++ b/src/fclang.c
@@ -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
diff --git a/src/fcmatch.c b/src/fcmatch.c
index ed245c6c..6778967b 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -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)
diff --git a/src/fcmutex.h b/src/fcmutex.h
index dd4487d4..b10572c8 100644
--- a/src/fcmutex.h
+++ b/src/fcmutex.h
@@ -36,6 +36,8 @@
#include <config.h>
#endif
+#define FC_STMT_START do
+#define FC_STMT_END while (0)
/* mutex */
diff --git a/src/fcpat.c b/src/fcpat.c
index 9d95266a..c3b90d66 100644
--- a/src/fcpat.c
+++ b/src/fcpat.c
@@ -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)
diff --git a/src/fcstr.c b/src/fcstr.c
index 553588fa..e72be5e2 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -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;
}