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

This commit is contained in:
Behdad Esfahbod 2012-10-07 14:41:38 -04:00
parent 814871b2aa
commit 64af9e1917
10 changed files with 107 additions and 88 deletions

View File

@ -63,7 +63,7 @@ static inline void HBMemoryBarrier (void) {
} }
#endif #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_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
#define fc_atomic_ptr_get(P) (HBMemoryBarrier (), (void *) *(P)) #define fc_atomic_ptr_get(P) (HBMemoryBarrier (), (void *) *(P))
@ -74,7 +74,7 @@ typedef long fc_atomic_int_t;
#include <libkern/OSAtomic.h> #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_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
#define fc_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P)) #define fc_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P))
@ -111,13 +111,13 @@ typedef int fc_atomic_int_t;
#endif #endif
/* reference count */ /* reference count */
#define FC_REF_CONSTANT ((fc_atomic_int_t) -1) #define FC_REF_CONSTANT_VALUE ((fc_atomic_int_t) -1)
#define FC_REF_CONSTANT_INIT {FC_REF_CONSTANT} #define FC_REF_CONSTANT {FC_REF_CONSTANT_VALUE}
typedef struct _FcRef { fc_atomic_int_t count; } FcRef; typedef struct _FcRef { fc_atomic_int_t count; } FcRef;
static inline void FcRefInit (FcRef *r, int v) { r->count = v; } 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 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 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 void FcRefSetConst (FcRef *r) { r->count = FC_REF_CONSTANT_VALUE; }
static inline FcBool FcRefIsConst (FcRef *r) { return r->count == FC_REF_CONSTANT; } static inline FcBool FcRefIsConst (const FcRef *r) { return r->count == FC_REF_CONSTANT_VALUE; }
#endif /* _FCATOMIC_H_ */ #endif /* _FCATOMIC_H_ */

View File

@ -94,7 +94,7 @@ FcConfigCreate (void)
config->expr_pool = NULL; config->expr_pool = NULL;
config->ref = 1; FcRefInit (&config->ref, 1);
return config; return config;
@ -221,7 +221,7 @@ FcConfigReference (FcConfig *config)
return 0; return 0;
} }
config->ref++; FcRefInc (&config->ref);
return config; return config;
} }
@ -232,7 +232,7 @@ FcConfigDestroy (FcConfig *config)
FcSetName set; FcSetName set;
FcExprPage *page; FcExprPage *page;
if (--config->ref > 0) if (FcRefDec (&config->ref) != 1)
return; return;
if (config == _fcConfig) if (config == _fcConfig)
@ -662,7 +662,7 @@ typedef struct _FcSubState {
} FcSubState; } FcSubState;
static FcValue static FcValue
FcConfigPromote (FcValue v, FcValue u) FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
{ {
if (v.type == FcTypeInteger) if (v.type == FcTypeInteger)
{ {
@ -674,9 +674,9 @@ FcConfigPromote (FcValue v, FcValue u)
v.u.m = &FcIdentityMatrix; v.u.m = &FcIdentityMatrix;
v.type = FcTypeMatrix; 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; v.type = FcTypeLangSet;
} }
return v; return v;
@ -692,9 +692,10 @@ FcConfigCompareValue (const FcValue *left_o,
FcBool ret = FcFalse; FcBool ret = FcFalse;
FcOp op = FC_OP_GET_OP (op_); FcOp op = FC_OP_GET_OP (op_);
int flags = FC_OP_GET_FLAGS (op_); int flags = FC_OP_GET_FLAGS (op_);
FcValuePromotionBuffer buf1, buf2;
left = FcConfigPromote (left, right); left = FcConfigPromote (left, right, &buf1);
right = FcConfigPromote (right, left); right = FcConfigPromote (right, left, &buf2);
if (left.type == right.type) if (left.type == right.type)
{ {
switch (left.type) { switch (left.type) {
@ -893,10 +894,10 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e)
FcMatrix m; FcMatrix m;
FcValue xx, xy, yx, yy; FcValue xx, xy, yx, yy;
v.type = FcTypeMatrix; v.type = FcTypeMatrix;
xx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xx), 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); 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); 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); yy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yy), v, NULL);
if (xx.type == FcTypeDouble && xy.type == FcTypeDouble && if (xx.type == FcTypeDouble && xy.type == FcTypeDouble &&
yx.type == FcTypeDouble && yy.type == FcTypeDouble) yx.type == FcTypeDouble && yy.type == FcTypeDouble)
{ {
@ -987,8 +988,8 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e)
case FcOpDivide: case FcOpDivide:
vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right); vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right);
vl = FcConfigPromote (vl, vr); vl = FcConfigPromote (vl, vr, NULL);
vr = FcConfigPromote (vr, vl); vr = FcConfigPromote (vr, vl, NULL);
if (vl.type == vr.type) if (vl.type == vr.type)
{ {
switch ((int) vl.type) { switch ((int) vl.type) {

View File

@ -35,7 +35,7 @@ FcCharSetCreate (void)
fcs = (FcCharSet *) malloc (sizeof (FcCharSet)); fcs = (FcCharSet *) malloc (sizeof (FcCharSet));
if (!fcs) if (!fcs)
return 0; return 0;
fcs->ref = 1; FcRefInit (&fcs->ref, 1);
fcs->num = 0; fcs->num = 0;
fcs->leaves_offset = 0; fcs->leaves_offset = 0;
fcs->numbers_offset = 0; fcs->numbers_offset = 0;
@ -55,12 +55,12 @@ FcCharSetDestroy (FcCharSet *fcs)
if (fcs) if (fcs)
{ {
if (fcs->ref == FC_REF_CONSTANT) if (FcRefIsConst (&fcs->ref))
{ {
FcCacheObjectDereference (fcs); FcCacheObjectDereference (fcs);
return; return;
} }
if (--fcs->ref > 0) if (FcRefDec (&fcs->ref) != 1)
return; return;
for (i = 0; i < fcs->num; i++) for (i = 0; i < fcs->num; i++)
free (FcCharSetLeaf (fcs, i)); free (FcCharSetLeaf (fcs, i));
@ -237,7 +237,7 @@ FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
FcCharLeaf *leaf; FcCharLeaf *leaf;
FcChar32 *b; FcChar32 *b;
if (fcs == NULL || fcs->ref == FC_REF_CONSTANT) if (fcs == NULL || FcRefIsConst (&fcs->ref))
return FcFalse; return FcFalse;
leaf = FcCharSetFindLeafCreate (fcs, ucs4); leaf = FcCharSetFindLeafCreate (fcs, ucs4);
if (!leaf) if (!leaf)
@ -253,7 +253,7 @@ FcCharSetDelChar (FcCharSet *fcs, FcChar32 ucs4)
FcCharLeaf *leaf; FcCharLeaf *leaf;
FcChar32 *b; FcChar32 *b;
if (fcs == NULL || fcs->ref == FC_REF_CONSTANT) if (fcs == NULL || FcRefIsConst (&fcs->ref))
return FcFalse; return FcFalse;
leaf = FcCharSetFindLeaf (fcs, ucs4); leaf = FcCharSetFindLeaf (fcs, ucs4);
if (!leaf) if (!leaf)
@ -329,8 +329,8 @@ FcCharSetCopy (FcCharSet *src)
{ {
if (src) if (src)
{ {
if (src->ref != FC_REF_CONSTANT) if (!FcRefIsConst (&src->ref))
src->ref++; FcRefInc (&src->ref);
else else
FcCacheObjectReference (src); FcCacheObjectReference (src);
} }
@ -488,7 +488,7 @@ FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed)
if (!a || !b) if (!a || !b)
return FcFalse; return FcFalse;
if (a->ref == FC_REF_CONSTANT) { if (FcRefIsConst (&a->ref)) {
if (changed) if (changed)
*changed = FcFalse; *changed = FcFalse;
return FcFalse; return FcFalse;
@ -1204,7 +1204,7 @@ FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs)
freezer->charsets_allocated++; freezer->charsets_allocated++;
ent->set.ref = FC_REF_CONSTANT; FcRefSetConst (&ent->set.ref);
ent->set.num = fcs->num; ent->set.num = fcs->num;
if (fcs->num) if (fcs->num)
{ {
@ -1338,7 +1338,7 @@ FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
FcChar16 *numbers; FcChar16 *numbers;
int i; int i;
if (cs->ref != FC_REF_CONSTANT) if (!FcRefIsConst (&cs->ref))
{ {
if (!serialize->cs_freezer) if (!serialize->cs_freezer)
{ {
@ -1377,7 +1377,7 @@ FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
FcCharLeaf *leaf, *leaf_serialized; FcCharLeaf *leaf, *leaf_serialized;
int i; int i;
if (cs->ref != FC_REF_CONSTANT && serialize->cs_freezer) if (!FcRefIsConst (&cs->ref) && serialize->cs_freezer)
{ {
cs = FcCharSetFindFrozen (serialize->cs_freezer, cs); cs = FcCharSetFindFrozen (serialize->cs_freezer, cs);
if (!cs) if (!cs)
@ -1388,7 +1388,7 @@ FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
if (!cs_serialized) if (!cs_serialized)
return NULL; return NULL;
cs_serialized->ref = FC_REF_CONSTANT; FcRefSetConst (&cs_serialized->ref);
cs_serialized->num = cs->num; cs_serialized->num = cs->num;
if (cs->num) if (cs->num)

View File

@ -170,7 +170,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 (v2.u.s); FcSharedStrFree ((char *) v2.u.s);
} }
#define __fcdefault__ #define __fcdefault__
#include "fcaliastail.h" #include "fcaliastail.h"

View File

@ -35,6 +35,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <stddef.h> #include <stddef.h>
@ -108,6 +109,8 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
#define FcPrivate #define FcPrivate
#endif #endif
FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int));
typedef enum _FcValueBinding { typedef enum _FcValueBinding {
FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
} FcValueBinding; } FcValueBinding;
@ -188,7 +191,7 @@ struct _FcPattern {
int num; int num;
int size; int size;
intptr_t elts_offset; intptr_t elts_offset;
int ref; FcRef ref;
}; };
#define FcPatternElts(p) FcOffsetMember(p,elts_offset,FcPatternElt) #define FcPatternElts(p) FcOffsetMember(p,elts_offset,FcPatternElt)
@ -296,7 +299,7 @@ typedef struct _FcCharLeaf {
} FcCharLeaf; } FcCharLeaf;
struct _FcCharSet { struct _FcCharSet {
int ref; /* reference count */ FcRef ref; /* reference count */
int num; /* size of leaves and numbers arrays */ int num; /* size of leaves and numbers arrays */
intptr_t leaves_offset; intptr_t leaves_offset;
intptr_t numbers_offset; intptr_t numbers_offset;
@ -309,7 +312,7 @@ struct _FcCharSet {
#define FcCharSetNumbers(c) FcOffsetMember(c,numbers_offset,FcChar16) #define FcCharSetNumbers(c) FcOffsetMember(c,numbers_offset,FcChar16)
struct _FcStrSet { struct _FcStrSet {
int ref; /* reference count */ FcRef ref; /* reference count */
int num; int num;
int size; int size;
FcChar8 **strs; FcChar8 **strs;
@ -497,7 +500,7 @@ struct _FcConfig {
time_t rescanTime; /* last time information was scanned */ time_t rescanTime; /* last time information was scanned */
int rescanInterval; /* interval between scans */ int rescanInterval; /* interval between scans */
int ref; /* reference count */ FcRef ref; /* reference count */
FcExprPage *expr_pool; /* pool of FcExpr's */ FcExprPage *expr_pool; /* pool of FcExpr's */
}; };
@ -525,6 +528,17 @@ struct _FcStatFS {
FcBool is_mtime_broken; 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 */ /* fcblanks.c */
/* fccache.c */ /* fccache.c */
@ -798,7 +812,7 @@ FcPrivate FcLangResult
FcLangCompare (const FcChar8 *s1, const FcChar8 *s2); FcLangCompare (const FcChar8 *s1, const FcChar8 *s2);
FcPrivate FcLangSet * FcPrivate FcLangSet *
FcLangSetPromote (const FcChar8 *lang); FcLangSetPromote (const FcChar8 *lang, FcValuePromotionBuffer *buf);
FcPrivate FcLangSet * FcPrivate FcLangSet *
FcNameParseLangSet (const FcChar8 *string); FcNameParseLangSet (const FcChar8 *string);
@ -952,7 +966,7 @@ FcPrivate const FcChar8 *
FcSharedStr (const FcChar8 *name); FcSharedStr (const FcChar8 *name);
FcPrivate FcBool FcPrivate FcBool
FcSharedStrFree (const FcChar8 *name); FcSharedStrFree (FcChar8 *name);
FcPrivate FcChar32 FcPrivate FcChar32
FcStringHash (const FcChar8 *s); FcStringHash (const FcChar8 *s);

View File

@ -22,10 +22,11 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <string.h>
#include "fcint.h" #include "fcint.h"
#include "fcftint.h" #include "fcftint.h"
/* Objects MT-safe for readonly access. */
typedef struct { typedef struct {
const FcChar8 lang[8]; const FcChar8 lang[8];
const FcCharSet charset; const FcCharSet charset;
@ -702,34 +703,38 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
/* /*
* Used in computing values -- mustn't allocate any storage * Used in computing values -- mustn't allocate any storage
* XXX Not thread-safe
*/ */
FcLangSet * FcLangSet *
FcLangSetPromote (const FcChar8 *lang) FcLangSetPromote (const FcChar8 *lang, FcValuePromotionBuffer *vbuf)
{ {
static FcLangSet ls;
static FcStrSet strs;
static FcChar8 *str;
int id; int id;
typedef struct {
FcLangSet ls;
FcStrSet strs;
FcChar8 *str;
} FcLangSetPromotionBuffer;
FcLangSetPromotionBuffer *buf = (FcLangSetPromotionBuffer *) vbuf;
memset (ls.map, '\0', sizeof (ls.map)); FC_ASSERT_STATIC (sizeof (FcLangSetPromotionBuffer) <= sizeof (FcValuePromotionBuffer));
ls.map_size = NUM_LANG_SET_MAP;
ls.extra = 0; memset (buf->ls.map, '\0', sizeof (buf->ls.map));
buf->ls.map_size = NUM_LANG_SET_MAP;
buf->ls.extra = 0;
id = FcLangSetIndex (lang); id = FcLangSetIndex (lang);
if (id > 0) if (id > 0)
{ {
FcLangSetBitSet (&ls, id); FcLangSetBitSet (&buf->ls, id);
} }
else else
{ {
ls.extra = &strs; buf->ls.extra = &buf->strs;
strs.num = 1; buf->strs.num = 1;
strs.size = 1; buf->strs.size = 1;
strs.strs = &str; buf->strs.strs = &buf->str;
strs.ref = 1; FcRefInit (&buf->strs.ref, 1);
str = (FcChar8 *) lang; buf->str = (FcChar8 *) lang;
} }
return &ls; return &buf->ls;
} }
FcChar32 FcChar32

View File

@ -23,10 +23,6 @@
*/ */
#include "fcint.h" #include "fcint.h"
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
static double static double
FcCompareNumber (FcValue *value1, FcValue *value2) FcCompareNumber (FcValue *value1, FcValue *value2)

View File

@ -36,6 +36,8 @@
#include <config.h> #include <config.h>
#endif #endif
#define FC_STMT_START do
#define FC_STMT_END while (0)
/* mutex */ /* mutex */

View File

@ -22,9 +22,8 @@
#include "fcint.h" #include "fcint.h"
#include "fcftint.h" #include "fcftint.h"
#include <stdlib.h>
#include <string.h> /* Objects MT-safe for readonly access. */
#include <assert.h>
FcPattern * FcPattern *
FcPatternCreate (void) FcPatternCreate (void)
@ -37,7 +36,7 @@ FcPatternCreate (void)
p->num = 0; p->num = 0;
p->size = 0; p->size = 0;
p->elts_offset = FcPtrToOffset (p, NULL); p->elts_offset = FcPtrToOffset (p, NULL);
p->ref = 1; FcRefInit (&p->ref, 1);
return p; return p;
} }
@ -362,13 +361,13 @@ FcPatternDestroy (FcPattern *p)
if (!p) if (!p)
return; return;
if (p->ref == FC_REF_CONSTANT) if (FcRefIsConst (&p->ref))
{ {
FcCacheObjectDereference (p); FcCacheObjectDereference (p);
return; return;
} }
if (--p->ref > 0) if (FcRefDec (&p->ref) != 1)
return; return;
elts = FcPatternElts (p); elts = FcPatternElts (p);
@ -546,7 +545,7 @@ FcPatternObjectListAdd (FcPattern *p,
FcPatternElt *e; FcPatternElt *e;
FcValueListPtr l, *prev; FcValueListPtr l, *prev;
if (p->ref == FC_REF_CONSTANT) if (FcRefIsConst (&p->ref))
goto bail0; goto bail0;
/* /*
@ -598,7 +597,7 @@ FcPatternObjectAddWithBinding (FcPattern *p,
FcPatternElt *e; FcPatternElt *e;
FcValueListPtr new, *prev; FcValueListPtr new, *prev;
if (p->ref == FC_REF_CONSTANT) if (FcRefIsConst (&p->ref))
goto bail0; goto bail0;
new = FcValueListCreate (); new = FcValueListCreate ();
@ -1060,8 +1059,8 @@ bail0:
void void
FcPatternReference (FcPattern *p) FcPatternReference (FcPattern *p)
{ {
if (p->ref != FC_REF_CONSTANT) if (!FcRefIsConst (&p->ref))
p->ref++; FcRefInc (&p->ref);
else else
FcCacheObjectReference (p); FcCacheObjectReference (p);
} }
@ -1153,7 +1152,7 @@ bail0:
* significant by any means. */ * significant by any means. */
FcBool FcBool
FcSharedStrFree (const FcChar8 *name) FcSharedStrFree (FcChar8 *name)
{ {
free (name); free (name);
return FcTrue; return FcTrue;
@ -1162,7 +1161,7 @@ FcSharedStrFree (const FcChar8 *name)
const FcChar8 * const FcChar8 *
FcSharedStr (const FcChar8 *name) FcSharedStr (const FcChar8 *name)
{ {
return strdup (name); return strdup ((const char *) name);
} }
FcBool FcBool
@ -1195,7 +1194,7 @@ FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
return NULL; return NULL;
*pat_serialized = *pat; *pat_serialized = *pat;
pat_serialized->size = pat->num; pat_serialized->size = pat->num;
pat_serialized->ref = FC_REF_CONSTANT; FcRefSetConst (&pat_serialized->ref);
elts_serialized = FcSerializePtr (serialize, elts); elts_serialized = FcSerializePtr (serialize, elts);
if (!elts_serialized) if (!elts_serialized)

View File

@ -33,6 +33,8 @@
#include <windows.h> #include <windows.h>
#endif #endif
/* Objects MT-safe for readonly access. */
FcChar8 * FcChar8 *
FcStrCopy (const FcChar8 *s) FcStrCopy (const FcChar8 *s)
{ {
@ -1078,7 +1080,7 @@ FcStrSetCreate (void)
FcStrSet *set = malloc (sizeof (FcStrSet)); FcStrSet *set = malloc (sizeof (FcStrSet));
if (!set) if (!set)
return 0; return 0;
set->ref = 1; FcRefInit (&set->ref, 1);
set->num = 0; set->num = 0;
set->size = 0; set->size = 0;
set->strs = 0; set->strs = 0;
@ -1229,18 +1231,18 @@ FcStrSetDel (FcStrSet *set, const FcChar8 *s)
void void
FcStrSetDestroy (FcStrSet *set) FcStrSetDestroy (FcStrSet *set)
{
if (--set->ref == 0)
{ {
int i; int i;
if (FcRefDec (&set->ref) != 1)
return;
for (i = 0; i < set->num; i++) for (i = 0; i < set->num; i++)
FcStrFree (set->strs[i]); FcStrFree (set->strs[i]);
if (set->strs) if (set->strs)
free (set->strs); free (set->strs);
free (set); free (set);
} }
}
FcStrList * FcStrList *
FcStrListCreate (FcStrSet *set) FcStrListCreate (FcStrSet *set)
@ -1251,7 +1253,7 @@ FcStrListCreate (FcStrSet *set)
if (!list) if (!list)
return 0; return 0;
list->set = set; list->set = set;
set->ref++; FcRefInc (&set->ref);
list->n = 0; list->n = 0;
return list; return list;
} }