Make cache hash threadsafe
This concludes my first pass at making fontconfig threadsafe. Now to testing and actually fixing it!
This commit is contained in:
parent
adb03b730d
commit
68b8ae9af8
|
@ -248,6 +248,7 @@ struct _FcCacheSkip {
|
|||
|
||||
#define FC_CACHE_MAX_LEVEL 16
|
||||
|
||||
/* Protected by cache_lock below */
|
||||
static FcCacheSkip *fcCacheChains[FC_CACHE_MAX_LEVEL];
|
||||
static int fcCacheMaxLevel;
|
||||
|
||||
|
@ -383,6 +384,8 @@ FcCacheInsert (FcCache *cache, struct stat *cache_stat)
|
|||
FcCacheSkip *s, **next;
|
||||
int i, level;
|
||||
|
||||
lock_cache ();
|
||||
|
||||
/*
|
||||
* Find links along each chain
|
||||
*/
|
||||
|
@ -434,11 +437,13 @@ FcCacheInsert (FcCache *cache, struct stat *cache_stat)
|
|||
s->next[i] = *update[i];
|
||||
*update[i] = s;
|
||||
}
|
||||
|
||||
unlock_cache ();
|
||||
return FcTrue;
|
||||
}
|
||||
|
||||
static FcCacheSkip *
|
||||
FcCacheFindByAddr (void *object)
|
||||
FcCacheFindByAddrUnlocked (void *object)
|
||||
{
|
||||
int i;
|
||||
FcCacheSkip **next = fcCacheChains;
|
||||
|
@ -459,6 +464,16 @@ FcCacheFindByAddr (void *object)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static FcCacheSkip *
|
||||
FcCacheFindByAddr (void *object)
|
||||
{
|
||||
FcCacheSkip *ret;
|
||||
lock_cache ();
|
||||
ret = FcCacheFindByAddrUnlocked (object);
|
||||
unlock_cache ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
FcCacheRemove (FcCache *cache)
|
||||
{
|
||||
|
@ -469,6 +484,7 @@ FcCacheRemove (FcCache *cache)
|
|||
/*
|
||||
* Find links along each chain
|
||||
*/
|
||||
lock_cache ();
|
||||
next = fcCacheChains;
|
||||
for (i = fcCacheMaxLevel; --i >= 0; )
|
||||
{
|
||||
|
@ -482,6 +498,7 @@ FcCacheRemove (FcCache *cache)
|
|||
*update[i] = s->next[i];
|
||||
while (fcCacheMaxLevel > 0 && fcCacheChains[fcCacheMaxLevel - 1] == NULL)
|
||||
fcCacheMaxLevel--;
|
||||
unlock_cache ();
|
||||
free (s);
|
||||
}
|
||||
|
||||
|
@ -490,14 +507,17 @@ FcCacheFindByStat (struct stat *cache_stat)
|
|||
{
|
||||
FcCacheSkip *s;
|
||||
|
||||
lock_cache ();
|
||||
for (s = fcCacheChains[0]; s; s = s->next[0])
|
||||
if (s->cache_dev == cache_stat->st_dev &&
|
||||
s->cache_ino == cache_stat->st_ino &&
|
||||
s->cache_mtime == cache_stat->st_mtime)
|
||||
{
|
||||
FcRefInc (&s->ref);
|
||||
unlock_cache ();
|
||||
return s->cache;
|
||||
}
|
||||
unlock_cache ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -987,14 +1007,17 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
|
|||
* new cache file is not read again. If it's large, we don't do that
|
||||
* such that we reload it, using mmap, which is shared across processes.
|
||||
*/
|
||||
if (cache->size < FC_CACHE_MIN_MMAP &&
|
||||
(skip = FcCacheFindByAddr (cache)) &&
|
||||
FcStat (cache_hashed, &cache_stat))
|
||||
if (cache->size < FC_CACHE_MIN_MMAP && FcStat (cache_hashed, &cache_stat))
|
||||
{
|
||||
lock_cache ();
|
||||
if ((skip = FcCacheFindByAddrUnlocked (cache)))
|
||||
{
|
||||
skip->cache_dev = cache_stat.st_dev;
|
||||
skip->cache_ino = cache_stat.st_ino;
|
||||
skip->cache_mtime = cache_stat.st_mtime;
|
||||
}
|
||||
unlock_cache ();
|
||||
}
|
||||
|
||||
FcStrFree (cache_hashed);
|
||||
FcAtomicUnlock (atomic);
|
||||
|
|
Loading…
Reference in New Issue