map.c (2329B)
1 /* Written by Kris Maglione */ 2 /* Public domain */ 3 #include <stdlib.h> 4 #include "ixp_local.h" 5 6 /* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g x/^([^a-zA-Z]|static|$)/-+d s/ (\*map|val|*str)//g */ 7 8 struct MapEnt { 9 ulong hash; 10 const char* key; 11 void* val; 12 MapEnt* next; 13 }; 14 15 MapEnt *NM; 16 17 static void 18 insert(MapEnt **e, ulong val, const char *key) { 19 MapEnt *te; 20 21 te = emallocz(sizeof *te); 22 te->hash = val; 23 te->key = key; 24 te->next = *e; 25 *e = te; 26 } 27 28 static MapEnt** 29 map_getp(IxpMap *map, ulong val, bool create, bool *exists) { 30 MapEnt **e; 31 32 e = &map->bucket[val%map->nhash]; 33 for(; *e; e = &(*e)->next) 34 if((*e)->hash >= val) break; 35 if(exists) 36 *exists = *e && (*e)->hash == val; 37 38 if(*e == nil || (*e)->hash != val) { 39 if(create) 40 insert(e, val, nil); 41 else 42 e = &NM; 43 } 44 return e; 45 } 46 47 void 48 ixp_mapfree(IxpMap *map, void (*destroy)(void*)) { 49 int i; 50 MapEnt *e; 51 52 thread->wlock(&map->lock); 53 for(i=0; i < map->nhash; i++) 54 while((e = map->bucket[i])) { 55 map->bucket[i] = e->next; 56 if(destroy) 57 destroy(e->val); 58 free(e); 59 } 60 thread->wunlock(&map->lock); 61 thread->rwdestroy(&map->lock); 62 } 63 64 void 65 ixp_mapexec(IxpMap *map, void (*run)(void*, void*), void *context) { 66 int i; 67 MapEnt *e; 68 69 thread->rlock(&map->lock); 70 for(i=0; i < map->nhash; i++) 71 for(e=map->bucket[i]; e; e=e->next) 72 run(context, e->val); 73 thread->runlock(&map->lock); 74 } 75 76 void 77 ixp_mapinit(IxpMap *map, MapEnt **buckets, int nbuckets) { 78 79 map->bucket = buckets; 80 map->nhash = nbuckets; 81 82 thread->initrwlock(&map->lock); 83 } 84 85 bool 86 ixp_mapinsert(IxpMap *map, ulong key, void *val, bool overwrite) { 87 MapEnt *e; 88 bool existed, res; 89 90 res = true; 91 thread->wlock(&map->lock); 92 e = *map_getp(map, key, true, &existed); 93 if(existed && !overwrite) 94 res = false; 95 else 96 e->val = val; 97 thread->wunlock(&map->lock); 98 return res; 99 } 100 101 void* 102 ixp_mapget(IxpMap *map, ulong val) { 103 MapEnt *e; 104 void *res; 105 106 thread->rlock(&map->lock); 107 e = *map_getp(map, val, false, nil); 108 res = e ? e->val : nil; 109 thread->runlock(&map->lock); 110 return res; 111 } 112 113 void* 114 ixp_maprm(IxpMap *map, ulong val) { 115 MapEnt **e, *te; 116 void *ret; 117 118 ret = nil; 119 thread->wlock(&map->lock); 120 e = map_getp(map, val, false, nil); 121 if(*e) { 122 te = *e; 123 ret = te->val; 124 *e = te->next; 125 thread->wunlock(&map->lock); 126 free(te); 127 } 128 else 129 thread->wunlock(&map->lock); 130 return ret; 131 } 132