xref: /plan9/sys/src/lib9p/intmap.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <auth.h>
47dd7cddfSDavid du Colombier #include <fcall.h>
57dd7cddfSDavid du Colombier #include <thread.h>
6*9a747e4fSDavid du Colombier #include <9p.h>
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier enum {
97dd7cddfSDavid du Colombier 	NHASH = 128
107dd7cddfSDavid du Colombier };
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier typedef struct Intlist	Intlist;
137dd7cddfSDavid du Colombier struct Intlist
147dd7cddfSDavid du Colombier {
157dd7cddfSDavid du Colombier 	ulong	id;
167dd7cddfSDavid du Colombier 	void*	aux;
177dd7cddfSDavid du Colombier 	Intlist*	link;
187dd7cddfSDavid du Colombier };
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier struct Intmap
217dd7cddfSDavid du Colombier {
227dd7cddfSDavid du Colombier 	RWLock;
237dd7cddfSDavid du Colombier 	Intlist*	hash[NHASH];
247dd7cddfSDavid du Colombier 	void (*inc)(void*);
257dd7cddfSDavid du Colombier };
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier static ulong
hashid(ulong id)287dd7cddfSDavid du Colombier hashid(ulong id)
297dd7cddfSDavid du Colombier {
307dd7cddfSDavid du Colombier 	return id%NHASH;
317dd7cddfSDavid du Colombier }
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier static void
nop(void *)347dd7cddfSDavid du Colombier nop(void*)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier }
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier Intmap*
allocmap(void (* inc)(void *))397dd7cddfSDavid du Colombier allocmap(void (*inc)(void*))
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier 	Intmap *m;
427dd7cddfSDavid du Colombier 
43*9a747e4fSDavid du Colombier 	m = emalloc9p(sizeof(*m));
447dd7cddfSDavid du Colombier 	if(inc == nil)
457dd7cddfSDavid du Colombier 		inc = nop;
467dd7cddfSDavid du Colombier 	m->inc = inc;
477dd7cddfSDavid du Colombier 	return m;
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier void
freemap(Intmap * map,void (* destroy)(void *))51*9a747e4fSDavid du Colombier freemap(Intmap *map, void (*destroy)(void*))
527dd7cddfSDavid du Colombier {
53*9a747e4fSDavid du Colombier 	int i;
54*9a747e4fSDavid du Colombier 	Intlist *p, *nlink;
55*9a747e4fSDavid du Colombier 
56*9a747e4fSDavid du Colombier 	if(destroy == nil)
57*9a747e4fSDavid du Colombier 		destroy = nop;
58*9a747e4fSDavid du Colombier 	for(i=0; i<NHASH; i++){
59*9a747e4fSDavid du Colombier 		for(p=map->hash[i]; p; p=nlink){
60*9a747e4fSDavid du Colombier 			nlink = p->link;
61*9a747e4fSDavid du Colombier 			destroy(p->aux);
62*9a747e4fSDavid du Colombier 			free(p);
63*9a747e4fSDavid du Colombier 		}
64*9a747e4fSDavid du Colombier 	}
65*9a747e4fSDavid du Colombier 
667dd7cddfSDavid du Colombier 	free(map);
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier static Intlist**
llookup(Intmap * map,ulong id)707dd7cddfSDavid du Colombier llookup(Intmap *map, ulong id)
717dd7cddfSDavid du Colombier {
727dd7cddfSDavid du Colombier 	Intlist **lf;
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier 	for(lf=&map->hash[hashid(id)]; *lf; lf=&(*lf)->link)
757dd7cddfSDavid du Colombier 		if((*lf)->id == id)
767dd7cddfSDavid du Colombier 			break;
777dd7cddfSDavid du Colombier 	return lf;
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier /*
817dd7cddfSDavid du Colombier  * The RWlock is used as expected except that we allow
827dd7cddfSDavid du Colombier  * inc() to be called while holding it.  This is because we're
837dd7cddfSDavid du Colombier  * locking changes to the tree structure, not to the references.
847dd7cddfSDavid du Colombier  * Inc() is expected to have its own locking.
857dd7cddfSDavid du Colombier  */
867dd7cddfSDavid du Colombier void*
lookupkey(Intmap * map,ulong id)877dd7cddfSDavid du Colombier lookupkey(Intmap *map, ulong id)
887dd7cddfSDavid du Colombier {
897dd7cddfSDavid du Colombier 	Intlist *f;
907dd7cddfSDavid du Colombier 	void *v;
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier 	rlock(map);
937dd7cddfSDavid du Colombier 	if(f = *llookup(map, id)){
947dd7cddfSDavid du Colombier 		v = f->aux;
957dd7cddfSDavid du Colombier 		map->inc(v);
967dd7cddfSDavid du Colombier 	}else
977dd7cddfSDavid du Colombier 		v = nil;
987dd7cddfSDavid du Colombier 	runlock(map);
997dd7cddfSDavid du Colombier 	return v;
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier void*
insertkey(Intmap * map,ulong id,void * v)1037dd7cddfSDavid du Colombier insertkey(Intmap *map, ulong id, void *v)
1047dd7cddfSDavid du Colombier {
1057dd7cddfSDavid du Colombier 	Intlist *f;
1067dd7cddfSDavid du Colombier 	void *ov;
1077dd7cddfSDavid du Colombier 	ulong h;
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier 	wlock(map);
1107dd7cddfSDavid du Colombier 	if(f = *llookup(map, id)){
1117dd7cddfSDavid du Colombier 		/* no decrement for ov because we're returning it */
1127dd7cddfSDavid du Colombier 		ov = f->aux;
1137dd7cddfSDavid du Colombier 		f->aux = v;
114*9a747e4fSDavid du Colombier 	}else{
115*9a747e4fSDavid du Colombier 		f = emalloc9p(sizeof(*f));
1167dd7cddfSDavid du Colombier 		f->id = id;
1177dd7cddfSDavid du Colombier 		f->aux = v;
1187dd7cddfSDavid du Colombier 		h = hashid(id);
1197dd7cddfSDavid du Colombier 		f->link = map->hash[h];
1207dd7cddfSDavid du Colombier 		map->hash[h] = f;
1217dd7cddfSDavid du Colombier 		ov = nil;
1227dd7cddfSDavid du Colombier 	}
1237dd7cddfSDavid du Colombier 	wunlock(map);
1247dd7cddfSDavid du Colombier 	return ov;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier int
caninsertkey(Intmap * map,ulong id,void * v)1287dd7cddfSDavid du Colombier caninsertkey(Intmap *map, ulong id, void *v)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier 	Intlist *f;
1317dd7cddfSDavid du Colombier 	int rv;
1327dd7cddfSDavid du Colombier 	ulong h;
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier 	wlock(map);
1357dd7cddfSDavid du Colombier 	if(*llookup(map, id))
1367dd7cddfSDavid du Colombier 		rv = 0;
1377dd7cddfSDavid du Colombier 	else{
138*9a747e4fSDavid du Colombier 		f = emalloc9p(sizeof *f);
1397dd7cddfSDavid du Colombier 		f->id = id;
1407dd7cddfSDavid du Colombier 		f->aux = v;
1417dd7cddfSDavid du Colombier 		h = hashid(id);
1427dd7cddfSDavid du Colombier 		f->link = map->hash[h];
1437dd7cddfSDavid du Colombier 		map->hash[h] = f;
1447dd7cddfSDavid du Colombier 		rv = 1;
1457dd7cddfSDavid du Colombier 	}
1467dd7cddfSDavid du Colombier 	wunlock(map);
1477dd7cddfSDavid du Colombier 	return rv;
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier void*
deletekey(Intmap * map,ulong id)1517dd7cddfSDavid du Colombier deletekey(Intmap *map, ulong id)
1527dd7cddfSDavid du Colombier {
1537dd7cddfSDavid du Colombier 	Intlist **lf, *f;
1547dd7cddfSDavid du Colombier 	void *ov;
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier 	wlock(map);
1577dd7cddfSDavid du Colombier 	if(f = *(lf = llookup(map, id))){
1587dd7cddfSDavid du Colombier 		ov = f->aux;
1597dd7cddfSDavid du Colombier 		*lf = f->link;
1607dd7cddfSDavid du Colombier 		free(f);
161*9a747e4fSDavid du Colombier 	}else
1627dd7cddfSDavid du Colombier 		ov = nil;
1637dd7cddfSDavid du Colombier 	wunlock(map);
1647dd7cddfSDavid du Colombier 	return ov;
1657dd7cddfSDavid du Colombier }
166