intmap.c 2.2 KB

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