1
0

Set.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #define Set_NOCREATE
  16. #include "util/Set.h"
  17. #include "util/Bits.h"
  18. #include <stddef.h>
  19. #include <stdlib.h>
  20. #include <node_build/dependencies/tree.h>
  21. struct Entry {
  22. void* data;
  23. uint32_t hashCode;
  24. struct Allocator* alloc;
  25. struct Set_pvt* set;
  26. struct {
  27. struct Entry* rbe_left;
  28. struct Entry* rbe_right;
  29. struct Entry* rbe_parent;
  30. int rbe_color;
  31. } tree;
  32. };
  33. #define BLOCK_SZ 8
  34. struct Block {
  35. int usedCount;
  36. int number;
  37. struct Block* next;
  38. struct Allocator* alloc;
  39. struct Entry entries[BLOCK_SZ];
  40. };
  41. struct Set_Iter
  42. {
  43. void* val;
  44. struct Entry* entry;
  45. };
  46. struct Set_pvt
  47. {
  48. int size;
  49. struct Allocator* alloc;
  50. struct Block* block;
  51. struct ActiveTree {
  52. struct Entry* rbh_root;
  53. } activeTree;
  54. struct FreeTree {
  55. struct Entry* rbh_root;
  56. } freeTree;
  57. Set_Compare_t compare;
  58. Set_HashCode_t hashCode;
  59. Identity
  60. };
  61. static int compare(const struct Entry* a, const struct Entry* b)
  62. {
  63. if (a->hashCode != b->hashCode) { return a->hashCode - b->hashCode; }
  64. struct Set_pvt* set = Identity_check((struct Set_pvt*) a->set);
  65. return set->compare(a->data, b->data);
  66. }
  67. RB_GENERATE_STATIC(ActiveTree, Entry, tree, compare)
  68. static int freeCompare(const struct Entry* a, const struct Entry* b)
  69. {
  70. return a->hashCode - b->hashCode;
  71. }
  72. RB_GENERATE_STATIC(FreeTree, Entry, tree, freeCompare)
  73. static struct Block* blockForEntry(const struct Set_pvt* set, const struct Entry* e)
  74. {
  75. struct Block* b = set->block;
  76. uintptr_t ep = (uintptr_t) e;
  77. while (b) {
  78. if (ep >= (uintptr_t)&b->entries && ep < (uintptr_t)&b->entries[BLOCK_SZ]) { return b; }
  79. b = b->next;
  80. }
  81. Assert_failure("No matching block for entry");
  82. }
  83. static struct Entry* allocateBlock(struct Set_pvt* set)
  84. {
  85. struct Allocator* alloc = Allocator_child(set->alloc);
  86. struct Block* newBlock = Allocator_calloc(alloc, sizeof(struct Block), 1);
  87. newBlock->alloc = alloc;
  88. newBlock->next = set->block;
  89. set->block = newBlock;
  90. uint32_t num = newBlock->number = (set->block ? set->block->number : -1) + 1;
  91. for (int i = 0; i < BLOCK_SZ; i++) {
  92. newBlock->entries[i].set = set;
  93. newBlock->entries[i].hashCode = num;
  94. FreeTree_RB_INSERT(&set->freeTree, &newBlock->entries[i]);
  95. }
  96. return &newBlock->entries[0];
  97. }
  98. static struct Entry* newEntry(struct Set_pvt* set)
  99. {
  100. struct Entry* e = RB_MIN(FreeTree, &set->freeTree);
  101. if (!e) { e = allocateBlock(set); }
  102. FreeTree_RB_REMOVE(&set->freeTree, e);
  103. struct Block* b = blockForEntry(set, e);
  104. b->usedCount++;
  105. set->size++;
  106. return e;
  107. }
  108. static void freeBlock(struct Set_pvt* set, struct Block* b)
  109. {
  110. for (int i = 0; i < BLOCK_SZ; i++) {
  111. FreeTree_RB_REMOVE(&set->freeTree, &b->entries[i]);
  112. }
  113. int ok = 0;
  114. for (struct Block** bp = &set->block; *bp; bp = &(*bp)->next) {
  115. if (*bp == b) {
  116. *bp = b->next;
  117. ok = 1;
  118. break;
  119. }
  120. }
  121. Assert_true(ok && "INTERNAL: block was not linked into linked list");
  122. Allocator_free(b->alloc);
  123. }
  124. static void freeEntry(struct Set_pvt* set, struct Entry* e)
  125. {
  126. struct Block* b = blockForEntry(set, e);
  127. ActiveTree_RB_REMOVE(&set->activeTree, e);
  128. e->data = NULL;
  129. e->hashCode = b->number;
  130. if (e->alloc) {
  131. Allocator_free(e->alloc);
  132. e->alloc = NULL;
  133. }
  134. FreeTree_RB_INSERT(&set->freeTree, e);
  135. b->usedCount--;
  136. set->size--;
  137. if (!b->usedCount) { freeBlock(set, b); }
  138. }
  139. static struct Entry* get(struct Set_pvt* set, void* val, uint32_t hashCode)
  140. {
  141. struct Entry e = {
  142. .hashCode = hashCode,
  143. .data = val,
  144. .set = set
  145. };
  146. return ActiveTree_RB_FIND(&set->activeTree, &e);
  147. }
  148. int Set_addCopy(struct Set* _set, void* val, uint32_t size)
  149. {
  150. struct Set_pvt* set = Identity_check((struct Set_pvt*) _set);
  151. uint32_t hashCode = set->hashCode(val);
  152. struct Entry* e = get(set, val, hashCode);
  153. if (!e) {
  154. struct Entry* e = newEntry(set);
  155. e->hashCode = hashCode;
  156. ActiveTree_RB_INSERT(&set->activeTree, e);
  157. struct Block* b = blockForEntry(set, e);
  158. e->alloc = Allocator_child(b->alloc);
  159. e->data = Allocator_malloc(e->alloc, size);
  160. Bits_memcpy(e->data, val, size);
  161. }
  162. return set->size;
  163. }
  164. int Set_add(struct Set* _set, void* val)
  165. {
  166. struct Set_pvt* set = Identity_check((struct Set_pvt*) _set);
  167. uint32_t hashCode = set->hashCode(val);
  168. struct Entry* e = get(set, val, hashCode);
  169. if (!e) {
  170. struct Entry* e = newEntry(set);
  171. e->data = val;
  172. e->hashCode = hashCode;
  173. ActiveTree_RB_INSERT(&set->activeTree, e);
  174. }
  175. return set->size;
  176. }
  177. void Set_iter(struct Set* _set, struct Set_Iter* iter)
  178. {
  179. struct Set_pvt* set = Identity_check((struct Set_pvt*) _set);
  180. struct Entry* e = iter->entry = RB_MIN(ActiveTree, &set->activeTree);
  181. if (e) {
  182. iter->val = e->data;
  183. iter->entry = ActiveTree_RB_NEXT(e);
  184. } else {
  185. iter->val = NULL;
  186. }
  187. }
  188. void Set_iterNext(struct Set_Iter* iter)
  189. {
  190. struct Entry* e = iter->entry;
  191. if (e) {
  192. iter->val = e->data;
  193. iter->entry = ActiveTree_RB_NEXT(e);
  194. } else {
  195. iter->val = NULL;
  196. }
  197. }
  198. void* Set_remove(struct Set* _set, void* val)
  199. {
  200. struct Set_pvt* set = Identity_check((struct Set_pvt*) _set);
  201. struct Entry* e = get(set, val, set->hashCode(val));
  202. void* out = NULL;
  203. if (e) {
  204. out = e->data;
  205. freeEntry(set, e);
  206. }
  207. return out;
  208. }
  209. void* Set_get(struct Set* _set, void* val)
  210. {
  211. struct Set_pvt* set = Identity_check((struct Set_pvt*) _set);
  212. struct Entry* e = get(set, val, set->hashCode(val));
  213. void* out = NULL;
  214. if (e) { out = e->data; }
  215. return out;
  216. }
  217. struct Set* Set_new(struct Allocator* alloc, Set_HashCode_t hashCode, Set_Compare_t compare)
  218. {
  219. struct Set_pvt* out = Allocator_calloc(alloc, sizeof(struct Set_pvt), 1);
  220. Identity_set(out);
  221. out->alloc = alloc;
  222. out->compare = compare;
  223. out->hashCode = hashCode;
  224. return (struct Set*) out;
  225. }