diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/lib9p/intmap.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/lib9p/intmap.c')
-rwxr-xr-x | sys/src/lib9p/intmap.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/sys/src/lib9p/intmap.c b/sys/src/lib9p/intmap.c new file mode 100755 index 000000000..40e886e8b --- /dev/null +++ b/sys/src/lib9p/intmap.c @@ -0,0 +1,165 @@ +#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; +} |