123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- #include <u.h>
- #include <libc.h>
- #include <auth.h>
- #include <fcall.h>
- #include <thread.h>
- #include <9p.h>
- enum {
- NHASH = 128
- };
- typedef struct Intlist Intlist;
- struct Intlist
- {
- ulong id;
- void* aux;
- Intlist* link;
- };
- struct Intmap
- {
- RWLock;
- Intlist* hash[NHASH];
- void (*inc)(void*);
- };
- static ulong
- hashid(ulong id)
- {
- return id%NHASH;
- }
- static void
- nop(void*)
- {
- }
- Intmap*
- allocmap(void (*inc)(void*))
- {
- Intmap *m;
- m = emalloc9p(sizeof(*m));
- if(inc == nil)
- inc = nop;
- m->inc = inc;
- return m;
- }
- void
- freemap(Intmap *map, void (*destroy)(void*))
- {
- int i;
- Intlist *p, *nlink;
- if(destroy == nil)
- destroy = nop;
- for(i=0; i<NHASH; i++){
- for(p=map->hash[i]; p; p=nlink){
- nlink = p->link;
- destroy(p->aux);
- free(p);
- }
- }
-
- free(map);
- }
- static Intlist**
- llookup(Intmap *map, ulong id)
- {
- Intlist **lf;
- for(lf=&map->hash[hashid(id)]; *lf; lf=&(*lf)->link)
- if((*lf)->id == id)
- break;
- return lf;
- }
- /*
- * The RWlock is used as expected except that we allow
- * inc() to be called while holding it. This is because we're
- * locking changes to the tree structure, not to the references.
- * Inc() is expected to have its own locking.
- */
- void*
- lookupkey(Intmap *map, ulong id)
- {
- Intlist *f;
- void *v;
- rlock(map);
- if(f = *llookup(map, id)){
- v = f->aux;
- map->inc(v);
- }else
- v = nil;
- runlock(map);
- return v;
- }
- void*
- insertkey(Intmap *map, ulong id, void *v)
- {
- Intlist *f;
- void *ov;
- ulong h;
- wlock(map);
- if(f = *llookup(map, id)){
- /* no decrement for ov because we're returning it */
- ov = f->aux;
- f->aux = v;
- }else{
- f = emalloc9p(sizeof(*f));
- f->id = id;
- f->aux = v;
- h = hashid(id);
- f->link = map->hash[h];
- map->hash[h] = f;
- ov = nil;
- }
- wunlock(map);
- return ov;
- }
- int
- caninsertkey(Intmap *map, ulong id, void *v)
- {
- Intlist *f;
- int rv;
- ulong h;
- wlock(map);
- if(*llookup(map, id))
- rv = 0;
- else{
- f = emalloc9p(sizeof *f);
- f->id = id;
- f->aux = v;
- h = hashid(id);
- f->link = map->hash[h];
- map->hash[h] = f;
- rv = 1;
- }
- wunlock(map);
- return rv;
- }
- void*
- deletekey(Intmap *map, ulong id)
- {
- Intlist **lf, *f;
- void *ov;
- wlock(map);
- if(f = *(lf = llookup(map, id))){
- ov = f->aux;
- *lf = f->link;
- free(f);
- }else
- ov = nil;
- wunlock(map);
- return ov;
- }
|