// Make a new hash table, with SIZE buckets initially. // Hash table and its elements are allocated in region r. HASH_FUNC_INLINE hashset_table make_hashset_table(region r, unsigned long size //, // hash_fn hash, keyeq_fn cmp ) { #if HASHSET_TABLE_SUPPORT_REGION if (!r) return make_hashset_table_owner(size /*, hash, cmp */); hashset_table ht; ht = ralloc(r, struct Hashset_table); ht->r = r; // ht->hash = hash; // ht->cmp = cmp; ht->used = 0; if (size) { size = hashset_init_size_pow2(ht, size); ht->table = rarrayalloc(ht->r, size, hash_key); } else { ht->log2size = 0; ht->table = NULL; } return ht; #else assert(r == NULL); return make_hashset_table_owner(size); #endif }
/* Serialization */ void serialize_start(FILE *f, serialize_fn_ptr kind_map[], int length) { assert(current_state == persist_raw); assert(f); persist_rgn = newregion(); current_state = persist_serializing; serialize_queue = new_persist_entry_queue(persist_rgn); serialized_objects = make_hash_table(persist_rgn, 128, ptr_hash, ptr_eq); current_file = f; num_kinds = length; serialize_fns = rarrayalloc(persist_rgn, length, serialize_fn_ptr); rarraycopy(serialize_fns, kind_map, length, serialize_fn_ptr); }
static void add_cfg_node(region r, function_decl fd, void *n) { if (fd->cfg_nextnode >= fd->cfg_size) { long oldsize = fd->cfg_size; node parentptr *oldnodes = fd->cfg_nodes; long newsize = 2 * oldsize, i; node parentptr *newnodes = rarrayalloc(r, newsize, node parentptr); for (i = 0; i < oldsize; i++) newnodes[i] = oldnodes[i]; fd->cfg_size = newsize; fd->cfg_nodes = newnodes; } fd->cfg_nodes[fd->cfg_nextnode++] = CAST(node, n); }
/* Reinsert all elements. New size of table is (used*2) rounded up to a power of 2. Duplicates are re-duplicated. If using regions, the memory used by the old table is lost until region deletion. */ HASH_FUNC_INLINE void hashset_rehash(hashset_table ht, hash_fn hash, keyeq_fn cmp) { #ifdef DEBUG // printf("Rehash table size=%ld, used=%ld\n", ht->size, ht->used); #endif unsigned long old_table_size = hashset_table_capacity(ht); hash_key *old_table = ht->table; hashset_init_size_pow2(ht, ht->used*2); #if HASHSET_TABLE_SUPPORT_REGION if (!ht->r) { ht->table = xcalloc(hashset_table_capacity(ht), sizeof(hash_key)); } else { ht->table = rarrayalloc(ht->r, hashset_table_capacity(ht), hash_key); } #else ht->table = xcalloc(hashset_table_capacity(ht), sizeof(hash_key)); #endif size_t i; for (i = 0; i < old_table_size; i++) { hash_key k = old_table[i]; if (k == HASHSET_TOMBSTONE) { ht->used -= 1; continue; } if (k != NULL) { // For performance, we don't check for duplicates; use // hashset_rehash_check() if you want that. hashset_table_insert_internal(ht, hash, cmp, k); } } #if HASHSET_TABLE_SUPPORT_REGION if (!ht->r) { free(old_table); } #else free(old_table); #endif }
HASH_FUNC_INLINE void hashset_table_convert_to_hash_mode(hashset_table ht, hash_fn hash, keyeq_fn cmp) { // array mode hash_key *old_table = ht->table; size_t old_table_size = ht->used; // add 1 since we're about to insert after this; don't multiply by 2 because // the whole point of array mode is to save memory! hashset_init_size_pow2(ht, ht->used+1); #if HASHSET_TABLE_SUPPORT_REGION if (!ht->r) { ht->table = xcalloc(hashset_table_capacity(ht), sizeof(hash_key)); } else { ht->table = rarrayalloc(ht->r, hashset_table_capacity(ht), hash_key); } #else ht->table = xcalloc(hashset_table_capacity(ht), sizeof(hash_key)); #endif size_t i; for (i = 0; i < old_table_size; i++) { hash_key k = old_table[i]; assert(k != NULL && k != HASHSET_TOMBSTONE); hashset_table_insert_internal(ht, hash, cmp, k); } // ht->used doesn't change. #if HASHSET_TABLE_SUPPORT_REGION if (!ht->r) { free(old_table); } #else free(old_table); #endif }
/* Reinsert all elements, checking for duplicates */ HASH_FUNC_INLINE void hashset_rehash_check(hashset_table ht, hash_fn hash, keyeq_fn cmp) { unsigned long old_table_size = hashset_table_capacity(ht); hash_key *old_table = ht->table; hashset_init_size_pow2(ht, ht->used*2); #if HASHSET_TABLE_SUPPORT_REGION if (!ht->r) { ht->table = xcalloc(hashset_table_capacity(ht), sizeof(hash_key)); } else { ht->table = rarrayalloc(ht->r, hashset_table_capacity(ht), hash_key); } #else ht->table = xcalloc(hashset_table_capacity(ht), sizeof(hash_key)); #endif size_t i; for (i = 0; i < old_table_size; i++) { hash_key k = old_table[i]; if (k == HASHSET_TOMBSTONE) { ht->used -= 1; continue; } if (k != NULL) { // inline the following but without hash check: // hashset_table_insert(ht, key); size_t hashVal = hashset_find_bucket(ht, hash, k); size_t curIndex = hashVal; size_t i = 0; while (1) { hash_key key = ht->table[curIndex]; if (key == NULL) { ht->table[curIndex] = k; break; } // no reason for the table we're creating to have tombstones! assert(key != HASHSET_TOMBSTONE); if (key == k || cmp(k, key)) { // duplicate! ht->used--; break; } ++i; curIndex = hashset_probe(ht, hashVal, i); assert(i < hashset_table_capacity(ht)); assert(curIndex != hashVal); } } } #if HASHSET_TABLE_SUPPORT_REGION if (!ht->r) { free(old_table); } #else free(old_table); #endif }