URI:
       tintmap.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tintmap.c (2322B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <fcall.h>
            4 #include <thread.h>
            5 #include <9p.h>
            6 
            7 enum {
            8         NHASH = 128
            9 };
           10 
           11 typedef struct Intlist        Intlist;
           12 struct Intlist
           13 {
           14         ulong        id;
           15         void*        aux;
           16         Intlist*        link;
           17 };
           18 
           19 struct Intmap
           20 {
           21         RWLock        rwlock;
           22         Intlist*        hash[NHASH];
           23         void (*inc)(void*);
           24 };
           25 
           26 static ulong
           27 hashid(ulong id)
           28 {
           29         return id%NHASH;
           30 }
           31 
           32 static void
           33 nop(void *v)
           34 {
           35         USED(v);
           36 }
           37 
           38 Intmap*
           39 allocmap(void (*inc)(void*))
           40 {
           41         Intmap *m;
           42 
           43         m = emalloc9p(sizeof(*m));
           44         if(inc == nil)
           45                 inc = nop;
           46         m->inc = inc;
           47         return m;
           48 }
           49 
           50 void
           51 freemap(Intmap *map, void (*destroy)(void*))
           52 {
           53         int i;
           54         Intlist *p, *nlink;
           55 
           56         if(destroy == nil)
           57                 destroy = nop;
           58         for(i=0; i<NHASH; i++){
           59                 for(p=map->hash[i]; p; p=nlink){
           60                         nlink = p->link;
           61                         destroy(p->aux);
           62                         free(p);
           63                 }
           64         }
           65 
           66         free(map);
           67 }
           68 
           69 static Intlist**
           70 llookup(Intmap *map, ulong id)
           71 {
           72         Intlist **lf;
           73 
           74         for(lf=&map->hash[hashid(id)]; *lf; lf=&(*lf)->link)
           75                 if((*lf)->id == id)
           76                         break;
           77         return lf;
           78 }
           79 
           80 /*
           81  * The RWlock is used as expected except that we allow
           82  * inc() to be called while holding it.  This is because we're
           83  * locking changes to the tree structure, not to the references.
           84  * Inc() is expected to have its own locking.
           85  */
           86 void*
           87 lookupkey(Intmap *map, ulong id)
           88 {
           89         Intlist *f;
           90         void *v;
           91 
           92         rlock(&map->rwlock);
           93         if(f = *llookup(map, id)){
           94                 v = f->aux;
           95                 map->inc(v);
           96         }else
           97                 v = nil;
           98         runlock(&map->rwlock);
           99         return v;
          100 }
          101 
          102 void*
          103 insertkey(Intmap *map, ulong id, void *v)
          104 {
          105         Intlist *f;
          106         void *ov;
          107         ulong h;
          108 
          109         wlock(&map->rwlock);
          110         if(f = *llookup(map, id)){
          111                 /* no decrement for ov because we're returning it */
          112                 ov = f->aux;
          113                 f->aux = v;
          114         }else{
          115                 f = emalloc9p(sizeof(*f));
          116                 f->id = id;
          117                 f->aux = v;
          118                 h = hashid(id);
          119                 f->link = map->hash[h];
          120                 map->hash[h] = f;
          121                 ov = nil;
          122         }
          123         wunlock(&map->rwlock);
          124         return ov;
          125 }
          126 
          127 int
          128 caninsertkey(Intmap *map, ulong id, void *v)
          129 {
          130         Intlist *f;
          131         int rv;
          132         ulong h;
          133 
          134         wlock(&map->rwlock);
          135         if(*llookup(map, id))
          136                 rv = 0;
          137         else{
          138                 f = emalloc9p(sizeof *f);
          139                 f->id = id;
          140                 f->aux = v;
          141                 h = hashid(id);
          142                 f->link = map->hash[h];
          143                 map->hash[h] = f;
          144                 rv = 1;
          145         }
          146         wunlock(&map->rwlock);
          147         return rv;
          148 }
          149 
          150 void*
          151 deletekey(Intmap *map, ulong id)
          152 {
          153         Intlist **lf, *f;
          154         void *ov;
          155 
          156         wlock(&map->rwlock);
          157         if(f = *(lf = llookup(map, id))){
          158                 ov = f->aux;
          159                 *lf = f->link;
          160                 free(f);
          161         }else
          162                 ov = nil;
          163         wunlock(&map->rwlock);
          164         return ov;
          165 }