MWCC/command_line/CmdLine/Src/CLIncludeFileCache.c

160 lines
3.4 KiB
C

#include "cmdline.h"
typedef struct CacheEntry {
struct CacheEntry *next;
struct CacheEntry *prev;
int locked;
int precompiled;
Handle text;
OSSpec spec;
UInt32 size;
UInt32 when;
} CacheEntry;
enum {
CACHE_SIZE = 0x800000
};
static CacheEntry *cachelist;
static CacheEntry *freelist;
static UInt32 availablecache;
static CacheEntry *makecacheentry(void) {
CacheEntry *c = freelist;
if (c) {
freelist = c->next;
return c;
} else {
return xmalloc("include file cache", sizeof(CacheEntry));
}
}
static void insertcacheentry(CacheEntry *c) {
if (cachelist)
cachelist->prev = c;
c->next = cachelist;
c->prev = NULL;
cachelist = c;
}
static void deletecacheentry(CacheEntry *c) {
if (c->next)
c->next->prev = c->prev;
if (c->prev)
c->prev->next = c->next;
else
cachelist = c->next;
}
void InitializeIncludeCache(void) {
freelist = NULL;
cachelist = NULL;
availablecache = CACHE_SIZE;
}
void CleanupIncludeCache(void) {
CacheEntry *c;
CacheEntry *c1;
for (c = cachelist; c; c = c1) {
c1 = c->next;
if (c->text)
DisposeHandle(c->text);
xfree(c);
}
for (c = freelist; c; c = c1) {
c1 = c->next;
xfree(c);
}
InitializeIncludeCache();
}
void CacheIncludeFile(OSSpec *spec, Handle text, Boolean precompiled) {
UInt32 size;
CacheEntry *c;
CacheEntry *lru;
size = GetHandleSize(text);
if (precompiled) {
lru = NULL;
for (c = cachelist; c; c = c->next) {
if (c->precompiled) {
lru = c;
break;
}
}
if (lru) {
DisposeHandle(lru->text);
lru->text = NULL;
deletecacheentry(lru);
lru->next = freelist;
freelist = lru;
}
} else {
if ((SInt32) size > (SInt32) CACHE_SIZE) {
return;
} else {
while (size > availablecache) {
lru = NULL;
for (c = cachelist; c; c = c->next) {
if (!c->locked && !c->precompiled && (lru == NULL || c->when < lru->when))
lru = c;
}
if (lru) {
DisposeHandle(lru->text);
lru->text = NULL;
availablecache += lru->size;
deletecacheentry(lru);
lru->next = freelist;
freelist = lru;
} else {
return;
}
}
}
}
c = makecacheentry();
c->locked = 1;
c->precompiled = precompiled;
c->spec = *spec;
c->text = text;
c->size = size;
c->when = OS_GetMilliseconds();
insertcacheentry(c);
if (!precompiled)
availablecache -= size;
}
Handle CachedIncludeFile(OSSpec *spec, Boolean *precompiled) {
CacheEntry *c;
for (c = cachelist; c; c = c->next) {
if (OS_EqualSpec(&c->spec, spec)) {
c->when = OS_GetMilliseconds();
*precompiled = c->precompiled;
c->locked++;
return c->text;
}
}
return NULL;
}
void FreeIncludeFile(Handle text) {
CacheEntry *c;
for (c = cachelist; c; c = c->next) {
if (c->text == text) {
c->locked--;
return;
}
}
DisposeHandle(text);
}