Blob
1 #include "a.h"3 struct Cache4 {5 CEntry **hash;6 int nhash;7 CEntry *head;8 CEntry *tail;9 int nentry;10 int maxentry;11 int sizeofentry;12 void (*cefree)(CEntry*);13 };15 static void16 nop(CEntry *ce)17 {18 }20 static uint21 hash(const char *s)22 {23 uint h;24 uchar *p;26 h = 0;27 for(p=(uchar*)s; *p; p++)28 h = h*37 + *p;29 return h;30 }32 Cache*33 newcache(int sizeofentry, int maxentry, void (*cefree)(CEntry*))34 {35 Cache *c;36 int i;38 assert(sizeofentry >= sizeof(CEntry));39 c = emalloc(sizeof *c);40 c->sizeofentry = sizeofentry;41 c->maxentry = maxentry;42 c->nentry = 0;43 for(i=1; i<maxentry; i<<=1)44 ;45 c->nhash = i;46 c->hash = emalloc(c->nhash * sizeof c->hash[0]);47 if(cefree == nil)48 cefree = nop;49 c->cefree = cefree;50 return c;51 }53 static void54 popout(Cache *c, CEntry *e)55 {56 if(e->list.prev)57 e->list.prev->list.next = e->list.next;58 else59 c->head = e->list.next;60 if(e->list.next)61 e->list.next->list.prev = e->list.prev;62 else63 c->tail = e->list.prev;64 }66 static void67 insertfront(Cache *c, CEntry *e)68 {69 e->list.next = c->head;70 c->head = e;71 if(e->list.next)72 e->list.next->list.prev = e;73 else74 c->tail = e;75 }77 static void78 movetofront(Cache *c, CEntry *e)79 {80 popout(c, e);81 insertfront(c, e);82 }84 static CEntry*85 evict(Cache *c)86 {87 CEntry *e;89 e = c->tail;90 popout(c, e);91 c->cefree(e);92 free(e->name);93 e->name = nil;94 memset(e, 0, c->sizeofentry);95 insertfront(c, e);96 return e;97 }99 CEntry*100 cachelookup(Cache *c, char *name, int create)101 {102 int h;103 CEntry *e;105 h = hash(name) % c->nhash;106 for(e=c->hash[h]; e; e=e->hash.next){107 if(strcmp(name, e->name) == 0){108 movetofront(c, e);109 return e;110 }111 }113 if(!create)114 return nil;116 if(c->nentry >= c->maxentry)117 e = evict(c);118 else{119 e = emalloc(c->sizeofentry);120 insertfront(c, e);121 c->nentry++;122 }123 e->name = estrdup(name);124 h = hash(name) % c->nhash;125 e->hash.next = c->hash[h];126 c->hash[h] = e;127 return e;128 }130 void131 cacheflush(Cache *c, char *substr)132 {133 CEntry **l, *e;134 int i;136 for(i=0; i<c->nhash; i++){137 for(l=&c->hash[i]; (e=*l); ){138 if(substr == nil || strstr(e->name, substr)){139 *l = e->hash.next;140 c->nentry--;141 popout(c, e);142 c->cefree(e);143 free(e->name);144 free(e);145 }else146 l = &e->hash.next;147 }148 }149 }